Sunday, October 23, 2011

REST-like PeopleSoft Services

As you survey the consumer web service landscape, you will notice a shift: fewer SOAP based services and more REST based services. I will refrain from sharing my true feelings about WSDL and SOAP to share with you the important stuff: how you can make REST-like calls into PeopleSoft. If you are not familiar with REST, then I suggest you read the Wikipedia REpresentational State Tranfer summary and then follow some of the external links for additional details.

While there are implementation differences, at its core, the difference between REST and SOAP is the focus. The focus of SOAP is the operation, not the data. The focus of REST is the data. I find this difference most evident when working with a Component Interface (CI). With a CI, you set key values, call Get (or Create), change values, and then call Save. The entire time you are working with that CI, you are working with a single transaction instance. The focus of the CI is the state of the data. The operations (get, create, save) are secondary. Service Operations are exactly opposite. Service Operations focus on method execution. The data (the transaction in this case) is just a parameter. OK, maybe this isn't the "core" of the REST specification, but as one who has tried working with a CI in a Web Service Data Control, it is enough for me to want to throw out web services. Don't misunderstand me at this point. I'm not blaming web services, the CI WSDL, or the Web Service Data Control. I'm sure they all have their place in development projects. It is my experience, however, that they mix together like chlorine bleach and ammonia (please, oh please don't mix these two chemicals!).

There are several implementation details that differ between REST and SOAP. As a user interface (think Ajax) developer, my preferred implementation detail is the ability to call services with a URL as an HTTP GET or POST. Yes, you can make SOAP calls with JavaScript, but I find it a lot more difficult to package up a SOAP envelope with JavaScript than to just make an HTTP GET or POST with jQuery.

As noted by the Cedar Hills Group PeopleSoft REST Wiki, there is a lot more to REST than just URL's, and a true REST URL doesn't use Query Strings for parameters. If you want more REST, then you will have to wait for PeopleTools 8.52 or build something yourself (stand-alone REST gateway, MyRestListeningConnector, etc). If, like me, your greatest interest is executing Service Operation Handlers from URL's, then review the PeopleBooks HTTP Listening Connector. It contains the URL call specification for PeopleSoft service operations. With an "Any to Local" routing, the basic form looks like this: http(s)://my.peoplesoft.server/PSIGW/HttpListeningConnector?Operation=EXECTHISOPERATION. If you prefer, you can pass transaction keys, etc as query string parameters, and then read those parameters in PeopleCode. Here is how (assuming &MSG is the message parameter to your OnRequest handler):

   Local &connectorInfo = &MSG.IBInfo.IBConnectorInfo;
   Local number &qsIndex = 0;
   Local string &qsValue;
   
   For &qsIndex = 1 To &connectorInfo.GetNumberOfQueryStringArgs()
      If (&connectorInfo.GetQueryStringArgName(&qsIndex) = "THE_QS_PARM_NAME") Then
         &qsValue = &connectorInfo.GetQueryStringArgValue(&qsIndex);
      End-If;
   End-For;

No, I'm not fond of having to iterate over each query string argument either, but that is what the API requires. I packaged this up in a Query String helper class and create an instance of it for each request that uses query string arguments. Here is my Helper class:

class IBQueryStringHelper
   method IBQueryStringHelper(&connectorInfo As IBConnectorInfo);
   method getParameterValue(&parameterName As string) Returns string;
   
private
   instance IBConnectorInfo &m_connectorInfo;
end-class;

method IBQueryStringHelper
   /+ &connectorInfo as IBConnectorInfo +/
   %This.m_connectorInfo = &connectorInfo;
end-method;

method getParameterValue
   /+ &parameterName as String +/
   /+ Returns String +/
   Local number &qsIndex = 0;
   
   For &qsIndex = 1 To &m_connectorInfo.GetNumberOfQueryStringArgs()
      If (&m_connectorInfo.GetQueryStringArgName(&qsIndex) = &parameterName) Then
         Return &m_connectorInfo.GetQueryStringArgValue(&qsIndex);
      End-If;
   End-For;
   Return "";
end-method;

What about the result? Does it have to be XML? No. I have used two ways to create non-XML results from Integration Broker. The first is by creating a JSON response directly in PeopleCode. It is this use case that prompted me to write the PeopleCode JSONEncoder. A service operation handler can return non-XML by wrapping the result in a psnonxml attribute like this:

   Local Message &result_msg = CreateMessage(Operation.MY_SERVICE_OPERATION, %IntBroker_Response);
   Local string &json;
   
   REM ** Do some processing to generate a json response;
   
   Local string &nonXmlData = "<?xml version=""1.0""?><data psnonxml=""yes""><![CDATA[" | &json | "]]></data>";
   Local XmlDoc &doc = CreateXmlDoc(&nonXmlData);
   
   &result_msg.SetXmlDoc(&doc);
   Return &result_msg;

The second method I use to create non-XML results is through a transformation. Using XSL, it is possible to transform an XML document into JSON -- although JSON-safe encoding might be more difficult.

If you use a debugging proxy (such as Fiddler) to inspect the results of an Integration Broker response, you will notice Integration Broker always returns the Content-Type header value text/xml. Unfortunately, this means you have to help jQuery understand the results because it won't be able to determine the response type based on the Content-Type header. When PeopleTools 8.52 arrives at your office, you will be able to specify different MIME types. For now, I find it satisfactory to just set the $.ajax dataType parameter to "json." If you absolutely need to set the Content-Type header and don't have PeopleTools 8.52, then I suggest looking into a reverse proxy with header rewrite capabilities (Apache, for example).

No, unfortunately, this post didn't show you true REST. If you are choosing REST for Ajax because it is easier to make a URL based request to a REST service than to build a SOAP header to send to a Web Service (like me), then this post hopefully offers you enough information to get started. If you require more of the REST specification than I've shown here, then you will probably have to wait for PeopleTools 8.52.

73 comments:

Dan Kibler said...

I've been hacking RESTful services in IScripts using JSON.Simple to create the JSON response string. It's a very low overhead approach. My client is HTML/jquery/javascript served from the PS webserver so the security is taken care of.

Jim Marion said...

@Dan, yes, exactly. It is very similar to this approach in its REST compliance, but iScripts require a lot less meta-data configuration.

Sudheer said...

Hi Jim,

Is there a possibity to get windows login into peoplesoft.

Thanks
Sudheer

Jim Marion said...

@Sudheer, yes, the best way is to use the PeopleTools Kerberos SDK. It is a Java ServletFilter for your PeopleSoft web server that sends your desktop the appropriate challenge/response to get the logged in user's token, and then verifies that token against your directory server.

jb said...

Jim, I am working on an issue in 8.9 HR Recruiting. I am trying to understand how the Service Framework is put together with the Interface registry. I have traced the code back to an App package called HHR_MANAGE_COMPTNCY_SERVICES:Person:GetPersonTrainingHist_v1_0:GetPersonTrainingHist.
From here though, I am lost as to what this is doing, besides instantiating an object. Eventually, if calls a Service Manager.LocateService. Can you shed some light on how this works?

Jim Marion said...

@jb, I know exactly what you are talking about: the HR services registry. I'm sorry, I have little to know experience with it. I've seen some of the code, but only from the same perspective as you: searching for a solution as to why something isn't working the way I think it should.

Unknown said...

Hi Jim,

I'm trying to develop a client for a service published trough PS HttpListeningConnector. My customer has provided an XML file, they tested the service importing the file in SOAPUI and sending SOAP messages to the service. in PS side the service perform operations like create a new user or add role to an user.

Please point me How to develop a client for this service (maybe an HttpClient like in your post "Generating an AuthToken for SwitchUser") please help me

Regards
Juan Sarro

Jim Marion said...

@Juan, there are a couple of ways to build a client. If you are using a CI based service or some other type of PeopleSoft service that has WSDL, then you can use one of the many, many developer tools for consuming WSDL.

If you want to just write a simple/basic program that sends data over HTTP to Integration Broker, then start with the HTTP URL for your service. You can paste this into a web browser to access your service. Next, write a program that speaks HTTP. If you are using Java, then use the commons-httpclient or even just the lower level URL and http connections.

Chandra said...

Thanks Jim for your post and tips and tools book. I learned lot of concepts from. I am working with a third party vendor on a integration. they are asking us to HTTPS POST a form with Name&value pair, in return they will send me a xml response. I need to use the contents form the XML and redirect url to their site. How do i approach doing this in peoplesoft. we have 8.51 tools.


I wrote an Iscript which response and html and java script.with the submit button, i am able to post the form to thirdparty url, I am not sure how to collect their response.
Appreciate your comments

Thanks
Chandra

Jim Marion said...

@Chandra, I believe the approach you took is a great way to post to a third party, but, as you noticed, once your browser sends the post to an external domain, you lose all control. That technique won't allow you to do anything with the response. As an alternative, you may want to attempt a server side POST. With a server side POST, your will write PeopleCode to POST those key/value pairs to the external site (Sync Request). Your PeopleCode will then receive the XML response. Integration Broker's HttpTargetConnector can handle POST. An alternative is to use Commons HttpClient.

Chandra said...

Thanks Jim for your quick response. I will try and let you know how it went.

Chandra said...

Jim,

Let me tell my objective again: third party is asking us to post some name/value pairs to their URL,
they did not give us wsdl and it is not a service. in return they will respond me with token, I use that
token to redirect the user to their website.

Based on your suggestion earlier,

I was able to come up with below code and it is posting the data
to thirdparty successfully, However, It seems thirparyt is not able to proces the name/value's from IB's post.

Both the name/value pairs in my reqeust are correct, I have validated by submitting them in simple html form
from my browser and i got the valid tokens. However, when i post via IB i am not getting the same result.

I have reviewd the synchoronous xml request log, it looked fine there, just name/value paris no xml/SOAP.
I am suspecting that IB is not sending the correct contect-type. I have set the content-type=application/x-www-form-urlencoded
both on Node and routing.

Is there any Fiddler like tool that i can use to see what IB is sending in terms of message's http header and
body ?

Or there any better ways you can think off. Please suggest me.


&encoded = "ENTITY_ID=" | &ENTITY_ID | "&REGISTRATION_ID=" | &REGISTRATION_ID;


Local string &nonXmlData = "";
&xmlDoc1 = CreateXmlDoc(&nonXmlData);

&Msg_Reqst [1].SetXmlDoc(&xmlDoc1);

&MSG = %IntBroker.SyncRequest(&Msg_Reqst [1], &Nodes_Reqst [1]);

Jim Marion said...

@Chandra, you may be on to something with the content-type header. I don't recall any way to set that other than through a reverse proxy sitting in front of IB. With apache in front of IB, you can change just about anything (using mod_headers, etc). PT 8.52 added more support for content types, but I don't think you could set the content-type before that.

Anyway, your other question: Fiddler. I use Fiddler with IB. I was actually going to suggest it and then read that you were asking about it. Here is what you do: Install fiddler on a Windows OS that your IB server can access and open Fiddler's options so you can enable external connections. Copy the host and port #. Modify your integrationGateway.properties file to use Fiddler's host and port for IB's proxy server settings. You may have to restart the IB web server for the settings to take affect.

I find fiddler to be the best tool for debugging IB and the process scheduler report posting process.

Another option for setting headers... if you find that the headers are your problem and you are not able to use a reverse proxy server, then another solution is to write a ServletFilter to modify the IB response as it leaves your J2EE web server (weblogic or websphere). The ServletFilter would be very simple. In your servlet filter, you call FilterChain.doFilter, and then you set the Content-Type header so that you are overriding the default. Of course, you would want to make sure you only do this for your service operation, so you will want to make sure you test the request (URL parameters, or something that identifies your service).

Chandra said...

Thanks Jim for all your suggestion. every time i speak to you I realize that i how much i don't know :). On my Issue, I was able to resolve the issu by post the name/value pairs in my query string itself. I am lucky in this case, I don't have to post more than 256 chars.

Jim Marion said...

@Chandra, we are all students. I learn from my readers as well.

Yes, if you can use the query string GET form instead of an HTTP post, that is MUCH, MUCH easier.

DarkPadawan said...

@Jim I know this is and old Post but I have a few questions on 8.52 tools support for REST Services. First of all it looks like PeopleSoft only recognize HTTP status codes in the 200. Which does not make sense since HTTP status 401 is a valid response and if the 3rd Party service returns that I get a message saying there is a network problem accesing the URI. Second is the JSON Response. Is there a way for me to get the RAW Body of the message as a String? this might not be important since without the HTTP status codes I see the proxy in front IB as the best solution.

Thank you for your help and I love your blog an books ;)

