Java Class

This chapter provides an overview of Java class and discusses the following topics:

Click to jump to parent topicUnderstanding Java Class

Using the PeopleCode Java functions, you can access Java classes, or create instances of Java objects. Calling a Java program from PeopleCode can greatly extend your application. Also, the PeopleCode integration with Java enables you to pass parameters such as record, record fields, or rowsets into Java programs.

The PeopleCode Java functions are:

See Also

http://java.sun.com/index.html

Click to jump to parent topicSupported Versions of Java

The supported platform database lists all supported versions of the Java Runtime Environment (JRE) for each version of PeopleTools on each supported operating system platform.

See My Oracle Support, “Platform Certifications.”

Oracle also bundles a supported JRE version with PeopleTools for all supported operating system platforms except the z/OS platform. For z/OS, you will have to install a supported JRE. To determine which JRE is bundled with your version of PeopleTools, see the README file in the PS_HOME\jre directory.

Click to jump to parent topicJava Packages and Classes Delivered with PeopleTools

Java classes delivered with PeopleTools are located in the following directory:

PS_HOME\class

For PeopleSoft software, we typically use a standard package hierarchy:

com.peoplesoft.prodline.prodcode

In this hierarchy, prodline is the company standardized product line code (for example, hrms) and prodcode is the product code unique within the product line (for example, hr).

In addition, if there are any classes that are common across products, they are placed into the common package for that product line, that is:

com.peoplesoft.prodline.common

See Also

http://java.sun.com/docs/codeconv/index.html

Click to jump to parent topicSystem Setup for Java Classes

If you access only the classes that come defined with PeopleTools, you don't need to do any additional setup.

If you want to access third-party Java classes or your own custom Java classes in the PeopleTools environment (that is, access these classes through PeopleCode), you must place the class files in specified locations or include the class files in JAR files in specified locations.

Note. Oracle recommends using the utility that comes with the Java SDK for creating JAR files.

When PeopleTools loads the Java Virtual Machine (JVM), PeopleTools builds a class path for the JVM from the following elements. The following numbering indicates the search order that the JVM would use for locating a specified Java class:

  1. Class files in the PS_HOME\class directory.

  2. Class files in JAR files in the PS_HOME\class directory.

  3. Class files in the PS_HOME\appserv\classes directory.

  4. Class files in JAR files in the PS_HOME\appserv\classes directory.

  5. For each directory listed in the “Add To CLASSPATH” parameter of the psappsrv.cfg configuration file:

    1. Class files in the specified directory.

    2. Class files in JAR files in the specified directory.

  6. For each directory listed in the PS_CLASSPATH environment variable:

    1. Class files in the specified directory.

    2. Class files in JAR files in the specified directory.

For example, if PS_CLASSPATH is “dir1;dir2”, the search order for item 6 described previously would be:

  1. Class files in dir1.

  2. Class files in JAR files in dir1.

  3. Class files in dir2.

  4. Class files in JAR files in dir2.

Note. PeopleTools uses the -classpath option when it loads the JVM, which overrides the CLASSPATH environment variable. Therefore, do not use the CLASSPATH environment variable to identify third-party or custom Java classes that you want to access in the PeopleTools environment.

Note. PeopleTools does not guarantee the order in which JAR files within a directory will be added to the class path. If it is necessary to impose a search order on JAR files, then the JAR files must be in separate directories.

Like most environment variables, you can specify more than one entry in PS_CLASSPATH. On Windows, the PS_CLASSPATH entries are separated by semicolons. On Unix, they’re separated by colons.

The following PS_CLASSPATH is for Windows:

c:\myjava;d:\myjava\com\mycompany\myproduct; . . .

The following PS_CLASSPATH would be for Unix:

/etc/myjava:/home/me/myjava/com/mycompany/myproduct: . . .

When developing your own classes you must be aware that most JVMs cache the class definitions. This means that even if you update the class files, a running JVM (inside an application server, for example) has already loaded and is referencing the old versions of the class files. The JVM won’t pick up the new versions of the class files. You must restart the application server to make the JVM reload the updated classes.

