Tuesday, September 17, 2013

Deploying Multiple PIA's on the Same Web Server

Background

In many PeopleSoft server environments, it makes sense to deploy multiple PIA's on the same physical (or virtual) web servers, in order to reduce the number of servers that need to managed, patched, and otherwise maintained.

One way to do this would be to deploy each PIA onto separate ports.  So, your first PIA could use ports 80/443 for HTTP/HTTPS traffic, but your additional PIA's would need to be deployed to non-standard ports, such as 8000/8001 and so on.

Unfortunately, this can be problematic (especially if these are production environments) as some of your users may be on networks where the firewalls block HTTP and HTTPS traffic on non-standard ports.  It can also be confusing to users to have to specify a port in a URL.

Example Case

Suppose that you have a physical (or virtual) web server with one network interface (eth0) mapped to a single IP address (10.1.1.100), with a DNS alias of "peoplesoft.myschool.edu".

For each of 3 PIA's deployed on that server (each deployed using unique HTTPS ports), the URL for each environment would be:
  • Portal:  https://peoplesoft.myschool.edu/
  • Student:  https://peoplesoft.myschool.edu:8001/
  • Financials:  https://peoplesoft.myschool.edu:8003/

Alternative Approach using IP Aliasing

An alternative to the scenario described above is to use IP aliasing to map multiple IP addresses to your web server's network interface card, and then to configure WebLogic so that each PIA maps to a specific IP address.

Here is a link to an excellent article on how to create virtual interfaces on a Linux server, and assign each virtual interface its own unique IP address:


Suppose now that, after following the steps in the article above, you now have the following network interfaces mapped to the following IP addresses and DNS aliases on your web server:

Network InterfaceIP AddressDNS Alias
eth010.1.1.100peoplesoft.myschool.edu
eth0:110.1.1.101portal.myschool.edu
eth0:210.1.1.102student.myschool.edu
eth0:310.1.1.103financials.myschool.edu

Configuring WebLogic

On your web server, you can now deploy your first PIA as normal using the installation wizard installed in your application's PS_HOME directory, leaving the PIA on ports 80 and 443.  Suppose that we are going to deploy the PIA for Portal first.

After you've deployed and booted the PIA, access the WebLogic Console at:
https://peoplesoft.myschool.edu/console

  1. Login to the console using the "system" account.
  2. In the left pane, expand "Environment" then select "Servers".
  3. In the right pane, select "PIA(admin)".
  4. In the upper-left corner, click "Lock & Edit" to unlock the interface and allow for changes.
  5. In the "Listen Address" field, specify the new IP Address, in this case:  10.1.1.101
  6. Save and Activate the changes.
After configuring WebLogic, you need to shutdown the PIA and make a change to the following file:

PIA_HOME/webserv/<domain>/bin/setEnv.sh

Update the "ADMINSERVER_HOSTNAME" parameter from:
  • ADMINSERVER_HOSTNAME=peoplesoft.myschool.edu
    to
  • ADMINSERVER_HOSTNAME=portal.myschool.edu
Restart your PIA, and you should now be able to access it via its new URL (and furthermore, you should no longer have a WebLogic console or PIA listening on the old server URL).

Summary

Rinse and repeat for each of the remaining PIA's, and you should now have one web server with multiple PIA's, each being served on standard HTTP ports via unique IP addresses and DNS aliases.  For our example, we should now have:
  • Portal:  https://portal.myschool.edu/
  • Student:  https://student.myschool.edu/
  • Financials:  https://financials.myschool.edu/

Friday, July 5, 2013

PeopleSoft Custom Run Control Pages

Every PeopleSoft developer will eventually need to create an SQR or App Engine process which can be executed from a Run Control page with custom parameters.  Here is a quick cheat sheet for creating the Run Control page, and how to retrieve the Run Control parameters from within an SQR or App Engine program.

Creating a Custom Run Control Page

This step is the same regardless of whether you will ultimately use the Run Control page with an SQR or App Engine program.  Do the following in Application Designer:

Creating the Run Control Record
  1. Open Record definition PRCSRUNCNTL and make a copy by using "Save As" and giving the Record a new name (for example, "MY_PRCS_RC").
    • When prompted to save a copy of the PeopleCode associated with PRCSRUNCNTL, choose "Yes".
  2. Update the following Record PeopleCode definitions on your new Run Control Record, replacing references to PRCSRUNCNTL with your custom Run Control Record name:
    • OPRID.RowInit
    • RUN_CNTL_ID.SaveEdit
    • LANGUAGE_CD.RowInit
    • LANGUAGE_OPTION.FieldChange
  3. Add any desired additional fields to your custom Run Control Record (for example, "STRM").
  4. Build the Record.
