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.

Thursday, September 13, 2007

Just wanted to follow-up my previous post about Log4j in PeopleCode and post the actual log4j.properties file that I used. Using this file along with the code posted previously is all you would need to get started.


log4j.rootLogger=WARN, rolling

log4j.appender.screen=org.apache.log4j.ConsoleAppender
log4j.appender.screen.layout=org.apache.log4j.PatternLayout
log4j.appender.screen.layout.ConversionPattern=%d %-4r [%t] %-5p %c %x - %m%n

log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.Threshold=DEBUG
log4j.appender.rolling.File=/some/directory/log4j.log
log4j.appender.rolling.MaxFileSize=20480KB
log4j.appender.rolling.MaxBackupIndex=5
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.ConversionPattern=%d %p [%c{4}] %M %m%n

Friday, September 7, 2007

Log4j in PeopleCode

Jim's PeopleSoft Journal had a good entry on using Log4j in PeopleCode. This first article assumed that you would have control over the log4j.properties file in your environment. Jim also posted a follow-up on Log4j and Peoplecode Part II where he discussed how to programmatically configure the logging. This is nice for those, like me, that do not have access to modify the $PS_HOME/appserv/classes/log4j.properties file.

The programmatic approach works well, but I didn't want to hardcode all that information in each event I want to log information in. You can point log4j to an alternative logging file using the code below, that way you can keep control of the logging level and setup of the appenders in a file that is easy to modify. Of course, this assumes that in your environment you have some access to a directory where you can store the file and grant write access to it for the daemon that runs the application server.


Local JavaObject &log4jConfig = GetJavaClass("org.apache.log4j.PropertyConfigurator");

&log4jConfig.configure("/some/directory/log4j.properties");

Local JavaObject &log = GetJavaClass("org.apache.log4j.Logger").getLogger("edu.csufresno.cis.HRS_CE_RESUME.PageActivate");

&log.info("hi from peoplecode");


