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

If you need to call methods on a Gosu class from Java, the following general steps increase the degree of type safety.
  1. 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 getMyField and setMyField.
    package doc.example.reflection.java;
    
    public interface MyJavaInterface {
      public String getMyField();
      public void setMyField(String value);
    }
  2. 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.
  3. 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")
      }
    }
  4. In code that requires a reference to the object, use ReflectUtil to 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.
  5. 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.

  6. 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.

The following example Gosu class defines a static method:
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!"
  }
}
The following Java code calls the static method defined in 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);
  }
}