Creating the Run Control Page
  1. Create a new Page definition and save it with a new name (for example, "MY_PRCS_RC").
  2. Insert a Subpage onto your page, and choose "PRCSRUNCNTL_SBP".
    • On the Insert Subpage dialog, change the "Subpage Record Name Substitution" value to your custom Run Control Record (i.e., "MY_PRCS_RC").
  3. Drag your custom Run Control fields onto the Page (i.e., "STRM").
    • Note:  You do not need to add the default Run Control fields onto the page (OPRID, RUN_CNTL_ID, etc).  These values will be populated automatically through PeopleCode.
Creating the Run Control Component
  1. Create a new Component definition.
  2. Set the Component Search Record to your custom Run Control Record (i.e., "MY_PRCS_RC").
  3. Save the Component with a new name (for example, "My PRCS_RC").
  4. Register your Component using the Registration Wizard (Tools > Register Component).
Creating the Process Definition

In this step, we create a Process definition entry for our SQR or App Engine program, and associate the process definition with our custom Run Control component.
  1. In the PIA, navigate to:  PeopleTools, Process Scheduler, Processes
  2. Click the "Add a New Value" tab and enter the Process Type and Process Name.
    • Note:  The Process Name must exactly match the name of your App Engine program, or in the case of an SQR, must exactly match the file name of your SQR file (without the ".sqr" extension suffix).
  3. On the "Process Definition Options" tab:
    1. Add your custom Run Control Component under the "Component" grid area on the bottom left of the page.
    2. Add whichever Process Groups are appropriate to grant process security to the appropriate persons.
You should now be able to navigate to your Run Control page in the PIA, fill out the Run Control parameters, and schedule your process to run on the Process Scheduler.

Retrieving Run Control Parameters

Now that we have a way to provide Run Control parameters via a Run Control page, we need to be able retrieve and use those parameters from within a program.  This part of the process is different for App Engine and SQR programs.

Run Control Parameters in App Engine Programs

The standard way to store Run Control parameters in an App Engine program is to use a State Record.  To set up the State Record:
  1. A requirement in naming State Records is that they must have "_AET" as their suffix.  Make a copy of your Run Control record, giving it a new name (for example, "MY_PRCS_AET").
    1. When prompted to save a copy of the PeopleCode associated with the original Record, choose "No".
  2. Change the Record Type from "SQL Table" to "Derived/Work".  A Derived/Work Record doesn't persist any data to the database.  Instead, it acts as an in-memory data structure while the program is running on the Process Scheduler.
  3. Open your App Engine program, and navigate to: File, Definition Properties
  4. On the "State Records" tab search for your State Record definition, and click the "Add" button to move the definition from the left-hand panel to the right-hand panel.
Now that the State Record is created and associated with the App Engine program, we need to populate it.
  1. Add an SQL step as the first step in the App Engine program.  To populate the State Record with values from the Run Control Record, we use the Meta-SQL %Select function.  For example:

    %Select(OPRID, RUN_CNTL_ID, LANGUAGE_CD, LANGUAGE_OPTION, STRM)
    FROM PS_MY_PRCS_RC
    WHERE OPRID = %OperatorId
    AND RUN_CNTL_ID = %RunControl
Now that the Run Control parameters have been stored into the State Record, they can be referenced from PeopleCode via the State Record.  For example, the following would write the STRM Run Control parameter value to the message log:
MessageBox(0, "", 0 , 0, "STRM=" | MY_PRCS_AET.STRM);

Run Control Parameters in SQR Programs

In an SQR program, there are no State Records.  Typically, Run Control parameter values are simply stored using variables.  The following steps will allow you to retrieve the Run Control parameters in an SQR program.  Please refer to the SQR code sample following the step descriptions to see this in action.
  1. Make sure you have added an include statement to include "stdapi.sqc" in your SQR program.  This delivered SQC provides routines which update the Process Scheduler with process status, as well as facilitating the retrieval of the Operator ID and Run Control ID values for the currently running SQR process instance.
  2. Ensure that the very first step of your program is to run the "Stdapi-Init" procedure, and that the very last step of your program is to run the "Stdapi-Term" procedure.
  3. Create a procedure to retrieve Run Control parameters, referencing the Operator ID and Run Control ID as "$prcs_oprid" and "$prcs_run_cntl_id" variables respectively.  The "Stdapi-Init" procedure initializes these variables.
The following code sample illustrates the steps above:

! Program Name:  MYPRCS.SQR
! Program Descr: My SQR Process
! Author:        Mark Stramaglia

#include 'stdapi.sqc'   ! Update status and get system parameters