See your system documentation for more information about setting an environment variable.

Click to jump to parent topicFrom PeopleCode to Java

In this section, we provide an overview of state management concerns and present the following examples:

Click to jump to top of pageClick to jump to parent topicState Management Concerns

The application server is stateless, which means that it doesn’t keep any information (state) for its clients between calls to it. For one reason, calls to the application server can use different actual servers for different calls. When you are using Java in the application server, be careful to not leave state in the JVM that would cause your application to fail if a different application server (which would use a different invocation of the JVM) was used for subsequent calls. One method to leave state in the virtual machine is to use static (class) variables.

Similar considerations to these apply using Java in Application Engine programs, though here the difficulty arises when you try to checkpoint and then restart the program. The restart starts with a JVM invocation that doesn’t have any of the state you might have stored into the JVM before the checkpoint.

Variables of the type JavaObject cannot have global or component scope because of this lack of ability to save the state of these objects.

An example of this is issuing messages. When you're running with PeopleSoft Pure Internet Architecture and issue a message, the message is produced by an end-user action, so the Application Server gathers up its state to return it to the browser. This state saving attempts to save the current PeopleCode execution state, causing it to issue an error because of the JavaObject.

The solution is to not have any non-null JavaObject objects when the message is issued.

The following is a simple Java program:

public class PC_Java_Test{ public String pcTest(){ String message; message = "PeopleCode is successfully executing Java."; return message; } }

Here is the PeopleCode that calls this Java program. Note that the JavaObject is set to NULL before the message is issued.

&java_test = CreateJavaObject("PC_Java_Test"); &java_message = &java_test.pcTest(); ​&java_test = Null; WinMessage(&java_message);

In SavePreChange, Workflow, or SavePostChange PeopleCode the situation is more complicated. Usually messages with a zero style parameter (no buttons other than OK and perhaps Explain, therefore no result possible except OK) are queued up by the Application Server. They are output by the browser when the service completes, so the serialization won't happen until after the PeopleCode has finished, so you won't have to set your JavaObject to null. With other kinds of messages, you must do this.

Click to jump to top of pageClick to jump to parent topicCreateJavaObject Example

The following is an example program creating a Java object from a sample program that generates a random password.

/* Example to return Random Passwords from a Java class */ Local JavaObject &oGpw; /* Create an instance of the object */ &oGpw = CreateJavaObject("com.PeopleSoft.Random.Gpw_Demo"); &Q = "1"; /* Call the method within the class */ &NEW_VALUE = &oGpw.getNewPassword(&Q, PSRNDMPSWD.LENGTH); /* This is just returning one value for now */ PSRNDMPSWD.PSWD = &NEW_VALUE;

Click to jump to top of pageClick to jump to parent topicCreateJavaArray Example

Suppose we had a PeopleCode array of strings (&Parms) that we wanted to pass to a Java method xyz of class Abc. This example assumes that you don't know when you write the code just how many parameters you will have.

Local JavaObject &Abc, &RefArray; Local array of String &Parms; &Parms = CreateArray(); /* Populate array how ever you want to populate it */ &Abc = GetJavaObject("com.peoplesoft.def.Abc"); /* Create the java array object. */ &JavaParms = CreateJavaArray("java.lang.String[]", &Parms.Len); /* Populate the java array from the PeopleCode array. */ &RefArray = GetJavaClass("java.lang.reflect.Array"); For &I = 1 to &Parms.Len &RefArray.set(&JavaParms, &I - 1, &Parms[&I]); End-For; /* Call the method. */ &Abc.xyz(&JavaParms);

Click to jump to top of pageClick to jump to parent topicGetJavaClass Example

The following example gets a system class.