Jim Marion said...

@Dark, I'm not sure if your scenario has PeopleSoft as the producer or consumer.

I haven't worked with HTTP status codes. If PeopleSoft is the producer, I'm not sure how you would set a different response code. If PeopleSoft is the consumer, then you should be able to determine the HTTP response code from the message HTTPResponseCode property.

The message class has a handful of methods for accessing the message content. I think the most generic is the GetContentString method which returns the content of the message in plain text. This is most likely what you want if the response is JSON.

I have worked a LOT with JSON from PeopleCode. When PeopleSoft is configured as the producer, some other system sends a synchronous request to PeopleSoft. Your REST service operation will have an OnRequest handler and that OnRequest handler runs whenever PeopleSoft receives a request from an external system. This OnRequest handler can return any kind of data (JSON, XML, CSV... anything). One of the great features of PT 8.52 is the ability to set the response content type and use the SetContentString method to return a non XML response. With prior releases of PeopleTools, you have to wrap the response in XML with an XML tag that has the psnonxml attribute.

Unfortunately, as of 8.52 PeopleSoft does not yet natively produce JSON. You can produce JSON, it just isn't native. You have to string a JSON response together using your PeopleCode OnRequest handler. This is why I wrote a JSON Encoder PeopleCode App Class.

As far as consuming JSON, I find the easiest way to parse JSON is to use the json.simple JSON parser. It is my favorite, and the one that I document in my book. Another alternative is the json.org parser along with this App Class JSON helper.