Note: I got tripped up initially because I didn't read Jim's code closely enough and tried using CreateJavaObject out of habit instead of GetJavaClass. Since both methods are static (i.e., can't create an instance of a Logger) it blew up with an error.

Pouring through logs

Been doing an inordinate amount of tracing and debugging lately. Our ERP system dumps a lot of junk to the logs. The following command is my friend.


tail -f trace.log |tee $HOME/mylog.log


I like to be able to follow the file as lines are added and also like to send the output to a log file that I can open in an editor so I can so more regex type searches.

Tuesday, September 4, 2007

Log4J - email notification of production errors

There are a couple of things I try to do before I sit down to write Java code for even the smallest project (cause they always grow). One is creating an ant build script and the other is creating a log4j configuration file and adding log4j to my library path. I used to sprinkle System.out.println's throughout my code and now I've gotten in the habit of using the logging library.

I hadn't used the SMTPAppender, but recent issues with production code got me thinking about it so I'd have a heads up before users starting yelling. Below is the log4j.properties file that's worked well so far. The code is all custom so I have total control of all log.error and log.fatal statements, so when I get an email I know exactly what the issues is. Wouldn't be possible if I still used System.out.


log4j.rootLogger=ERROR, SMTPAPPENDER, rolling

log4j.appender.screen=org.apache.log4j.ConsoleAppender
log4j.appender.screen.layout=org.apache.log4j.PatternLayout
log4j.appender.screen.layout.ConversionPattern=%d %-4r [%t] %-5p %c %x - %m%n

log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.Threshold=DEBUG
log4j.appender.rolling.File=/tmp/csufresno-hrsrecruit-cnv.log
log4j.appender.rolling.MaxFileSize=20480KB
log4j.appender.rolling.MaxBackupIndex=5
log4j.appender.rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.rolling.layout.ConversionPattern=%d %p [%c{4}] %M %m%n

log4j.appender.SMTPAPPENDER.To=me@myaddress.com
log4j.appender.SMTPAPPENDER.layout=org.apache.log4j.PatternLayout
log4j.appender.SMTPAPPENDER=org.apache.log4j.net.SMTPAppender
log4j.appender.SMTPAPPENDER.Subject=[hrsrecruit] ERROR
log4j.appender.SMTPAPPENDER.BufferSize=512
log4j.appender.SMTPAPPENDER.From=myapp@myserver.com
log4j.appender.SMTPAPPENDER.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
log4j.appender.SMTPAPPENDER.SMTPHost=mysmtp.server.com

log4j.logger.edu.csufresno.cis=INFO



Just a note, took me a few runs to figure out that I needed mail.jar and activation.jar in my classpath. After that, smooth sailing.

Sunday, September 2, 2007

Vista, no thanks

In early August we received new laptops at work, some very nice dual core Dell Latitudes with a couple gigs of RAM. Now I can finally have JDeveloper and SQLDeveloper open at the same time. I have forgone installing Microsoft Office and instead am rolling with OpenOffice 2.2, no regrets. Still a Thunderbird fan, what's Outlook? The main Microsoft software I rely on is the OS, Windows XP.

In a year we are supposed to upgrade to Vista and MS Office 2007. Based on what I've seen of Vista so far I think that will be the time to move to Linux. Many in IT where I work have moved to MacOS and while I admire the BSD-like OS under the covers, I'd just be trading one corporate vendor for another. In addition, most of the software that I need to run in order to do my job is either not available on the Mac or is in beta. There is not one tool I use that requires MacOS. There are quite a few tools I use that are available for both Windows and Linux. For those cases where a Linux version is not available I can use Wine or an XP guest OS in VMWare Server.

So I have one year to decide what distro to run. I've been running Ubuntu on my home laptop for about the last 8 months. It's a nice distribution, very easy to setup and use. It has given me a great appreciation for the Debian packaging system. I have it narrowed down to either a Debian or Redhat distribution. Redhat would be a good choice because it'll likely replace our Sun Solaris boxes in the near future. I've been working with CentOS in a VMWare image for a little while and found I really like both the workstation and server installs. As for a Debian distro I think I would go with plain old Debian. While Ubuntu does have a large user base, I need very few of the features that are Ubuntu specific. I dislike some the configuration changes I've seen lately in Ubuntu (i.e., their choice of replacing the inittab with event.d). I want my Linux system to be as standard as possible if I go with Debian and I think Ubuntu is starting to stray away from Debian a little too much and I don't want to end up running a distro that forks from Debian.

I think the main decision will depend heavily on package management, I know Debian's apt-get is excellent. For now I need to continue playing with CentOS to see how Yum stacks up.

Podcasts

I am trying to make up for lost time since I haven't posted in a long, long, long time. Here my list of podcasts that I regularly listen to....

  • bsdtalk
  • Casting from the Server Room
  • FLOSS Weekly
  • Google Developer Podcast
  • In the Trenches
  • The Java Posse
  • Linux Reality
  • OnSoftware
  • Oracle TechCasts
  • Perlcast
  • Software Engineering Radio
  • SourceTrunk

iText - Java PDF library

I recently had to do some tuning on a project I had done that involves converting and merging documents into PDF format. The main performance issue turned out to be poor performing sql and a function-based index fixed it. I decided to try tuning a few other pieces of code and that brought me to try an newer version of the iText library...wow was I pleasantly surprised.

In the project I use iText to merge PDF documents into a single document and also use it to convert TIF and JPG files to PDF format. The ERP system this project was going to be a part of shipped with iText 1.02 so that is why I initially decided to use that library for the PDF manipulation. As part of my tuning effort I decided to try the latest version, 2.0.4. On average performance improved over 40%. As an added bonus some TIF files that failed to convert in the prior 1.02 version were handled flawlessly by the newer release.

In the near future I would like to compare the performance against other Java PDF libraries (such as PDFBox) to see how iText compares. The code that handles the PDF manipulation is isolated from the rest of the logic and implements an interface so it shouldn't be too difficult to try the test since the implementing class is plugable.

Couple lessons learned for me are:
  1. Write classes that do one thing and do it really well. I was lucky here, my project is relatively small and the code was well isolated making the upgrade in versions easy to test side by side.
  2. For sourceforge projects that I rely on I will sign up for the release mailing list and try out new versions. Open source projects like iText are continually evolving. I made a huge mistake of thinking that the art of PDF manipulation would not have advanced much since the release of 1.02 (which I think was sometime in 2004).
  3. iText is a great PDF library for Java. I had never used this library before this project but had heard a lot about it. What really impresses me the most about the project is the documentation and the fantastic examples on the site. I was able to use a lot of code from the examples and that left me to focus more on my program's logic rather than on the details of merging PDF files or converting images to PDF.
One last thing I want to mention was how painless the transition was from release 1.02 (circa 2004) to the latest release of 2.0.4. Just had to change 2 method calls from deprecated methods to new ones that were direct replacements. Great library, fast, stable API, well documented, definitely recommend it.

Friday, June 22, 2007

All Derived, All The Time (I wish...)

I have been working on a PeopleSoft inquiry page a bit this week. I was looking at the specifications for the page and saw I didn't need to create any physical objects in the database (tables or views) to do what I needed to do. I was planning on just using derived tables and values and just loading up a rowset with data from PeopleCode and pushing the rowset to the grid. I was using an existing derived table at row level 0 and created an additional derived table with all of the fields I needed for row level 1 (the grid). Everything derived. I added my fields at row level 0, added my grid object, added the fields I needed for the grid from the derived record and attempted to save. Error message of no data found in row level 1. What? I went back and looked, verifying that I had added the fields. Tried to save again. Same error. I went and showed one of my colleagues who also theorized that what I was trying to do should work. He got the same error. He added a field from a table that physically exists in the database and it saved. So the moral of the story is that in a PeopleSoft page, you can have all derived field at row level 0, but you must have at least one field that physically exists in the database in row level 1 for the page to work.

This posting probably is rambling and doesn't flow well, but hey, it's late on a Friday...

-E

Thursday, June 21, 2007

PeopleSoft and Firefox, Part One

I wanted to leave the door open for part two, if ever need be...

One ongoing gripe I have with Firefox is the speed of the browser in PeopleSoft. IE is hands down faster and I have yet to figure out why. Does IE cache more of the HTTPS pages where Firefox does not? Does the IE Trident rendering engine just work better with PeopleSoft than the Gecko rendering engine in Firefox? Did a very un-thorough Google search with nothing much to show for it. If anyone has an ideas or opinions, please post a comment.

Wednesday, June 20, 2007

NotePad++

We have been test-driving Notepad++ around here for the past couple of days. With the recent release of Textpad 5, we have been looking to see what else is available out there that is open source. We have been big Textpad fans for the last several years and have been looking forward to the changes that were coming with release 5, but the load time to open the app is huge. We have been conditioned for software to be lightning fast, so Textpad 5 left us wanting. I tried to revert back to Textpad 4, but had all kinds of little registry gremlins that caused me grief.

We have PSPad in the running too, but it has the same app load delay as Textpad 5 (but it has a ton of cool features).

Anyway, we will be using Notepad++ here, probably until next week until another text editor draws our attention.

Open Source Desktop Encryption Solutions

Let me throw out a couple of scenarios:

1.) You get a call from a user who needs a data extract of "XYZ" data. You run the extract, export the data to a spreadsheet and send the data back to the requester.

2.) You have 10 databases you work in, all with different passwords.

Consider these questions:
In scenario 1, what if the extract had some sensitive information in it? Where is that extract, in your local temporary folder? Is that temp folder under your profile (probably not) and who has access to it? What if it is sitting in your local temp folder and your laptop grows legs...

In scenario 2, do you remember all of you passwords or do you store you passwords in text docs locally, in a wiki, post-it note on your desk, etc. to make it easier to access the userid/ passwords?

TrueCrypt: This software allows you to create a encrypted partition in a file (yes, a file) on your harddisk that you can mount as a volume in the OS. Save anything you want to it.This is perfect for using as a temp directory. Provides a solution for scenario 1. If your laptop does take up jogging, the file is a bunch of gibberish without the passphrase.

KeePass: This software fixes the problem presented in scenario 2. The software basically keeps an encrypted database of your any userid/passwords you want to store. Add as many as you want. You only need to remember the single, encrypted passphrase to access the database.

Both of these products are available on multiple platforms. I can only vouch for the effectiveness on Windows XP.

Just to have one less thing to remember, save your KeePass database inside of your TrueCrypt partition.