&Sys = GetJavaClass("java.lang.System"); &Sys.setProperty("java.security.policy", "C:\java\policy"); WinMessage("The security property is: " | &Sys.getProperty("java.security.policy")); &Props = &Sys.getProperties(); &Props.put("java.security.policy", "C:\java\policy"); &Sys.setProperties(&Props); WinMessage("The security property is: " | &Sys.getProperty("java.security.policy"));

Click to jump to parent topicFrom Java to PeopleCode

The Java classes delivered with PeopleTools enable you to call PeopleCode from your Java program. Calling into PeopleCode works only from Java code that you have initially called from PeopleCode.

You must call PeopleCode facilities only from the same thread that was used for the call into Java. PeopleTools is not multithreaded.

You cannot call any PeopleCode facility that would cause the server to return to the browser for an end-user action, because the state of the Java computation cannot be saved and restored when the action is complete.

See Also

Considerations When Using the PeopleCode Java Functions

Click to jump to top of pageClick to jump to parent topicSysVar Java Class

Use the SysVar Java Class to refer to System Variables, such as %Language or %DBType.

For example, %Session, becomes SysVar.Session()

See Also

System Variables

Click to jump to top of pageClick to jump to parent topicSysCon Java Class

Use the SysCon Java Class to refer to system constants, such as %SQLStatus_OK or %FilePath_Absolute.

For example, %CharType_Matched becomes SysCon.CharType_Matched.

Click to jump to top of pageClick to jump to parent topicFunc Java Class

Use the Func Java Class to refer to built-in functions, such as CreateRowset or GetFile.

For example, SetLanguage(LANG_CD) becomes Func.SetLanguage(LANG_CD)

Click to jump to top of pageClick to jump to parent topicName Java Class

The Name Java Class enables you to use the PeopleSoft reserved item references. This enables you to reference pages, components, records, fieldnames, and so on.

For example, in PeopleCode you can refer to a record field using the following:

recname.fieldname

With the Name class, you can use a similar construct:

new PeopleSoft.PeopleCode.Name("RECNAME", "FIELDNAME");

Note that these must be in the exact case as the item. As all PeopleTools items are named in uppercase, that means you must use uppercase.

As another example, in PeopleCode you can refer to a page using the following:

PAGE.pagename

In Java, it would be:

new PeopleSoft.PeopleCode.Name("PAGE", "PAGENAME");

Click to jump to top of pageClick to jump to parent topicAccessing PeopleCode Objects

The existing PeopleCode classes (like Array, Rowset, and so on) have properties and methods you can access.

Here is an example of a Java program that uses PeopleCode objects to access the database:

/* * Class Test * * This code is used to test the Java/PeopleCode interface. * */ import PeopleSoft.PeopleCode.*; public class Test { /* * Test * * Add up and return the length of all the * item labels on the UTILITIES menu, * found two different ways. * */ public static int Test() { /* Get a Rowset to hold all the menu item records. */ Rowset rs = Func.CreateRowset(new Name("RECORD", "PSMENUITEM"), new Object[]{}); String menuName = "UTILITIES"; int nRecs = rs.Fill(new Object[]{"WHERE FILL.MENUNAME = :1", menuName}); int i; int nFillChars = 0; for (i = 1; i <= rs.getActiveRowCount(); i++) { String itemLabel = (String)rs.GetRow(i) .GetRecord(new Name("RECORD", "PSMENUITEM")) .GetField(new Name("FIELD", "ITEMLABEL")) .getValue(); nFillChars += itemLabel.length(); } /* Do this a different way - use the SQL object to read each menu item record. */ int nSQLChars = 0; Record menuRec = Func.CreateRecord(new Name("RECORD", "PSMENUITEM")); SQL menuSQL = Func.CreateSQL("%SelectAll(:1) WHERE MENUNAME = :2", new Object[]{menuRec, menuName}); while (menuSQL.Fetch(new Object[]{menuRec})) { String itemLabel = (String)menuRec .GetField(new Name("FIELD", "ITEMLABEL")) .getValue(); nSQLChars += itemLabel.length(); } return nFillChars + 100000 * nSQLChars; } } This can be run from PeopleCode like this: Local JavaObject &Test; Local number &chars; &Test = GetJavaClass("Test"); &chars = &Test.Test(); &Test = Null; WinMessage("The character counts found are: " | &chars, 0);