I hope some of this helps. Let me know if I misunderstood the question.

Jim Marion said...

I received some feedback from @DarkPadawan saying if the external service returns anything other than a 20x code, the result/response message from the external system will be Null and Integration Broker will through an Integration Gateway - External System Contact Error (158,10721). That is too bad. I suggest someone enter an enhancement request to have IB send this information through to the PeopleCode.

Fortunately, IB isn't the only way to call external services. I haven't written a PeopleCode version of this, but here is some Java that shows how to make an HTTP Request: http://docs.oracle.com/javase/tutorial/networking/urls/readingWriting.html. You would just have to convert it to CreateJavaObject and GetJavaClass calls. Another option that I find easier is to use Apache Jakarta Commons HttpClient. No, this alternate solution does not have the queuing and management facilities of IB, but it does get you connected. I wish I had a better answer, but worst case, there is always the Java, Windows, or Linux API's.

Karthik said...

Hi Jim,

Hope all is well.

We have a req to do an HTTP Post to a third party system. I was able to do this with iScripts - Created a html form and in the post url - I gave the third party URL. Once we submit the form, it goes to their URL, our user is expected to enter some more parameters and when they finally hit Submit, the third party will do a POST back to a return_url which we sent in the first POST. So for the return URL, I gave them an iScript URL and used %Response.GetParameter function in the iSCript code to obtain the values.

