Sunday, September 23, 2007

AJAX and PeopleSoft

After Ethan sent me the link to the PeopleSoft Auto-Save with Ajax post on the ITToolbox site I was inspired to try AJAX on a PeopleSoft page (and excited to try the jQuery library for the first time as it looked very cool). The blog post on the ITToolbox site had some great javascript code, but offered no details on how the whole thing was put together. Below are the exact steps I took to add AJAX to a page in PeopleSoft.

Before I get started I want to point out that I decided against trying the auto-save feature. While I think that this type of feature would be extremely useful in some use cases, I feel the Component you implement it with must be designed for it. Auto-saves should be saved as drafts and should not effect the current data stored in the tables. When the user actually clicks some sort of Save button, only then should the auto-saved data replace the data that existed before.

To simply my AJAX/PeopleSoft experience I decided to just create a dynamic DIV on an existing page. The DIV is updated periodically by sending an AJAX request to an IScript function which returns HTML that is placed directly into the DIV. This was done with PeopleTools 8.46.17.

Step 1.

I opened the Page I wanted to AJAX-ify and added an HTML Area control to the top of the page (specifically I added DERIVED_PTP.HTMLAREA).

Step 2.

I downloaded jQuery 1.2.1. I grabbed the "packed" version which is the smallest weighing in at only 26kb. As the ITToolbox entry hinted at, I tried adding the downloaded contents to an HTML object. However, when I tried to save the object in Application Designer I got the following error:

Object size exceeds 32K limit. Proceed with Save?

It let me save it anyway so I named the HTML object FR_JQUERY. When I opened up the page I received several javascript errors and when I looked at the cache javascript file that was created I found it was truncated. This happened when I used the code from the ITToolbox site:

<script src="%JavaScript(FR_JQUERY)"></script>


In order to make it work I added the contents of the packed jquery.js to a Message Catalog Entry (more details below).

Step 3.

I created an HTML object named FR_ISSUE_LOG_SRCH_DHTML with my code and a bind variable that I would later replace with the jQuery library. Here's the HTML object code:

FR_ISSUE_LOG_SRCH_DHTML HTML Object


<div id="new-issues">
</div>

%Bind(:1)

<script type="text/javascript">
var pollInterval = 15000;
function getIssues()
{
$("#new-issues").load("/psc/pshome/.../WEBLIB_..IScript_...");
setTimeout("getIssues()", pollInterval);
}

getIssues();

$("#new-issues").css({
left:"600px",
position: "absolute",
width: "250px",
fontSize: "9px",
padding: "2px",
});
</script>


Step 4.

On the Page Activate event I added the following code to populate the HTMLAREA field I had previously added to the Page.


Local string &jquery = MsgGetExplainText(31000, 3, "message not found");
DERIVED_PTP.HTMLAREA.Value = GetHTMLText(HTML.FR_ISSUE_LOG_SRCH_DHTML, &jquery);


What is noteable here is that the entire contents of the jquery.js file are stored in the Message Catalog and placed in the HTMLAREA using the %bind(:1) substitution variable. In our environment we can not easily added files to the webserver directory, so this provided a nice solution that did not require me to add any files to the webserver.

Step 5.

Finally, I created an IScript function that simply does a SQL Fetch for all rows entered in our custom table for the particular user viewing the page.

This was just an experiment on my part and only rates a 1 out of 10 on the coolness meter. My primary motivation was just to see how feasible it was to use AJAX on a PeopleSoft page. I was quite happy to find that it was easier than I expected (save for my little issue with placing the jquery.js code on the page). Also, I was able to dabble a lot with jQuery and find that it makes DOM manipulation and AJAX very easy and I will find a use for it in my next project.

Unlike the ITToolbox post, I was not attempting to interact with the component processor. Trying to involve actions by submitting the form information to the component processor and doing partial page updates is fairly complex and in my opinion looks like it can be prone to error. For the next couple of projects I think I'll stick to IScript type page refreshes to build my comfort level until a point when I am ready to do field validation and auto-saves.