Click to jump to top of pageClick to jump to parent topicUsing Application Classes From Java to PeopleCode

You call a Java program from an Application Class the same way you do using any other PeopleCode program, that is, by using one of the existing Java class built-in functions.

Calling an Application Class from a Java program has the following considerations:

The following is an example of how to call an Application Class from a Java program.

This is the Java program:

package com.peoplesoft.pcode; import PeopleSoft.PeopleCode.*; public class foo { public foo() { } public String getString() { Object foo = Func.CreateObject("GTP:Foo", new Object[]{}); return (String)Func.ObjectDoMethod((Peer)foo, "GetString", new Object[]{}); } }

The following is the Application Class Foo, in the Application Package Foo:

class Foo method GetString() Returns string; end-class; method GetString /+ Returns String +/ Return "Hello"; end-method;

The following is the PeopleCode program that starts it all:

Local JavaObject &foo = CreateJavaObject("com.peoplesoft.pcode.foo"); GTP_PARSER.GTP_STR_RESULT = &foo.getString();

Click to jump to parent topicPeopleCode and Java Data Types Mapping

The following table describes the matching of types for resolution of overloaded Java methods and basic conversions. The first Java Type/Class is the one that is produced in the absence of any other type of information.

PeopleCode Type

Java Type/Class

Float

double, float

Number

double, float, byte, char, short, int, long

Integer

int, byte, char, short, long

Boolean

Boolean

String

java.lang.String

Date

java.sql.Date

Time

java.sql.Time

Date Time

java.util.Date

any kind of object

any kind of object

The following table represents the conversions done to produce the Java class java.lang.Object. In addition to these, the conversions (listed in the previous table) from String onwards are done to produce a java.lang.Object.

PeopleCode Type

Java Type/Class

Float, Number

java.lang.Double

Integer

java.lang.Integer

Boolean

java.lang.Boolean

The following table represents other conversions that are done as required by the signature of a Java method or constructor.

PeopleCode Type

Java Class

Integer, Number, Float

java.lang.Integer, java.lang.Byte, java.lang.Character, java.lang.Short, java.lang.Long, java.lang.Float, PeopleSoft.PeopleCode.intHolder, PeopleSoft.PeopleCode.doubleHolder

String

PeopleSoft.PeopleCode.StringHolder

peoplecode builtin class Xxx

PeopleSoft.PeopleCode.Xxx

JavaObject

corresponding Java object

Click to jump to parent topicConsiderations When Using the PeopleCode Java Functions

Some PeopleCode built-in functions can't be called from a Java program. Many of these restrictions arise because you can't serialize Java objects. Inside Java, you can't serialize and save the state of the JVM.

This means that you cannot call the following built-in functions:

When you're creating your Java program, keep the following points in mind:

When setting a null date in Java, use the following:

myField.SetValue("");

See Also

Think-Time Functions

Click to jump to parent topicCopying Arrays of Data Between PeopleCode and Java

When PeopleCode is called from your Java program it executes what are called native methods. These methods looks like regular Java methods in their definition but are implemented in the PeopleTools layer. In order to go from Java into PeopleTools you have to use an interface called the Java Native Interface (JNI). There is a cost associated with each transition across the JNI. Using the CopyToJavaArray and the CopyFromJavaArray functions may improve your performance, as they act as a type of bulk data copy that minimizes the transition overhead.

For example you could copy an array by copying each element using the array's Get method. However, that would require traversing the JNI twice for each element; once going into Tools and once coming back from Tools. Not only is there transition overhead but there is also conversion between object types. For example a PeopleCode string has to be converted to a Java String and vice-versa. While these two builtins do not eliminate the latter conversions, they minimize the number of transitions across the JNI.