Questions:
How secured is this method? Do you see any security concers with this approach?
As an alternate, I created a ASync Service Operation(with Any to Local routing) and gave this as the return_url for them to POST.On the OnNotify peoplecode, using &_MSG.IBInfo.IBConnectorInfo.GetNumberOfQueryStringArgs() I am able to get the values they were posting. But the issue is, once they submit the form, the browser returns the MIME XML response success message for the Service Operation. I dont think it makes sense to display this to the end user. Is there a way to take control of this and just print, "Posted Successfully", etc.,

So please let me know the recommended approach for this - iScript or the HTTP Listening Connector method..

Thanks so much...

Jim Marion said...

@Karthik, either approach is fine security-wise. The iScript uses the logged in user's PS_TOKEN cookie. Just make sure you have appropriate validation on query string parameters and that you appropriately secure the iScript or service operation through permission lists.

To gain control over the IB response, use a Sync rather than Async service operation. Sync is request/response and lets the PeopleCode finish before returning a response. This lets you build the response. Just be sure to use the psnonxml attribute as described in this blog post so you can return HTML.

suryavel said...

hi,
we are doing outlook integration proj.While we try to integrate peoplesoft CRM 9.1(PT8.52) with a 3rd party system(BDSS-business data synchronising server) through integration broker, in this process we provide web services.Now we are able to conect with exchange but not with peoplesoft.Is there any thing to b configured in IB so it connects with peoplesoft??

Jim Marion said...

@suryavel, you may want to post your question on the OTN forum or in ITToolBox.

Carl said...

