
Application Engine can be fairly handy in a PeopleSoft developer's toolchest. Aside from all of the useful batch processing things that it can do, it can also be useful for providing ways of running PeopleCode against a system directly from within Application Designer. This can be used for things like testing some PeopleCode or providing some developer productivity utilities. David Bain and I used to do some presentations on developer productivity for PeopleSoft developers, and taking advantage of Application Engine was one of the tips that we used to always mention.
An example utility is the version control work that we've been doing for our products at Grey Sparling. When you have a project that needs to be checked into the source code control system, the project needs to be split up from one large file into a multitude of separate files (the exact number of objects that you have in your project). We have an App Engine program that does this for us, but we needed a way to specify the exact project name to the program. In regular App Engine programs running on a server, you'd have some page for entering run control parameters and the program would look at these. But when you run the App Engine program directly from within Application Designer, you don't have those facilities available to you.
So what we end up doing is a couple of things. First, we take advantage of the COM integration in PeopleCode and use that to have Internet Explorer provide a prompt with the list of projects in the database.
When you have an Application Engine program open in Application Designer, you can press the traffic light icon or select Edit->Run Program from the menu. You'll get a prompt like
this.
.
I always turn on the save to log checkbox, and then press Enter or click OK. Once the program starts, Internet Explorer pops up the list of projects in the database and lets you select one. The project name that you select is then used by the rest of the Application Engine program to do it's work.

Here's what the code looks like:
SCROLL BOX
The IEPrompt function takes a title and a label and an array of choices and returns back the selected choice. We use a hidden form field as a flag for when the user has made their choice since we can't actually catch COM events from within PeopleCode. The HTML that we generate from PeopleCode is not super fancy, but it gets the job done.
The other functions in the code are to assemble the list of projects from the database into a PeopleCode array and then to put the entire thing together.
How about if you wanted to supply the parameter yourself without getting prompted? Maybe you, as the developer, want to run this AE program as part of a bigger script. The answer is to just pass the parameter on the command line and use a little PeopleCode to parse out the values.
In order to do that, I ported over this C# based command line parser from The Code Project. It was easiest to port by utilizing Java from PeopleCode.
SCROLL BOX
The C# regular expression classes are fairly similar to what is available in Java. The only minor headache was that PeopleTools was having problems looking up one of the Java methods used (which we've seen before in previous blog entries), but that was fairly straightforward to get around. The workaround is to repeatedly compile one of the regular expressions instead of just once, but in this particular usage scenario, the overhead of that is so negligible that we don't care.
As a side note : native regular expression support was added the 1.4 version Java Runtime Environment, so if you're on an older version then you'd need to look at some extra libraries for adding regular expression support, or this code won't work.
Labels: PeopleSoft