These functions can be used when you are selecting data into a PeopleCode array and you want to copy that data into a Java array.

These functions also allow you to supply an optional parameter that specifies the list of items you want copied.

See Also

CopyFromJavaArray

CopyToJavaArray

Click to jump to parent topicConsiderations Working with the Java Garbage Collector

Memory is managed in the JRE by the Java garbage collector. Because PeopleTools has no control over when the Java garbage collector runs (apart from a user in their Java program calling it using system.gc()), PeopleTools interacts dynamically with the Java runtime garbage collector. In particular, PeopleCode objects created from a Java program (such as records, fields, and so on,) are in effect peer objects of real PeopleCode objects in PeopleTools. The release of these objects must be linked. Using the weak reference mechanism in Java, PeopleTools dynamically interracts with the Java garbage collector each time the execution thread passes through the JNI. This allows long-running Java applications in a PeopleTools context to function without having to wait for an "end of service" event for object cleanup.

There might be occasions where a Java application creates many application classes and wants to force the PeopleTools garbage collector to run. That can be achieved by calling the CollectGarbage function. This is not normally necessary.

See Also

CollectGarbage

Click to jump to parent topicError Handling and the PeopleCode Java Functions

Java functions throw exceptions to indicate something unusual has happened. However, all exceptions from Java called by PeopleCode are turned into fatal errors. You can catch these exception by enclosing the call to Java in a Try-Catch PeopleCode block. If you do not try to catch these exception, the PeopleCode program is terminated, and the user transaction must be canceled.

PeopleSoft recommends that you write a Java wrapper to handle errors.

Use either the All or None built-in functions to check values that are returned if you think you may call a Java method that is defined to return a string, but returns a Null object reference instead. Java Null object references are automatically converted into PeopleCode Null object references.

Accessing the Application Log File

For doing additional error handling in your application, you can access the application log file using the PeopleCode WriteToLog built-in function. For example:

Func.WriteToLog(SysCon.ApplicationLogFence_Level1, myLogString);

See WriteToLog.

Click to jump to parent topicThe Java Debugging Environment

To use Sun's JPDA V1.0 debugging architecture, you must do the following. These instructions are general: how you actually set up the debugger depends on your system.

To use the Java Debugging Environment (JDB):

  1. Download and install a copy of JPDA V1.0.

  2. Set the path for your system.

    Suppose you install JPDA V1.0 in C:\jpda. Set your PATH environment variable to include C:\jpda\bin.

  3. Set the path for the application server.

    For the application server, set the Domain Settings/Add to PATH to include C:\jpda\bin.

  4. Set the JavaVM Options.

    Set the JavaVM Options to be something like the following (see the JPDA documentation for a more complete example):

    -Xdebug -Djava.compiler=NONE -Xnoagent -Xrunjdwp:transport=dt_socket,suspend=⇒ n,address=8765,server=y

  5. Run the debugger.

    After starting the tools session and causing it to start the JVM, you can use the JDB command line debugger that comes with JPDA, using a command like the following:

    jdb -connect com.sun.jdi.SocketAttach:port=8765

    You can also use the (no cost) Forte for Java Community Edition IDE from Sun or any of the Java IDEs noted on the JPDA pages.

See Also

http://java.sun.com/products/jpda

http://www.sun.com/forte/ffj/ce/index.html

Click to jump to parent topicData Type of a Java Object

You should declare a Java object as type JavaObject. For example:

Local JavaObject &MyJavaClass;

Note. Java objects can be declared as type Local only.

Click to jump to parent topicScope of a Java Object

A Java object can be instantiated from PeopleCode only. This object can be used anywhere you have PeopleCode, that is, in an application class, Component Interface PeopleCode, record field PeopleCode, and so on.

Click to jump to parent topicPeopleCode Java Built-in Functions

CopyFromJavaArray

CopyToJavaArray

CreateJavaArray

CreateJavaObject

GetJavaClass