My post relates to Jim and DarkPadawan's discussion regarding HTTP status codes. In my scenario, Peoplesoft is the consumer of a third party REST provider, and I agree it is too bad that IB reports an ERROR with any non 20X HTTP response code.

What's worse is that there is no way to access the response message once IB considers it an ERROR. I've created an enhancement request with Oracle to address this.

In the mean time, I suppose I will look into the Integration Broker Connector SDK despite my heavy anticipation of true REST support within 8.52.

Bijay Bhushan Singh said...

hi jim,
i am creating non ci based web service using application package. and i created some wsdl for some delivered peoplesoft campus solution.
for consuming i am using soap tool.can u just tell me how can we add role level security during the creation of wsdl.please suggest me how to add role level security in wsdl. thanks in advance

Jim Marion said...

@Bijay, did you mean row level instead of role level? All CI's are role level because you have to connect a CI to a permission list and role in order to execute it. Row level is handled by the component business and SQL logic behind the CI, not by the WSDL. A WSDL is just a definition identifying operations, parameters, target location, and type of authentication required to execute the service operations identified by the WSDL.

Bijay Bhushan Singh said...

thanks jim for reply,
sorry but really i am very new to web sevices.i want to provide role level(not row level) security in ci based and non ci based both type web services. for testing purpose i am using soapui tool. is there any way to give security like role is manager then he can see these data(in response).so in peoplesoft during creaton where we can assign security like this. as i read in xml message schema i think but i am not able to get it clearly
thanks in advance.

Jim Marion said...

@Bijay, not in the WSDL, but in the underlying component itself. In the RowInit event or other initialization event, you can determine what data to display based on IsUserInRole results. Likewise, you can join to security views to limit the data visible based on role membership.

Kedar said...

Jim,

I want to use ajax and send JSON from an external client to Peoplesoft, and then return a value back to the client from Peoplesoft, using a Message/Integration Broker.

I read your various posts about JSON in Peoplesoft. I kind of understood how to return the JSON in a CDATA section using psnonxml in the header, although I have not implemented it yet. But am still not sure how Peoplesoft Integration Broker would accept JSON, or non-xml data sent by the ajax on the client side.

Could you please explain or provide some help regarding this?

Thanks,
Kedar

Jim Marion said...

@Kedar, I have not yet had to post JSON data to Integration Broker. Fortunately, I've been able to fit everything into the query string.

Fortunately, integration broker accepts unstructured data. Just make sure to use an unstructured message for your service operation.

Your next hurdle will be reading the JSON data with PeopleCode. I For this, I recommend using JSON.simple.

Brian Heinbaugh said...

Hi Jim,

Thanks so much for keeping up the blog! I realize this is an old post but I thought I'd at least give it a try.

We have a requirement to send an http post that consists of a URL plus a number of parameters to be used as a query string. We have successfully accomplished this via iscript online but also have a nightly batch requirement via app engine.

We tried creating a REST service using the document message structure. Setup was an adventure as the service ended up defaulting to synchronous? When we try a .publish for example, we are getting a message that no queue exists - which is true. We have no way of adding a queue to the particular service.


When we use the service tester, it appears to work correctly. However when we run through an app engine, the logs generated appear to perform a GET - rather than a POST?

Are we overcomplicating this?

Any insight would be appreciated.

Thank you,


-Brian

Jim Marion said...

@Brian, By definition, REST is synchronous.

If you are posting from an App Engine to Integration Broker, then I think the easiest way would be to use standard/old 8.42 PeopleSoft rowset-based message structures. That way you don't have to figure out how to post or move data into message structures. You can just use CopyRowset.

Jim Marion said...

@Brian, I was going to ask you if you changed something to attempt to make a REST service asynchronous and that is why you were seeing a queue message. Queue's are only relevant for asynchronous service operations.

Brian Heinbaugh said...

Jim,

Thanks for responding so quickly. Yes we tried a peoplecode command reserved for asynch I believe (&msg.publish) once the message (&doc) tied to the Restful service we created was intantiated. That is when we got the queue message - and now I know why thanks to you.

Our issue is that our third party in this case cannot handle a standard integration message structure. They require a basic http post only.

Now understanding that RESTful by definition is synchronous, I assume that invoking that type of service in a batch program - i.e app engine would also not work.

