The following is intended to outline my experience and exposure to PeopleSoft’s Technologies. This is not a training document. References in this blog have been compiled from various sources like Oracle webcasts, blogs, and prototypes that I have developed over time.
Monday, January 6, 2025
Taleo Web API - managing user groups in a user profile
Thursday, October 17, 2024
Uploading files to SharePoint Online
Here are the steps to upload files to SharePoint Online using PeopleSoft's services/service operations.
I am running PeopleTools 8.61.x and there are some properties that are discussed below that are only available in the latest tools release.
At a high level there are three steps
1. Generate Access Token
2. Using the access token generate Form Digest
3. Finally using both the access token and form digest upload file to SPO.
Service and Service Operation build
1. Created a Document Template (N_SPO_URI_TEMPLATE) with the following primitives defined as text.
TenantID, TenantName, SiteName, SPOFolder and FileName
2. Defined two non-rowset based messages - N_SPO_REQUEST and N_SPO_RESPONSE
3. Created a consumer REST service called as N_SPO.
4. Created three service operations all with REST method as POST -
N_SPO_ACCESSTOKEN_POST, N_SPO_FORMDIGEST_POST and N_SPO_UPLOADFILES_POST
For the service operation N_SPO_ACCESSTOKEN_POST the REST base URL is
https://accounts.accesscontrol.windows.net/ and template is {TenantID}/tokens/OAuth/2
For the service operation N_SPO_FORMDIGEST_POST the REST base URL is https:// and
template is {TenantName}.sharepoint.com/sites/{SiteName}/_api/ContextInfo as we cannot provide any variables in the base URL.
Finally for the N_SPO_UPLOADFILES_POST service operation, the REST base URL is https:// and template is {TenantName}.sharepoint.com/sites/{SiteName}/_api/web/GetFolderByServerRelativeURL('/sites/{SiteName}/{SPOFolder}/')/Files/add(url='{FileName}',overwrite=true)
All other settings are default settings.
5. Updated the integrationGateway.properties file as follows - (this parameter may be available only in the latest tools release)
ig.UseDomainName.ExternalOperationNames=N_SPO_FORMDIGEST.v1,N_SPO_UPLOADFILES.v1
Had to provide external operational service name for these two. The first one related to access token generation worked without having to define it here.
6. For the SPO site to which I want to upload the file, I need a Client ID and Secret, which is kind of like the user ID/password to make the connection. SharePoint admin can generate this. Value for &ApplicationID, &TenantID also provided by SharePoint admin. Value for variables like &TenantName, &SiteName, &SPOFolder derived by parsing the SPO URL to which I had to upload the file. &attachFileName is derived from the complete file path of the file to be uploaded.
7. Now comes the peoplecode part to invoke these service operations.
&Doc_Tmpl = &reqMsg.GetURIDocument();
&COM_Tmpl = &Doc_Tmpl.DocumentElement;
&reqMsg.URIResourceIndex = 1;
&COM_Tmpl.GetPropertyByName("TenantID").Value = &TenantID;
&bRet = &reqMsg.SetContentString("grant_type=client_credentials&client_id=" | EncodeURLForQueryString(&ClientID | "@" | &TenantID) | "&client_secret=" | EncodeURLForQueryString(&ClientSecret) | "&resource=" | EncodeURLForQueryString(&ApplicationID | "/" | &TenantName | ".sharepoint.com@" | &TenantID));
&bRet = &reqMsg.IBInfo.IBConnectorInfo.AddConnectorProperties("Disable_URLEncodingBody", "True", %HttpProperty);
&sResp = &respMsg.GenXMLString();
Sunday, August 2, 2020
PeopleSoft Reporting Web Services
{OwnerType}/{QueryName}/{OutResultType}/{OutResultFormat}?isconnectedquery=
{isConnectedQuery}&maxrows={MaxRow}&prompt_psqueryname={Prompt_PSQueryName*}
&prompt_uniquepromptname={Prompt_UniquePromptName*}&prompt_fieldvalue=
{Prompt_FieldValue*}&filterfields={FilterFields*}&json_resp={json_response}
Tuesday, April 21, 2020
Creating JSON request for REST web services
The request that I have to generate is in the following form.
[
{
"attrib1":"value1",
"attrib2":"value2",
"attrib3":{
"attrib3_1":"values3_1",
"attrib3_2":"values3_2",
"attrib3_3":"values3_3",
"attrib3_4":"values3_4"
}
}
]
I am running PT 8.57.x and at this time its not possible to build a document with the root node as an array as shown in the example below. Also I have nested compounds which is also a challenge, the parent compound does not have a label where as the child does.
So to build something like above I am using the CreateJsonBuilder API provided by PeopleSoft.
Local JsonBuilder &jbldr = CreateJsonBuilder();
Local JsonArray &jArray;
Local message &request, &response;
Local boolean &bRet;
&jbldr.StartObject(""); /* no label */
&jbldr.AddProperty("attrib1", "value1");
&jbldr.AddProperty("attrib2", "value2");
&jbldr.StartObject("attrib3"); /* need a label */
&jbldr.AddProperty("attrib3_1", "value3_1");
&jbldr.AddProperty("attrib3_2", "value3_2");
&jbldr.AddProperty("attrib3_3", "value3_3");
&jbldr.AddProperty("attrib3_4", "value3_4");
&jbldr.EndObject("attrib3"); /* closing out the compound or JSONObject */
&jbldr.EndObject("");
&jbldr.EndArray("");
/* this will return the array just like what I want */
&jArray = &jbldr.GetRootNode().GetJsonObject().GetJsonArray("");
&json = &jArray.ToString();
Created a basic non-rowset based message and assigned that as the request message in my service operation. Use this method to set the content for the message segment for a non-rowset-based message only.
&bRet = &request.SetContentString(&json);
&response = %IntBroker.SyncRequest(&request);
That's it, works like a charm.
Sunday, March 8, 2020
Event Mapping (managing customizations)
Following is what I have tried in PeopleTools 8.56.07 and 8.57.08 on HCM 9.2 (PUM 31 and beyond). For this POC I am going to call my custom application package peoplecode on SavePostChange event on the DEPARTMENT_TBL component to perform something like sending out a notification. In the absence of the event mapping functionality I would have written this code in SavePostChange event of the DEPARTMENT_TBL component thus customizing the delivered object.
So, step one is to build the application package peoplecode. Import of PT_RCF:ServiceInterface is the key. The class name can be anything but the method name has to be "Execute".
import PT_RCF:ServiceInterface;
class FoundationDataNotify extends PT_RCF:ServiceInterface
method Execute();
end-class;
method Execute
/+ Extends/implements PT_RCF:ServiceInterface.execute +/
/* custom logic to send out notification goes here */
end-method;
Once the package is developed navigate to PeopleTools > Portal > Related Content Service > Define Related Content Service. Create a new definition and select "URL Type" as application class and then provide the package details. For this POC I selected "Public Access" under security options. Save the service definition.
Then navigate to PeopleTools > Portal > Related Content Service > Manage Related Content Service, Event Mapping tab. Click on the "Map Application Classes to Component Events" link and then navigate the portal tree to find the component on which this event would be based on or associated with. In my case it would be the department table component located under Set Up HCM > Foundation Tables > Organization > Departments.
Under "Component Level Event Mapping" section, select "enable" check-box, event name would be SavePostChange and select the Service ID created in the earlier step. Set sequence number to 1 and processing sequence as "Post Process". Save the page and that is it.
Navigate to the department component make a change and save the page and verify that the custom application package peoplecode fires.
The PeopleCode Editor provides an Event Mapping button in the dynamic Application Designer toolbar. For an application developer, the Event Mapping button is a visual indicator of custom PeopleCode programs mapped to events of a component, component page, component record, or component record field. This button is not available for page level event mapping.
So opened component peoplecode of component DEPARTMENT_TBL and clicked on the button to produce the following output.
Right-clicking on the application package code and selecting "Event Mapping References" in the pop-up menu as shown below should display the component but that did not work.
"Event Mapping References" tab is empty as shown below.
So I guess this might work in future releases or maybe I don't have something configured correctly for this to work.
Wednesday, April 4, 2018
PeopleSoft web service response namespace issue
Request
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing/" xmlns:xsd="http://www.w3.org/2001/XMLSchema/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance/">
<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
</soapenv:Header>
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<HelloWorld xmlns="http://xmlns.oracle.com/Enterprise/Tools/schemas/HELLOWORLD.V1"></HelloWorld>
</soapenv:Body>
</soapenv:Envelope>
Response via PeopleSoft SOAP message template
<soapenv:Envelope xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing/" xmlns:xsd="http://www.w3.org/2001/XMLSchema/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance/">
<soapenv:Header xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
</soapenv:Header>
<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<HelloWorldResponse xmlns="http://xmlns.oracle.com/Enterprise/Tools/schemas/HELLOWORLDRESPONSE.V1">
<HelloWorldResult>XYZ</HelloWorldResult>
</HelloWorldResponse>
</soapenv:Body>
</soapenv:Envelope>
Actual response via SOAPUI or Postman
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<HelloWorldResponse xmlns="http://peoplesoft.com/HelloWorldResponseResponse">
<HelloWorldResult>Success</HelloWorldResult>
</HelloWorldResponse>
</soapenv:Body>
</soapenv:Envelope>
As you see the the problem is the namespace value returned for the root tag "HelloWorldResponse".
<HelloWorldResponse xmlns="http://peoplesoft.com/HelloWorldResponseResponse">
PeopleSoft puts the default value (not sure where this is stored)
http://peoplesoft.com/HelloWorldResponseResponse
instead of what is defined in the WSDL which is
http://xmlns.oracle.com/Enterprise/Tools/schemas/HELLOWORLDRESPONSE.V1
I have a very basic synchronous service operation, with a request and response message and the handler OnRequest peoplecode is doing all the work.
Following was my application package peoplecode initially.
&response = CreateMessage(Operation.HELLOWORLD_SVCOP, %IntBroker_Response);
&xmldata = "<?xml version='1.0'?><HelloWorldResponse/>";
&xmlresponsedoc = CreateXmlDoc(&xmldata);
&HWResponseNode = &xmlNode.AddElement("HelloWorldResult");
&HWResponseNode.NodeValue = "Success";
&response.SetXmlDoc(&xmlresponsedoc);
Return &response;
So when creating the XmlDoc I was not specifying any namespace and I was hoping PeopleSoft will add it based on the schema definition.
Instead following is what I had to do to correct the issue. (only displaying the change, no change to rest of the code)
&xmlresponsedoc = CreateXmlDoc("");
&docTypeNode = &xmlresponsedoc.CreateDocumentType("", "", "");
&rootNode = &xmlresponsedoc.CreateDocumentElement("HelloWorldResponse", "http://xmlns.oracle.com/Enterprise/Tools/schemas/HELLOWORLDRESSPONSE.V1", &docTypeNode);
&xmlNode = &xmlresponsedoc.DocumentElement;
So I have to use the CreateDocumentElement method of CreateXmlDoc in order to define the namespace. In order to use this method I had to first initialize the &docTypeNode variable by using the CreateDocumentType method.
After making the above change the response comes back correctly.
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<HelloWorldResponse xmlns="http://xmlns.oracle.com/Enterprise/Tools/schemas/HELLOWORLDRESSPONSE.V1">
<HelloWorldResult>Success</HelloWorldResult>
</HelloWorldResponse>
</soapenv:Body>
</soapenv:Envelope>
Saturday, March 26, 2016
Sending and Receiving MTOM-encoded binary data
&request = CreateMessage(Operation.SEND_OPERATION);
&MTOMFile = GetFile("C:\temp\document.xml", "R", %FilePath_Absolute);
&request.CreateNextSegment();
If (&request.SetContentString(&theBase64encodedString)) Then
&response = %IntBroker.SyncRequest(&request);