I think you've omitted the external function declaration of Sleep on kernel32 library. Also (sorry for nitpicking), this function does not need to return a value, can be used by PeopleCode without &tmp if declared as:
Declare Function Sleep Library "kernel32" (long Value As number);
The return value is a good catch as well. Definitely not nit-picking though. When you get the parameter passing between PeopleCode and .DLLs wrong, then Bad Things can happen.
I used to do a lot more of that years ago for an internal SFA system that we had built in PeopleTools for some international groups in PeopleSoft (using the Windows progress bar for file copies, FTP-ing files, etc.). Since declaring these functions in VB is fairly close to PeopleCode, I used to reference a lot of VB sample code.
For most things that was pretty straightforward, but dealing with structs and nulls was pretty challenging. The secret is to allocate the memory yourself and do some low level poking that way. I don't know how much need there is for that these days, but maybe it's worth a future blog entry.
Of course, even Microsoft gets the translation of the actual API calls into VB code wrong :-)
http://support.microsoft.com/default.aspx?scid=kb;EN-US;q239588
They obviously pinched the same example VB declaration for Sleep() that I did!
Here's the actual function declaration from MSDN
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/sleep.asp
I'd also like to point out another omission: in your command line parsing code snippet, the definition of ParseWindowsCommandLine is not included. My guess is that this is where GetCommandLineA and lstrcpyA are called.
Declare Function Str6Test Library "str6" (string, string, string, string, string, string) Returns integer;
But Peoplesoft returns this Error:
"External function Str6Test not available. This external function was not found in the dll as defined in peoplecode program.
Make sure dll is in the Windows PATH. Verify that the routine is properly linked..."
My machine is Linux and I don't know how to do this call for Linux.
Sorry about my english.
Thanks and Regards
The C function interface that PeopleCode supports works on Unix/Linux as well as Windows, but the naming is different.
Instead of .dll files, you have .so files (so stands for shared object).
The other difference is that on Unix/Linux the .so files are prefixed with "lib". So if you had str6.dll on Windows, you would have libstr6.so on Linux.
Mainly because there's no way to catch IE events from within PeopleCode, so the only way to know what the user is doing is to do polling inside PeopleCode.
Make sure dll is in the Windows PATH. Verify that the routine is properly linked..."
Did I miss some stem in this . Plz help me out
External function '' not available.
The specified external function was not found in the DLL as defined in the PeopleCode program.
Make sure the DLL is in the Windows PATH. Verify that the routine is properly linked. Review the program for errors
One possible reason is that you're not actually exporting the function from your .DLL. I would definitely double-check your .DLL's function exports to be sure your function is there.
Another likely reason is that you have the wrong calling convention for your function. PeopleTools expects that external functions are using standard calling convention (I think that PeopleBooks mentions this), so if you're not using that, then it won't work (although I think that PeopleBooks also mentions that you can declare alternate calling conventions though; can't remember for sure at the moment)
The other possibility is that you are exporting a function out of something that is being compiled as C++ code so your function name is being mangled. Check your function exports to be sure that the name is what you're expecting.
The last tip is to try calling your .DLL function from some other environment (like VB). That can help determine whether the problem is with the .DLL or with the way that you are invoking it from PeopleTools.
Page activate PeopleCode always runs on the application server. Technically, you can call COM objects from PeopleCode running on the application server *if* the app server is running on Windows.
But I doubt that you'd want to load up Internet Explorer on the application server each time that someone opens that page in their web browser. Not so good for performance :-)
Your Blogs have been very useful.
I am facing a problem in trying to call a C function from PeopleCode within an Application engine program. The function is located in a library in LINUX (.so file). To invoke the function I need to set the path for the application to understand where the library sits. I have set the path in CLASSPATH, PS_LIBPATH and LD_LIBRARY_PATH in psconfig.sh file in both the application server and the process scheduler.
Still I get the message "External function 'function_name' not available. Can you suggest whether my steps are correct or is there any other place to set the library path.
Thanks
Shibu K
From the error message that you're getting it sounds like the library is being found, but that the function name is not being located. Could be a problem with name mangling.
Is the library one that you are compiling yourself? or is something general?
Thanks for the quick reply.
The library is provided by an external provider for some functionality which we want to use from PeopleSoft.
In PeopleBooks it is given "To support processes running on an application server, you can declare and call functions compiled in dynamic link libraries on windows (*.DLL files) and shared libraries on UNIX (lib*.so files.) The PeopleCode declaration and function call syntax is the same regardless of platform, but UNIX libraries must be compiled with an interface function."
I am not sure what it means by ".. UNIX libraries must be compiled with an interface function". Is there anything else we need to do apart from calling the library (to compile the library)?
The code I am using is as follows:
Declare Function QABatchWV_Startup Library "libqabwvcda.so"
(integer Value As number) Returns integer As number;
Declare Function QABatchWV_Startup Library "libqabwvcd.so"
(Long Value As number) Returns integer As number;
I also changed the input parameter from integer to long to better match what QAS is looking for.
Their API docs are here http://www.qas.com/downloads/pdf/support/v6/batch/bat_api.pdf
Thanks for pointing the typo.
But unfortunately I get the same error inspite of correcting the name of the library. One point to note is that I have my library files on the machine on which application server is installed and I am trying to call the library using an application engine which runs on a process scheduler installed on a different machine. Should my library files be placed on the machine on which process scheduler is installed.
I am a bit confused about where the application engine looks for to find the library path?
I was trying to generate trace to have a look at why the function cannot be called although the external library is placed in the bin folder in $PS_HOME.
In Appserver logs, I found that although I have mentioned the function name as "QABatchWV_Startup", it tries to look for funtion "QABatchWV_Startup_intf" and shows a message " Unable to find external function 'QABatchWV_Startup_intf' in library 'qabwvcd' ".
There was a point in PeopleBooks which said, "The PeopleCode declaration and function call syntax is the same regardless of platform, but UNIX libraries must be compiled with an interface function". Has this got anything to do with this error?
Any inputs on this will be useful.
Thanks
Shibu Keloth
If I am trying to call a C function from an App Engine PeopleCode, where does my C func need to reside? Is it on the application server or the process scheduler server?
Is there a way to get this working if I place the c library on the Process Scheduler Server?
Thanks
Subash
So, if your App Engine program is running as a scheduled process on the process scheduler machine, then it will get loaded there. If the App Engine is being called on the appserver, then the C function would be running on that appserver machine.