I fear we may be faced with creating our own java class or target connector perhaps to solve what honestly we thought would be an easy problem.

As mentioned before we are able to post fine using iscript online. Now we need to batch up a number of files and post URL's to another system - a document repository for example. The post should be nothing more than a URL with query strings appended.

I really appreciate your taking the time to respond.

Thanks,

Brian

Jim Marion said...

@Brian, here are a couple of other options:

1. Use an XSL transform to convert the outgoing standard Async PeopleSoft XML document into a key=value form field pair.

2. Use a PeopleCode transform to do the same as #1, to make sure the result is www-form-urlencoded.

Also, what is wrong with using a Sync Request in your App Engine? It will block while waiting for a response, but that should be OK. This is how your browser works.

selvakumar said...

Hi Jim,

How can we call a third party REST based web service (via URL with query strings) and receive the response? We are in tools 8.49 and consume web services supports only SOAP based services.

Please bear with me as am new to web services.

Jim Marion said...

@selvakumar, You can make a synchronous request from PeopleCode using %IntBroker.ConnectorRequestURL. The link has a good example. The return value is a plain string.

M Asim said...

Hi Jim
I am new to web services and I am trying to publish Provide web Service(with SOAP). I have done all setting right as I know from oracle document.
But I am getting following error while testing it on SOAP service test tool.

Integration Broker Sync Handler: OnRequest for message CUSTOM2 could not run to completion on node PSFT_HR. (158,974)

Any Help related this error please.
Thanks

Jim Marion said...

@M Asim, run the test and then look in your app server log. If you don't find the answer there, then look in the PSIGW web app folder for msgLog.html and errorLog.html. If you still don't find the answer, then increase the log level from the domain advanced configuration page.

bharat sadavarte said...

Hi Jim,
Can we call Qualtrics Control Panel REST API like createPanel, addRecipient, sendSurveyToPanel etc from PeopleSoft ( tools version 8.49 )

Jim Marion said...

@bharat, I am not familiar with Qualtrics. Integration Broker has no problem creating HTTP requests with the HttpTargetConnector, so I would suspect it would have no trouble making requests.

ChicagoMom said...

Hello Jim,

I start to read your articles; read the responses/comments and realize how REALLY smart you are and how little I REALLY understand.

Thank you for sharing all that you know.

Yvonne

Thirumal said...

Hi Jim,
I was working on RESTful web services in PeopleSoft with Tools 8.52. Client wants JSON to and from PeopleSoft. We tried different options and finally using GetContentString([SegmentIndex])to get the JSON from the HTTP request. Just thought of sharing this so that it will be useful to others.

Regards,
Thirumal

Jim Marion said...

@Thirumal, thanks for sharing!!

SK said...

I am trying to send the response received from a punchout requisition to a third party application. I would like to capture the xml being returned by the direct connect service operation and then send it to a third party application even before the requisition is saved. Any ideas on this?

Jim Marion said...

@SK yes. Create a PeopleCode transform on the inbound routing. This will trigger before the handler. You don't actually have to transform something, just use it as a hook.

SK said...

@JIM When the response is generated by the punchout it transfers to PV_DC_Catcher page where the page activate code triggers to capture the response.It is a synchronous operation but I do not see a inbound routing for this. I can see the response in the code but trying to send this response as part of another service operation...Thanks

Jim Marion said...

@SK, I didn't think about it being synchronous. In that case, you set your transform on the synchronous outbound routing response message.

SK said...

I may not have asked the question correctly..

The synchronous service is as follows:
PS --> Vendor (request)
Vendor --> PS (response)

Need to catch the response and send a response to another third party system..The third party system uses IB in the backend to perform the punchout and capture the response.

I cannot set the transform on the outbound routing as it would not have the earlier response in the buffer..Sorry for the trouble..

Jim Marion said...

@SK, I understood. With a sync service (inbound or outbound) you only have one routing, but that routing has transforms for both the request and the response. In this case, I assume you have an outbound routing (Local to Any?) where sender is your default local node and the receiver is Any, or some other named node. In the routing Parameters, you will see a transform for the request and a transform for the response. You can capture the entire response in that response message transform and do whatever you want with it: send it somewhere else, change it, delete it... whatever.

SK said...

Hi Jim

Thanks for all the comments.

I am trying to close the response window once the service operation is successful. Can we accomplish this through peoplecode?

