Using Java Inverse Proxy Objects
The Java Native SDK is designed to take full advantage of Java External Server connections, allowing completely transparent bidirectional communications between InterSystems IRIS and your Java application.
Inverse proxy objects are Java objects that allow you to control ObjectScript target objects over an external server gateway connection. You can use an inverse proxy object to call target methods and get or set target property values, manipulating the target object as easily as if it were a native Java object.
This section covers the following topics:
-
Introducing External Servers — provides a brief overview of external servers.
-
Creating an Inverse Proxy Object — describes methods used to create inverse proxy objects.
-
Controlling a Target Object — demonstrates how inverse proxy objects are used.
-
IRISObject Supported Datatypes — describes datatype-specific versions of the inverse proxy methods.
Introducing External Servers
External Server connections allow InterSystems IRIS target objects and Java objects to interact freely, using the same connection and working together in the same context (database, session, and transaction). External server architecture is described in detail in Using InterSystems External Servers, but for the purposes of this discussion you can think of an external server connection as a simple black box allowing proxy objects on one side to control target objects on the other:
As the diagram shows, a forward proxy object is an ObjectScript proxy that controls a Java object (see “Working with External Languages” in Using InterSystems External Servers for details). A Java inverse proxy works in the other direction, allowing your Java application to control an InterSystems IRIS target object.
Creating an Inverse Proxy Object
You can create an inverse proxy object by obtaining the OREF of an ObjectScript class instance (normally by calling the %New() method of the class) and casting it to IRISObject. (See “Calling ObjectScript Methods and Functions” for more information). The following methods can be used to generate an inverse proxy object:
-
jdbc.IRIS.classMethodObject() calls an ObjectScript class method and returns the result as an instance of Object.
-
jdbc.IRIS.functionObject() calls an ObjectScript function and returns the result as an instance of Object.
If the %New() method successfully creates a new target instance, an inverse proxy object will be generated for the instance. For example, the following call creates an inverse proxy object named test that controls an instance of ObjectScript class Demo.Test:
IRISObject test = (IRISObject)irisjv.classMethodObject("Demo.Test","%New");
-
classMethodObject() calls the %New() method of an ObjectScript class named Demo.Test to create a new target instance of that class.
-
If the call to %New() returns a valid instance of the class, an inverse proxy for the new instance is generated, and classMethodObject() returns it as an Object.
-
In Java, the Object is cast to IRISObject, creating inverse proxy variable test.
Variable test is a Java inverse proxy object for the new target instance of Demo.Test. In the following section, test will be used to access methods and properties of the Demo.Test target instance.
Controlling a Target Object
An inverse proxy object is an instance of IRISObject. It provides methods invoke() and invokeVoid() to call target instance methods, and accessors get() and set() to read and write target properties. The example in this section uses an inverse proxy to control a target instance of ObjectScript class Demo.Test, which includes declarations for methods initialize() and add(), and property name:
Class Demo.Test Extends %Persistent
Method initialize(initialVal As %String)
Method add(val1 As %Integer, val2 As %Integer) As %Integer
Property name As %String
In the following example, the first line creates an inverse proxy object named test for a new instance of Demo.Test (as described in the previous section). The rest of the code uses test to control the target Demo.Test instance.
// Create an instance of Demo.Test and return a proxy object for it
IRISObject test = (IRISObject)irisjv.classMethodObject("Demo.Test","%New");
// instance method test.initialize() is called with one argument, returning nothing.
test.invokeVoid("initialize", "Test One");
// instance method test.add() is called with two arguments, returning an int value.
int sum = test.invoke("add",2,3); // adds 2 plus 3, returning 5
// The value of property test.name is set and then returned.
test.set("name", "Einstein, Albert"); // sets the property to "Einstein, Albert"
String name = test.get("name"); // returns the new property value
In the example above, inverse proxy object test is created by a call to IRIS.classMethodObject(), and the following methods are used to access methods and properties of the Demo.Test target instance:
-
IRISObject.invokeVoid() invokes target instance method initialize(), which accepts a string argument but does not return a value.
-
IRISObject.invoke() invokes target instance method add(), which accepts two integer arguments and returns the sum as an integer.
-
IRISObject.set() assigns a new value to target property name.
-
IRISObject.get() returns the value of target property name.
There are also datatype-specific versions of these methods, as described in the following section.
IRISObject Supported Datatypes
The example in the previous section used the generic set(), get(), and invoke() methods, but the IRISObject class also provides datatype-specific methods for supported datatypes.
The IRISObject.set() method accepts any Java object as a property value, including all datatypes supported by IRIS.set() (see “Class IRIS Supported Datatypes”).
In addition to the generic get() method, IRISObject provides the following type-specific methods: getBoolean(), getBytes(), getDouble(), getIRISList(), getLong(), getObject(), getString(), and invokeVoid().
The IRISObject invoke methods support the same set of datatypes as the IRIS classmethod calls (see “Class Method Calls”).
In addition to the generic invoke() method, IRISObject provides the following type-specific methods: invokeBoolean(), invokeBytes(), invokeDouble(), invokeIRISList(), invokeLong(), invokeObject(), invokeString(), and invokeVoid().
In addition to methods for the standard supported datatypes, IRISObject also provides invokeStatusCode(), which gets the contents of an ObjectScript %Status return value (see “Catching %Status Error Codes”).
All of the invoke methods take a String argument for methodName plus 0 or more method arguments, which may be any of the following types: Integer, Short, String, Long, Double, Float, byte[], Boolean, Time, Date, Timestamp, IRISList or IRISObject. If the connection is bidirectional, any Java object can be used as an argument.
Trailing arguments may be omitted in argument lists, either by passing fewer than the full number of arguments, or by passing null for trailing arguments. An exception will be thrown if a non-null argument is passed to the right of a null argument.