Using Java Reflection in PeopleCode - Part 2

If you had referred to part 1 of our post on Using Java Reflection in PeopleCode, we create a very small class file, 'image.class', and tried invoking a method 'square' in that class. When doing so, PeopleSoft was unable to identify which 'square' method to invoke (the class had two square methods, with different inputs) and throwed a nice error on the screen "more than one overload matches".  We decided to spoon-feed PeopleSoft by using Java Reflection techniques. This would help us to use the right method that we are after to get the desired result.

If you had referred to the sample Java code in Part 1, the square method that we are trying to invoke accepts a "double" parameter as input.  The right code to use in such a situation is presented below.

Local JavaObject &Obj_class_l = GetJavaClass("java.lang.Class");
Local JavaObject &Obj_classloader_l = GetJavaClass("java.lang.ClassLoader");
Local JavaObject &Obj_getcoreclass_l = &Obj_class_l.forName("image", False, &Obj_classloader_l.getSystemClassLoader());
Local JavaObject &Obj_doubletype_l = GetJavaClass("java.lang.Double").TYPE;
Local JavaObject &Obj_argtypes_l = CreateJavaObject("java.lang.Class[]", &Obj_doubletype_l);
Local JavaObject &Obj_getcorrectmethod_l = &Obj_getcoreclass_l.getDeclaredMethod("square", &Obj_argtypes_l);
Local JavaObject &Obj_consargarray_l = CreateJavaObject("java.lang.Object[]", CreateJavaObject("java.lang.Double", "2.5"));
Local JavaObject &Obj_finalinvoke_l = &Obj_getcorrectmethod_l.invoke(&Obj_getcoreclass_l, &Obj_consargarray_l);
Error &Obj_finalinvoke_l.toString();

Don't worry, this is just the full code. How I arrived to this approach would be explained shortly. I would prefer to explain this from Top - Bottom. The output we are expecting in this case is 6.25.

For us to know which method to invoke, we need to get into the metadata of our class file. To do that, we create an object  &Obj_class_l of java.lang.Class. Using this object, we will be loading our class file "image.class" and then get into its metadata. 

Now, for us to get into the metadata of "image.class", we need to use  the "forName" method of java.lang.class and pass the class file name.  I first tried the following piece of code

Local JavaObject &Obj_getcoreclass_l = &Obj_class_l.forName("image");

When attempting to run this piece of code, the following error was observed on the screen;

Java Exception: java.lang.ClassNotFoundException: image: during call of java.lang.Class.forName.

This error means, PeopleSoft is not able to locate the class file "image". This could be because of the location of java.lang.class and image.class.  When I tried the following command to get the location; "java -verbose | grep java.lang.Class", I got the following output;

Loaded java.lang.Class from /… /PT846/jre1.4.2/lib/rt.jar]

Now, the class file "image.class" is located in /PT846/appserv/classes directory. This means, we cannot use "forName" directly but go for an alternate option where we tell  PeopleSoft, the exact location of the class file. There is another "forName" method in java.lang.Class, that takes the following inputs

public static Class forName(String name,
                            boolean initialize,
                            ClassLoader loader)

This method will help us to avoid the error, and load the Class file through PeopleCode. So, we declare an object for this method using

Local JavaObject &Obj_classloader_l = GetJavaClass("java.lang.ClassLoader");

and then use the second forname method as per below;

Local JavaObject &Obj_getcoreclass_l = &Obj_class_l.forName("image", False, &Obj_classloader_l.getSystemClassLoader());

This code tells PeopleSoft to load the core class file image, and to locate "image.class" , it needs to refer to the location returned by the method Obj_classloader_l.getSystemClassLoader(). Now, getSystemClassLoader method of java.lang.ClassLoader, returns the following output for me;

sun.misc.Launcher$AppClassLoader

I feel that provides the ability for the "forName" method, to look into the CLASSPATH to get the "image.class" file. So, the object &Obj_getcoreclass_l now has a reference to "image.class". With this reference, we will now be able to probe into the metadata of image.class file and choose the right method to execute..for our case, it is the "square" method with an input parameter type of "double".

We can now move into part 3 of our post, where we will explain how to identify the right method and then invoke it to get the output we are after.

No comments:

Post a Comment