Jim Marion said...

@SK, I am not familiar with a response window.

SK said...

I was referring to the response window generated by IB for synchronous or asynchronous services. Can we close this window through Peoplecode?

Jim Marion said...

@SK, web services are transparent. There is a request and a response. I am not aware of a window that opens. web services don't even expect you to be running in a browser, so they have no way of determining how to open a window.

Perhaps you can post a screenshot somewhere and provide a link here?

nitish Purohit said...

Dear All,

I wanted to send the Sync message. For that i created the message strcuture through CreateXMLDoc method, however got the Target connection error because the third party system requires soapenv: Envelope. Now i am using the SOAPDoc method but i am unable to construct the same structure through it. This is my structure:
+++++++++



















123


1

+++Plz help

Jim Marion said...

@Nitish, you have to escape XML before pasting it into the comment editor.

I've done the same thing as you, but the way I did it was to take the SOAP XML and place it in an HTML Definition with HTML bind parameters for real data values. Then you can just use GetHTMLText to replace the tokens.

Kirthi Sistla said...

Jim,
We are integrating PS recruiting with external vendor for backgroundcheck process.
As the vendor is not peoplesoft certified I created xsl files to convert peoplesoft xml to vendor xml and vice versa. It works great for PreEmploymentCheck transaction as we able to send request and receive response.

I have an issue with PreEmploymentStatus as I don't understand if we provide query string with webserver port and to node and messagename will they be able to send their results xml to our PeopleSoft Node.
Is this a standard integration process or is it only because of OIF.

Jim Marion said...

@Kirthi, yes, in theory, if you provide someone a URL for them to execute a web service, they will be able to do so. PeopleSoft was designed for use in this manner. The part left to a customer's implementation is network access. Whether or not the vendor can send you data through this service depends on whether your vender has network access to your PeopleSoft instance.

Dave Horne said...

Jim, I've been trying to use REST web services by passing in a usertoken to be used for authentication without using Peoplesoft security like is defined in a SOAP request using the WS_Security model; but it appears that it's not available yet. I've been told by some Oracle engineers to put the information in the Request Header and then pull it out in Peoplecode in the app class. However, I can't seem to find a way to retrieve the REQUEST header information; there's one comment in Peoplebooks that says: Note: "No HTTP properties are currently applicable for REST and will be removed by Integration Broker." Does this mean there is no way to retrieve header info from the request msg? If this is correct, is there another way you can suggest in getting the usertoken through to Peoplecode without having the user token in the URI or in the Message Body?

Jim Marion said...

@Dave, I do not. I had heard at one point that it would read the PS_TOKEN cookie, but I just tested it and didn't find that to be the case. I also heard something about using the token with the authorization header, but haven't tested that either. Of course, as you know, as soon as you get the token into PeopleCode, you can use SwitchUser.

Dave Horne said...

Jim, That's exactly what I want to do, but as you see; there seems to be no way to access the header. I have found that it is coming through the IB and being stored in the IBInfo Blob, but I can't see anyway to retrieve it. If I retrieve the log for the synchronous message (blob) I can see all of the &ltheader&gt tags, but I just can't seem to find a way to read it while in Peoplecode. Without this functionality we can't switch from SOAP to REST. Hope to find a solution soon.

Jim Marion said...

@Dave, I checked with an Integration Broker expert. Since you are already doing this with SOAP, I suspect you already checked IbConnectorInfo's GetConnectorPropertiesName, GetConnectorPropertiesValue, GetConnectorPropertiesType, GetNumberOfConnectorProperties properties? You have to iterate over them until you find the right one.

Jim Marion said...

@Dave, I just watched a presentation from David Bain given to the Quest user group. He showed a screenshot of service operation security that included PeopleSoft Token and PeopleSoft Token w/SSL as security options. Perhaps that is targeted for a future release? I don't have that option in my PeopleTools 8.53 instance.

Jason said...

Jim,

I'm trying to set up an integration scenario where PeopleSoft trusts my external authentication source (through some signed or shared secret method) and will execute the service operation in the context of a user I specify in the message (HTTP Header or some such). With SOAP I'd use Signed UsernameToken or SAML for this, but the service I'm calling is delivered as REST. There is a SOAP equivalent, but I'm also using a delivered client that expects REST and don't want the maintenance of translating back and forth.