7 comments:

Jim Marion said...

Brilliant post John. It is great to see customers customizing PeopleSoft like this. I've been using jQuery for quite some time. One thing I've found is that, even though the packed version is small, it takes an extremely long time for the browser to parse. In my tests I found that the packed version of jQuery took between 250 to 500 milliseconds (nearly half a second) to parse whereas the full and minified versions only took 60 milliseconds. Therefore, I prefer the minimified version. In fact, I actually downloaded the full jQuery and used the YUI Compressor to compress the jQuery library. I found that combining this with a gzip compression filter like com.cj.gzipflt.GzipFilter results in the smallest download and the shortest parse time. You can read more about the different jQuery distibutions on Julien Lecomte's blog.

If you plan to use this in production, I strongly encourage you to place your preferred jQuery distribution on your wb server. Here is why... While your message catalog approach gets the job done (and I must commend you on the unorthodox approach), it will result in a much larger file download that will have to be re-downloaded on every page refresh/server round trip. Likewise, if you decide to use the jQuery library on multiple pages, your users will have to re-download the jQuery library with each request. Basically, you loose the benefit of client side browser cache and increase your downloads by at least 20k. By placing the jQuery library on the web server, your users will be able to download the jQuery library once, and then just take the 60ms re-parse hit on every page that uses jQuery.

I read that you don't have access to your web server to change files. I feel your pain. If that is the case, then you do what you have to do to get the job done. Maybe if you buy your web server admin cookies?

Unknown said...

Thanks for the comment, I really appreciate the information. I had never given much thought to the packed version causing that much of a performance hit, but it makes sense. As you can probably can tell from this post and several others, the lack of control we have over our production environment often requires us to take unusual steps to implement certain things.

I will definitely take your advice and for production use I will bribe the powers that be to just load the unpacked version of jQuery on the web server. I try cookies and beer, maybe not in that order.

Jim Marion said...

John, I've been thinking more about developers being able to use libraries like jQuery even though they don't have access to the web server's directory structure. Like your solution, a developer in this situation needs to put the "large" JavaScript library in the database, but can't put it in a managed HTML object due to HTML object size limitations. Rather than load the jQuery contents into the page source, however, I recommend using an IScript to serve the jQuery library. From an IScript, you would use the same MsgGetxxx function to fetch the jQuery library from the database. Rather than put the entire contents into an HTML area on the page, you would just put a <script> tag that points to your IScript. Of course, this isn't as efficient as placing the file on the web server, but, for most developers, it is much more practical.

Atul Yadav said...

Hi I have tried the same steps as mentioned by you in this Post.But when page opens I get following html error.

Expected Identifier, String or Number.

Please Help.

Jim Marion said...

John, I just found this post that looks amazingly similar to yours: Injecting Javascript & AJAX into a PeopleSoft Page.

Anonymous said...

This is a very good article and I tried to follow all steps, facing issues and not clear, I'm sure I've missed a few or misinterpreted. Step 2 and 5 are not very clear as in Step 2 code is given but not sure where to post it, similarly step 5 mentions writing an IScript Function again not sure what and where, how to code. Seek help, throw some light.

This is anand.pandit@adityabirla.com

sabarinathan said...

oJohn,

I tried the same as you mentioned

Step 1:

Included the Jquery in Message catalog .

Created a HTML Area and mapped to DERIVED.HTMLAREA field.

HTML Code:

Same HTML code you provided
Step 2:
Created the function

WEBLIB_TEST.ISCRIPT1.FieldFormula.IScript_jQuery1

Function IScript_jQuery1 Returns Rowset
&rs = CreateRowset(Record.TEST);
&rs.Fill();
Return &rs;
End-Function;

Step:3

Page activate code:

Local string &jquery = MsgGetExplainText(29000, 1, "message not found");
DERIVED.HTMLAREA.Value = GetHTMLText(HTML.TEST, &jquery);

Result:

Result Page is having all the letters from message catalog ( i mean Jquery library) Not sure what mistake i am doing here ?