BEGIN-PROGRAM

  DO Stdapi-Init
  DO Get-Run-Control-Parameters
  DO Main-Process
  DO Stdapi-Term

END-PROGRAM

BEGIN-PROCEDURE Get-Run-Control-Paramters

  BEGIN-SELECT
  RC.STRM
    LET $strm = &RC.STRM
  FROM PS_MY_PRCS_RC RC
  WHERE RC.OPRID = $prcs_oprid
  AND RC.RUN_CNTL_ID = $prcs_run_cntl_id
  END-SELECT

END-PROCEDURE Get-Run-Control-Parameters

BEGIN-PROCEDURE Main-Process

  SHOW 'STRM=' $strm

END-PROCEDURE Main-Process


Thursday, May 30, 2013

Showing/Hiding Fields using PeopleCode

When developing pages in PeopleTools, there are times when you might want to conditionally show or hide a group of fields based on some logic.  It is actually very simple to do - here are the steps:

Note:  This works best if you think of your page as one long, single column, with fields grouped all the way horizontally across the screen.  If you have multiple "columns" of content across the screen, PeopleTools may not be able to adjust the layout appropriately.

For our example, let's suppose that you have a page with a group box containing employee info fields, as well as a button that you'd like to use to show or hide the fields.  Also, when the group box is hidden, we want the layout to automatically adjust itself to fill in the white space where the group box used to be.

My Info Group Box Expanded


My Info Group Box Hidden and Layout Adjusted


To accomplish this, perform the following steps:

Set Page Properties

  1. Right-click on the Page and choose "Page Properties".
  2. On the "Use" tab, check the box for "Adjust Layout for Hidden Fields".

Set Group Box Properties

  1. Right-click on the Group Box and choose "Page Field Properties".
  2. On the "Record" tab, ensure that the Group Box has a Record and Field name associated with it.  It is usually best to associate it with a Work Record:

  3. On the "Label" tab, check the box for "Adjust Layout for Hidden Fields".
  4. On the "Use" tab, check the box for "Hide all Fields when Group Box Hidden".

Add "Show/Hide" Button PeopleCode

  1. Right-click on your button and choose "View Record PeopleCode".
  2. Choose the "FieldEdit" event and add the following PeopleCode:
If MY_WORK_RECORD.GROUP_BOX_1.Visible = True Then
  MY_WORK_RECORD.GROUP_BOX_1.Visible = False;
Else
  MY_WORK_RECORD.GROUP_BOX_1.Visible = True;
End-If;

Automatically Hide on Page Load

If you'd like for the group box to default to being hidden when the page first loads, you can add Page Activate PeopleCode to accomplish this.
  1. Right-click on the Page and choose "View Page PeopleCode".
  2. You will default to the "Activate" event.  Add the following PeopleCode:
MY_WORK_RECORD.GROUP_BOX_1.Visible = False;

Summary

That's it! In just a few easy steps, we've created the ability to toggle the visibility of a group of fields. This technique can be expanded upon to conditionally show or hide groups of fields depending on a variety of conditions.

Wednesday, August 22, 2012

PeopleSoft SOAP Integration

Although web services can certainly be more complex than other integration methods, there is a lot of horsepower and potential benefit from a web services approach, especially when there is a requirement for near real-time integration.

Following is an overview of how to consume a SOAP web service in PeopleSoft, call the web service from PeopleCode, and parse the response message.

Overview of SOAP


SOAP is a lightweight protocol intended for the exchange of structured information between distributed systems.  SOAP uses XML to provide an extensible and flexible messaging framework.  A SOAP message consists of three parts:

  • Envelope: This required element identifies the XML document as a SOAP message.
  • Header:  This optional element contains application-specific information about the SOAP message.  If the Header element exists, it must be the first child element of the Envelope element.
  • Body:  This required element contains the actual message information intended for the recipient.
SOAP messages can be transported via various transport protocols, but the most common protocol for use over the Internet is HTTP.

Web Services Description Language (WSDL)


WSDL is an XML document used to describe a web service, including the location of the service and the available operations for the service.

Example Web Service


For the purpose of this example, assume that you have a third-party, web-based system which houses data on new applicants who have applied online, and you want to import this data into PeopleSoft via a "GetApplicants" web service provided by the third-party.

Our example web service will accept a date and an API key, and will return a response message with all of the applications for that date.  A sample request message is structured as follows:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
  <soap:Body>
    <GetApplicants xmlns="http://www.example.com/">
      <APIKey>123456789</APIKey>
      <Date>2012-04-14</Date>
    </GetApplicants>
  </soap:Body>
</soap:Envelope>