Any options you'd suggest for trusting that the user has been externally authenticated on a REST service?

Jim Marion said...

@Jason, REST uses the Authorization header. Usually this is implemented as basic auth over SSL. You will see this option in the REST service operation definition. Then you use the authorization header to pass credentials. Most libraries, etc will have an option for a username and password. If they don't, you just base64 encode username:password. You can find plenty of examples online.

Unknown said...

@Jason - We are attempting you have stated above regarding having a third party Authentication and trust that throughout the REST service. Can you share if you managed to get that working and the steps you used?

Jason said...

@Jim - Unfortunately I've been unsuccessful so far and have fallen back to allowing Peoplesoft to directly authenticate the username/password through custom signon peoplecode. I'm also working an SR with Oracle that I believe is trending in the direction of an enhancement request as we've not found any way to access any of the HTTP context (headers, cookies, extra path info, etc) from the context of signon peoplecode when calling a REST service.

Jim Marion said...

@Jason, that is correct, Integration Broker does not give access to the HTTP transactional information. I find this regretful. There are many times where I wish I could access the HTTP request and response headers.

Syed Usman said...

@Jason -- Could you put some light on how are you using custom signon PeopleCode(PC)for authentication, as I am also trying to authenticate user via custom signon PC for REST web service.
My user is being prompt for user name & pwd on browser but it is being authenticate from PSFT PSOPRDEFN table, not from our custom signon PC.
Any hint?

Jason said...

@Syed - From what I've found there could be a couple of issues here.

The ability to execute SOPC for IB web service calls was not working if the username you're trying to use doesn't exist in the PSOPRDEFN table on some tools versions. My understanding is 8.53.12 and 8.52.21 have a fix for this and that it will also be fixed in 8.54 when that is released. If you're not on one of these later tools versions, the OPRID has to exist in PSOPRDEFN for the SOPC to even get called.

Beyond that, ensure that you have set the Invoke As user in your Signon Peoplecode setup. Without this set, SOPC will attempt to execute in the context of the user who's logging in - which won't work if the username isn't in PSOPRDEFN.

Hope that helps

Syed Usman said...

@Jason - Thank you for this insight.In my case userid does exist in PSOPRDEFN table and the pwd is not matched with PSOPRDEFN that is why our SOPC fired when user login via common PIA login page but for REST web service prompt user/pwd page it won't go in SOPC. Does tool version issue means PT only auth from PSOPRDEFN table and then stop further verification like SOPC?

Jason said...

@Syed - I believe the tools version issue would cause this issue. When I turned on appserver tracing I never saw the SOPC execute on a rest call before we installed the proper patch version.

Because my application's usernames don't exist in PSOPRDEFN though I can't recall if I replicated your test exactly. I'd suggest turning on an appserver trace (has to be for the whole appserver - I haven't found a way to just turn this on for IB) and see what you get. If you're not on one of the recommended tools versions though you may want to try that in a sandbox first - pretty easy to do now with the PUM images being released on VirtualBox.

Pratiba Paul said...

Hi Jim,

I do not have prior experience working with PS IB. However, in an attempt to create an opportunity to learn it, I am trying to build an integration between LinkedIn and PS Recruiting, wherein an applicant's profile information is obtained from LinkedIn as an XML via HTTP POST. (LinkedIn Plugin called "Apply with LinkedIn"). In its basic form the code is as below (provided by LinkedIn)

HTML Header - loading the LinkedIn Javascript:

src="//platform.linkedin.com/in.js" type="text/javascript">
api_key:


HTML Body invoking script:

type=IN/Apply data-url="http://my.company.com/rest/jobPostingXml" data-urlFormat="xml" data-jobTitle="Test" data-companyID="xxxx"

If instead of data-url I used the data-email parameter, I would receive an email with the applicant's LinkedIn profile. How can we receive this JSON or XML from LinkedIn to store within our PS DB? What would the data-url be? I'd like to ultimately create an applicant a profile within PS DB and refine the profile/resume parsing function. I know this is pretty basic, but a push in the right direction or a high level idea of how to solve this, would really help.

Jim Marion said...

@Pratiba, do you have an external facing URL for Integration Broker? Have you created a service operation and handler? If so, the URL would be the service operation's URL. Alternatively, you can send it to an e-mail and use the POP3/IMAP connector to access information from an inbox.