A Complete PeopleSoft REST Web Service Example
By Chris Malek | Tue, Aug 2, 2016
In this article we will create a simple REST service in PeopleSoft using PeopleTools 8.55. It will have the following characteristics.
- It will be an simple “echo” service that echoes back what was given in the URL query path.
- We will return XML because JSON support in PeopleSoft is a bit painful at the time of writing even on the latest tools release.
- See the “JSON” Tagged Articles for more information
- We will first use no authentication then show how we can use “basic authentication” which is tied to an OPRID.
This article is similar to the Synchronous HTTP Post to PeopleSoft Integration Broker using Python article I wrote. However, in that article we were posting to the HttpListeningConnector
endpoint. The HttpListeningConnector accepts everything as an HTTP POST method. In REST, you use different HTTP verbs/methods to describe what your intended operation is. In this example, we will be “getting” data from PeopleSoft (sort of) so we will be using an HTTP GET operation.
The steps required to create an HTTP GET REST web service are the following:
- Build a “Template”
document
object. This is adocument
that will allow you to retrieve the URL parameters matched. These could be in thepath
or thequery
portion of the URL. - Create a new
message
that links the templatedocument
to a message. - Create your response
message
which structures your response. - Create a REST
Service
- Create your
Service Operation
- Create your service operation handler application package. This is the PeopleCode that will trigger and will respond to the incoming request and return something useful to the client.
- Link your service operation handler to the application class.
- Setup the security of the web service.
- Test
The final URL allowed for the service will be either:
https://ibdev.cedarhillsgroup.com/PSIGW/RESTListeningConnector/PSFT_HR/C_REST_ECHO.v1/echo/the-parameter-we-will-echo
https://ibdev.cedarhillsgroup.com/PSIGW/RESTListeningConnector/PSFT_HR/C_REST_ECHO.v1/echo/?value-to-echo=the-parameter-we-will-echo
There are several pieces to the URL:
- ibdev.cedarhillsgroup.com - This is the hostname that is not accessible to the internet (sorry)
- PSIGW - Standard Integration Gateway path
- RESTListeningConnector - REST connector that accepts REST web services.
- PSFT_HR - The node name that I am directing this service to. This will differ based on your installation.
- C_REST_ECHO.v1 - The service operation name and version we will create
- echo - A URL path we defined in the service operation.
- the-parameter-we-will-echo - This is the value that will be picked up at run time that the client will send.
- We will be able to pass this in the URL
path
or in thequery
portion of the URL depending on what URL the client uses.
- We will be able to pass this in the URL
In REST, the URL structure matters tremendously. You need to think about your URL structure prior to implementing. Our example service here is trivial so I put zero thought into it.
Building the Template Document
You first have to build a document
object that will capture all the parameters that may be sent inbound to your web service. In this simple example, we will only have one parameter. There are some rules about a document that is used as a template.
This document can only contain primitive elements and collection elements. The document cannot contain any imports (compounds) or compound elements. – 8.55 PeopleBooks
Our web service will be really simple to start off with and only have one parameter. We will call it parameter1
.
We build a document that looks like this.
Build New Message linked to Template Document
Now we have to build a message
object based on the document template we built above. I have no idea why you can’t just use the document itself. However, for some unknown reason PeopleTools requires that you create a message object.
You can do this at:
- PeopleTools > Integration Broker > Integration Setup > Messages
- Choose Add New Message
- Choose Type = “Document”
- Enter in your desired message name and then input the package document package and name in the boxes.
The end result is a message that basically shows the document. I told you it was useless.
Creating the Response Message
We now need to create a message
that will be used to return the XML from the service. In this case, we will have our PeopleCode actually create the XML dynamically during processing. So we will create a nonrowset-based
message. This is a type of message where your code is responsible for generating the XML. It also does not generate any schemas for you automatically. You would have to add that manually.
Creating the Service
Now we need to create a REST Service
which will “group” or “own” our service operation.
Creating the Service Operation
The next step is to create the service operation. You can do this from the service page. We will be providing a web service that uses the “GET” HTTP method. So we need to specify not only the desired Service Operation name but also the method.
Now that the service was created, you will see that the actual service operation name was the name we ask for but it also appended on “_GET” at the end. This will map to the HTTP method.
I highlighted a few things to make note of:
- We are going to put in 2 different “URI” syntaxes where this service can be called.
- You will see that we have some curly braces in the URI grid. Those are variables that will be substituted at run-time into our “document template” and our handler code can pick them up. You can only put variable names in the URI section that match data elements in your “document template”. This really confused me when I first started to look at PeopleSoft REST services. If this does not make sense now look closely at the URI grid and the document template created above and look at the names specifically
parameter1
.
- You will see that we have some curly braces in the URI grid. Those are variables that will be substituted at run-time into our “document template” and our handler code can pick them up. You can only put variable names in the URI section that match data elements in your “document template”. This really confused me when I first started to look at PeopleSoft REST services. If this does not make sense now look closely at the URI grid and the document template created above and look at the names specifically
- We input the document template message name in the appropriate place and we also specified the return message.
- In our case we are returning XML, so that is chosen as the return content type.
- In the first iteration we will NOT have any authentication turned on to make testing easier.
For REST Service Operations, we have to maintain different service operations at the HTTP method level. So if we allowed an HTTP POST and/or DELETE operation we would have additional Service operations for those. This makes sense in the Service Operation Structure because those would probably accept different HTTP Bodies so you would potentially need a different set of message objects to represent those structures. A DELETE operation does not tend to have an HTTP Body. However, an HTTP POST always has an HTTP Body.
Creating the Service Operation Handler
Now we need to create an application package and class that will serve as our handler. This is the PeopleCode that will be triggered when a valid request comes into the integration broker. This code is responsible for returning data to the client.
Here is the full PeopleCode for the echo service that is in the C_REST_TEST.EchoHandler
Application Package.
import PS_PT:Integration:IRequestHandler;
class EchoHandler implements PS_PT:Integration:IRequestHandler
method EchoHandler();
method OnRequest(&_MSG As Message) Returns Message;
method OnError(&pRequestMsg As Message) Returns string;
end-class;
method EchoHandler
/* Nothing here for now */
end-method;
method OnRequest
/+ &_MSG as Message +/
/+ Returns Message +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnRequest +/
Local Message &request, &response;
&request = &_MSG;
Local Document &reqDOC;
&reqDOC = &request.GetURIDocument();
Local string &parm1;
&parm1 = &reqDOC.GetElement("parameter1").value;
&response = CreateMessage(Operation.C_REST_ECHO_GET, %IntBroker_Response);
Local XmlDoc &xmlout;
Local XmlNode &childNode;
&xmlout = CreateXmlDoc("<?xml version='1.0'?><response/>");
&childNode = &xmlout.DocumentElement.AddElement("parameter1").AddText(&parm1);
&response.SetXmlDoc(&xmlout);
Return &response;
end-method;
method OnError
/+ &pRequestMsg as Message +/
/+ Returns String +/
/+ Extends/implements PS_PT:Integration:IRequestHandler.OnError +/
Return "Error Occured";
end-method;
Let’s look at what is happening line by line in the OnRequest
method where all the magic happens.
The first section is basic setup.
We get the inbound message object, declare a document object. Then we use the GetURIDocument()
method on the request message to get to a document object.
Local Message &request, &response;
&request = &_MSG;
Local Document &reqDOC;
&reqDOC = &request.GetURIDocument();
So what &reqDOC
contain at this point? It is an in memory object that maps to a document that resembles our “document template”. The integration broker will generate a document and substitute any variables sent in the URL and put those values into the document for your code to parse. The integration broker looks at the URL paths and query strings and pulls the parameters out of the URL, populates a document and communicates it to your handler via the “URIDocument” on the request message. It is a bit confusing, I know.
The next two lines you see this:
Local string &parm1;
&parm1 = &reqDOC.GetElement("parameter1").value;
We declare a &parm1
string variable to store our parameter that the client wants echoed back. Then we get the parameter1
element from the document and store it in the string variable. It is important to note that this parameter1
reference exactly matches our document template that we created. Go back and look at that screenshot above if this does not make sense.
In the next few lines, we have code that is setting up the response message object and also generating an XML document that will wrap our response echo.
&response = CreateMessage(Operation.C_REST_ECHO_GET, %IntBroker_Response);
Local XmlDoc &xmlout;
Local XmlNode &childNode;
&xmlout = CreateXmlDoc("<?xml version='1.0'?><response/>");
Now the final few lines add an XML element to the response and push in the value that the client sent. It then pushes the XML into the response message and returns the message.
&childNode = &xmlout.DocumentElement.AddElement("parameter1").AddText(&parm1);
&response.SetXmlDoc(&xmlout);
Return &response;
That is all there is to the handler code for this service.
Linking the Handler Code to the Service Operation
Now we need to register our handler with the service operation. That is being done here:
Setting Up Service Operation Security
REST service operations are NOT tied to nodes or configured to have “routings” setup at a node level. In the current setup that we have so far, we have no authentication on the Service Operation. All PeopleCode has to run under some user context. So what user ID do we need to give permission to for this service operation? In the current configuration the node “ANONYMOUS” will be used. The user id that is attached to that node has to have security to this new service operation. There was no routing setup to this node but the broker uses this to find a default user if one is not provided.
You need to make sure your ANONYMOUS node has a valid user defined and that the user has access to the service operation via some permission list. I will not document that as it is pretty standard.
If you care to understand the ANONYMOUS node security a bit more you should take a look at the “Properly Securing the ANONYMOUS IB Node” article.
Testing the Echo Service
Now we should have everything setup to do a test.
I would highly recommend using Postman to do your HTTP testing. It is a wonderful piece of software that keeps improving.
I am actually going to document the testing here in HTTP syntax as it is language neutral.
The first test will be a simple example where we pass the parameter in the path. Notice the “how-are-you-today” at the end of the URL. This matches a pattern in the service operation URI grid where “how-are-you-today” will be substituted for “parameter1” at run time.
GET /PSIGW/RESTListeningConnector/PSFT_HR/C_REST_ECHO.v1/echo/how-are-you-today HTTP/1.1
Host: ibdev.cedarhillsgroup.com
The response we get back is this:
HTTP Headers:
Content-Encoding: gzip
Content-Length: 90
Content-Type: text/xml; encoding="UTF-8"
Date: Fri, 15 Jul 2016 05:32:30 GMT
The HTTP Body is:
<?xml version="1.0"?>
<response>
<parameter1>how-are-you-today</parameter1>
</response>
Let’s try the alternative method where we pass a query string key to “value-to-echo” which will match on the second URI in the service operation setup. We are passing a string of “surfing is fun” here that is URL encoded. Remember “%20” equals a space.
GET /PSIGW/RESTListeningConnector/PSFT_HR/C_REST_ECHO.v1/echo?value-to-echo=surfing%20is%20fun HTTP/1.1
Host: ibdev.cedarhillsgroup.com
The HTML Body we get back is:
<?xml version="1.0"?>
<response>
<parameter1>surfing is fun</parameter1>
</response>
Setup up Basic Authentication
On the service operation
if you change the “Req Verification” authentication to “Basic Authentication” now the request has to come with a special HTTP header with a value that is mapped to a PeopleSoft user ID and password.
- So let’s say that we create a new PeopleSoft OPRID of
REST_TESTER
and give it a password ofmamma-lumber-solemn
. - You need to make sure this user has access to the service operation via a permission list.
- You then have to take the user name and password and concatenate it together with a colon. That will give you
REST_TESTER::mamma-lumber-solemn
- Now you have to BASE64 encode that string which will give you:
UkVTVF9URVNURVI6Om1hbW1hLWx1bWJlci1zb2xlbW4=
- Now you have to pass an
Authorization
HTTP header in the request that looks like this:Authorization:Basic UkVTVF9URVNURVI6bWFtbWEtbHVtYmVyLXNvbGVtbg==
This is all very easy to do in Postman.
If you do not submit the correct Authorization header that maps to a valid user that has permission to the web service you will get an HTTP 401 (Unauthorized) status code back. Remember in REST status codes and HTTP methods are used extensively.
Exploring Further and More Use case
I will admit that this echo service is not very useful. However, this will give you a quick start to develop a more useful REST web service. Let’s say you wanted to return some employee level data to a client. You could take this example and replace the parameter1
value with EMPLID, then do some lookups via SQL and return the data. That part is easy.
You can also do much more complicated URL structures. Take a look at PeopleBooks for some examples. Also you can look at the “QAS” REST services for some good examples of URL structures.
Additional Reading
Article Categories
Chris Malek
Chris Malek is a PeopleTools® Technical Consultant with two decades of experience working on PeopleSoft enterprise software projects. He is available for consulting engagements.
About Chris Work with ChrisPeopleSoft Simple Web Services (SWS)
Introducing a small but powerful PeopleSoft bolt-on that makes web services very easy. If you have a SQL statement, you can turn that into a web service in PeopleSoft in a few minutes.
Integration Broker - The Missing Manual
I am in the process of writing a book called "Integration Broker - The Missing Manual" that you can read online.