The response message will return the id, name, birthdate, and declared major for each applicant, as shown in the following example:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope>
  <soap:Body>
    <GetApplicantsResponse xmlns="http://www.example.com/">
      <Applicant>
        <Id>12345</Id>
        <Name>Smith, John</Name>
        <Birthdate>1982-08-25</Birthdate>
        <Major>Computer Science</Major>
      </Applicant>
      <Applicant>
        <Id>12346</Id>
        <Name>Jones, Sally</Name>
        <Birthdate>1983-11-04</Birthdate>
        <Major>Engineering</Major>
      </Applicant>
    </GetApplicantsResponse>
  </soap:Body>
</soap:Envelope>

PeopleSoft Consume Web Service Wizard


Oracle has delivered a wizard which will interrogate the WSDL URL for a web service, and then build the appropriate PeopleSoft components within Integration Broker for using that web service.  To set up the "GetApplicants" web service using the Consume Web Service Wizard:
  1. Navigate to: PeopleTools > Integration Broker > Web Services > Consume Web Service
  2. Select WSDL Source:
    1. Choose "WSDL URL" and paste in: "http://www.example.com/webservices.wsdl"
    2. Click "Next".
  3. Select the appropriate Service and click "Next".
  4. Select Service Ports: Check the row for "SERVICESOAP" and click "Next".
  5. Select Service Operations: Check the row for "GetApplicants" and click "Next".
  6. Rename Operation Messages: Click "Next".
  7. Select the Receiver Node: Click "Finish" to accept "WSDL_NODE" as the default node.
This process will create a Service Operation named "GetApplicants", as well as the Request and Response Message definitions associated with the Service Operation.

Invoking a Synchronous Web Service from PeopleCode


From here, we can invoke the Service Operation from PeopleCode using delivered Integration Broker PeopleCode libraries.  The PeopleCode is actually very simple:

import PS_PT:Integration:*;
&reqStr = "<Request XML from above...>";
/* (1) Create Request Message from Service Operation */
&reqMsg = CreateMessage(@("Operation.GetApplicants"));
/* (2) Create XML Document from Request XML Text String */
&inXml = CreateXmlDoc(&reqStr);
/* (3) Set XML Document on Request Message */
&reqMsg.SetXmlDoc(&inXml);
/* (4) Invoke SyncRequest for Request Message */
&respMsg = %IntBroker.SyncRequest(&reqMsg);
/* (5) Get XML Document from Response Message */
&outXml = &respMsg.GetXmlDoc();

If we wanted to print the raw XML response to a log or to a text area on the screen, we can return a formatted XML string using the following PeopleCode:

/* (6) Display Returned XML Text String */
&outXml.GenFormattedXmlString();

You've successfully made the round-trip from PeopleSoft to the third-party web service and back.  You now have response data which can be manipulated according to your business need.

Parsing the Response Data


The last piece is to deconstruct the XML response so that data can be loaded appropriately into your system.  The following PeopleCode will isolate the Applicants from the XML response and print the Id and Name for each applicant to a popup Message:

/* Pull out all of the Applicant elements into an array */
Local array of XmlNode &applicantList;
& applicantList = &outXml.DocumentElement.GetElementsByTagName("Applicant");
  
/* Print the number of Applicants to a Message */
MessageBox(%MsgStyle_OK, " ", 0, 0, "Applicants: " | &applicantList .Len);

/* Iterate over the Applicants and print the Id and Name for each */
&i = 0;
While & applicantList.Next(&i)
    MessageBox(%MsgStyle_OK, " ", 0, 0, " Applicant " | &i | ": Id(" | &applicantList.Get(&i).GetChildNode(1).NodeValue | ") Name(" | &applicantList.Get(&i).GetChildNode(2).NodeValue | ")");
End-While;

For our example Response message from above, which had two Applicants, this PeopleCode would fire two Message popups, with the following text in each:

Applicant 1: Id(12345) Name(Smith, John)
Applicant 2: Id(12346) Name(Jones, Sally)

Now that we know how to get the actual data values, we have all of the pieces we need to evaluate and take action on the response data.  From here, a common exercise would be to load a staging table or possibly load a delivered Component via a Component Interface.

Friday, August 10, 2012

Selecting Vertical Text using Notepad++

Ever had a log file or data output file, and you wanted to cut a vertical section out of the file?  You could accomplish that with some sub-string functions, or you could use this nifty feature of Notepad++:

Open your text file in Notepad++:
Fig 1. Log file example in Notepad++



















Supposing that we wanted to only select the IP addresses on the left side of the log file, we can press and hold the ALT key, and then highlight the section we want:

Fig 2. Selecting a vertical section of text using ALT key



















From here, you can delete, cut, or copy the selection just like you would normally.

For more information, check out:  http://notepad-plus-plus.org/