Calling Gosu from Java by using reflection
From Java, you use reflection to access Gosu types. Reflection means asking the
type system about types at run time to get data, set data, or invoke methods. Reflection is a
powerful way to access type information at run time, but is not type safe. For example,
language elements such as class names and method names are manipulated as
String values. Be careful to correctly type the names of classes and
methods because the Java compiler cannot validate the names at compile time.
To use reflection from Java, you use the same utility class gw.lang.reflect.ReflectUtil that provides reflection to Gosu classes. The ReflectUtil class contains methods to get information about a class, get information about members (properties and methods), and invoke static class methods or instance methods.
To access Gosu API classes from Java, including the classes that you use to implement reflection, you must add gosu-core-api-release.jar to your Java project's class path.
To run the Java code that accesses Gosu classes, you must be in the PolicyCenter application context. You cannot run that code from your Java IDE because the IDE project does not initialize Gosu. When PolicyCenter starts, it performs that initialization. You can test the Java class and its methods by running them in Guidewire Studio with a running server.
Improving type safety in using reflection
- Create a Java interface containing only those methods that you need to call from Java.
For getting and setting properties, define the interface using getter and setter
methods, such as
getMyFieldandsetMyField.package doc.example.reflection.java; public interface MyJavaInterface { public String getMyField(); public void setMyField(String value); } - Compile the interface and place the class file in its complete hierarchy in the PolicyCenter/modules/configuration/plugins/Gosu/classes folder. If the interface extends a plugin interface, use the PolicyCenter/modules/configuration/plugins/shared/classes folder instead.
- Create a Gosu class that implements that interface. The Gosu class can contain
additional methods as well as the interface
methods.
package doc.example.reflection.gosu class MyGosuClass implements doc.example.reflection.java.MyJavaInterface { public static function myMethod(input : String) : String { return "MyGosuClass returns the value ${input} as the result!" } override property get MyField():String{ print("Get MyField called") return "test" } override property set MyField(value:String){ print("hello") } } - In code that requires a reference to the object, use
ReflectUtilto create an instance of the Gosu class. The following approaches are available.- Create an instance by using the constructGosuClassInstance
method in
ReflectUtil.package doc.example.reflection.java; import gw.lang.reflect.ReflectUtil; public class MyJavaClass { ... public void accessGosuClass(String gosuClassName) { Object myGosuObject = ReflectUtil.constructGosuClassInstance(gosuClassName); } } - Define a method on an object that creates an instance, and call that method with
the invokeMethod or invokeStaticMethod method
in
ReflectUtil, as appropriate.To see a list of available methods on the created instance, use
ReflectUtil.invokeMethod(myGosuObject, "@IntrinsicType").getClass().getMethods(). Getting the value of a property requires the@symbol before the property name. Alternatively, use the getProperty method.Note: In both cases, any new object instances at compile time that are returned by ReflectUtil have the type Object.
- Create an instance by using the constructGosuClassInstance
method in
- Downcast the new instance to your new Java interface and assign a new variable of that
interface
type.
MyJavaInterface myJavaInterface = (MyJavaInterface) myGosuObject;You now have an instance of an object that conforms to your interface.
- Call methods on the Gosu instance as you normally would from Gosu. The getters,
setters, and other method names are defined in your interface, so the method calls are
type safe. For example, the Java compiler can protect against misspelled method
names.
myJavaInterface.setMyField("New value");
Calling a Gosu method from Java by reflection
If you need to call a method by reflection without using the previous technique, you can
pass parameter values as additional arguments to the invokeMethod or
invokeStaticMethod method in ReflectUtil.
package doc.example.reflection.gosu
class MySimpleGosuClass {
public static function myMethod(input : String) : String {
return "MyGosuClass method myMethod returns the value ${input} as the result!"
}
}MyGosuClass by
calling the ReflectUtil.invokeStaticMethod
method:package doc.example.reflection.java;
import gw.lang.reflect.ReflectUtil;
public class MyNonTypeSafeJavaClass {
public void callStaticGosuMethod() {
// Call a static method on a Gosu class
Object o = ReflectUtil.invokeStaticMethod("doc.example.reflection.gosu.MySimpleGosuClass", "myMethod", "hello") ;
// Print the return result
System.out.println((String) o);
}
}