Skip to main content

Using Dynamic Object Gateways

This chapter describes how to implement Object Gateways using dynamic proxy objects. In previous releases, static proxies had to be generated separately, compiled, and stored in the class library just like any other ObjectScript class (see “Importing Java Classes” in the previous chapter). Dynamic proxy objects do not require a separate import process before the business operation can start. The business operation simply creates and uses them as needed during runtime.

Introducing Dynamic Gateways

All versions of the Object Gateway can instantiate an external Java object and manipulate it as if it were a native InterSystems IRIS object. This is accomplished by creating a proxy object that provides all of the same methods and properties as the corresponding Java object. Any call on the proxy object triggers the corresponding method or property of the Java object. There are currently two kinds of proxy objects:

  • Static proxies are standard ObjectScript classes, which must be individually generated and compiled before they can be used. If a new version of the Java class changes the interface in any way, the corresponding proxy class must be regenerated and recompiled to match it.

  • Dynamic proxies are created at runtime by introspecting the current version of the Java class. All dynamic proxies are instances of %Net.Remote.Object. Although each Object instance appears to have the same methods and properties as the corresponding Java object, it actually uses an internal map of the interface to simulate these features.

In use, static and dynamic proxies are identical except for the way they are instantiated. For example:

// Static proxy: call %New() on a pregenerated class
  set newFruit = ##class(Fruit).%New()

// Dynamic proxy: create an Object instance and specify the class to introspect
  set newFruit = ##class(%Net.Remote.Object).%New(gateway,"Fruit")

When the code is used in a business production, the only noticeable difference is that dynamic gateways eliminate the import process.

Creating and Using a Dynamic Object Gateway

This section describes the complete procedure for creating and running an Object Gateway that uses dynamic proxies:

Get the server definition and make sure the server is running

The Service class provides methods to start, stop, and test the server. Most of these methods require the server definition contained in an ObjectGateway object. In the following example, Service.OpenGateway() returns an ObjectGateway instance defining a server named JavaGate. Service.IsGatewayRunning() uses the information to test the current state of the server, and Service.StartGateway() can start it if necessary.

try {
// Get a ObjectGateway instance that defines the JavaGate server
  set st = ##class(%Net.Remote.Service).OpenGateway("JavaGate",.OG)
  write !, "Using "_OG.Name_" server definition"

// Test to make sure the server is running. If not, start it
  if ('##class(%Net.Remote.Service).IsGatewayRunning(OG.Server,OG.Port,,.status)) {
    // Instantiate the server on the host machine
    set status = ##class(%Net.Remote.Service).StartGateway(OG.Name)
catch ex {
  write !,$system.OBJ.DisplayError(ex.AsStatus())
Exception Handling

Your ObjectScript code should always use try/catch for Object Gateway error handling. When the class running on the host machine encounters an exception, the dynamic proxy will throw %Net.Remote.Exception. In addition to standard status details, the Exception object contains call stack information, which is returned by calling method Exception.StackAsArray(.array). The information may be different between Java and .NET.

Define the location of your Java classes and create a Gateway connection

Each dynamic proxy will access the corresponding Java object through a Gateway object connected to the server. The Gateway object needs a path to each .class or .jar file containing a class you want to use. In this example, the location of the .jar file containing class Fruit is specified in the last argument to Gateway.%Connect().

// define the location of the file containing the Fruit class
set fruitPath = ##class(%ListOfDataTypes).%New()
do fruitPath.Insert("C:\Dev\Fruit.jar")

// Connect a Gateway instance to server JavaGate on the host machine
set GW = ##class(%Net.Remote.Gateway).%New()
set st = GW.%Connect(OG.Server, OG.Port, "USER",,fruitPath)

This example only adds one path, but you can insert a separate path for each .class or .jar file you want to use.

Create a dynamic proxy for Java class Fruit and call some methods

In this example, an new instance of Object is created, specifying Fruit as the Java class to introspect. The resulting dynamic proxy will communicate with the Java object through Gateway instance GW (created in the previous example). Once the dynamic proxy is instantiated, it works just like a static proxy.

// Use GW connection to create a proxy for the Fruit class
set proxyFruit = ##class(%Net.Remote.Object).%New(GW,"Fruit")

write !,
write !,"Current fruit preference: ",!,"   "_proxyFruit.getFruit()
do proxyFruit.setFruit("Jujube")
write !,"Fruit preference has been reset: ",!,"   "_proxyFruit.getFruit()


This Java class displays your favorite fruit.
Current fruit preference: UglyFruit
Fruit preference has been reset: Jujube
Disconnect and shut down the server

The connection remains open and the server continues to run until you explicitly disconnect and shut down. In this example, the Gateway.%Disconnect() method breaks the connection, but the server won’t release the port it uses until the call to Service.StopGatewayObject() stops it.

// Disconnect from the server
  set st = GW.%Disconnect()

// Stop the server
  set st =  ##class(%Net.Remote.Service).StopGatewayObject(OG)

Array Access

When a property is declared as an array, it is projected to the proxy as an instance of %Net.Remote.Object. To create a new array, call the Object.%New() method and use array class name syntax in place of the regular class name. Arguments are used as the initial values for the array. Here are some examples:

Array initialization

Array can be initialized by rank or elements:

// by rank
  set newArray = ##class(%Net.Remote.Object).%New(gateway,"String[2]")

// by elements
  set newArray = ##class(%Net.Remote.Object).%New(gateway,"String[]","A","B","C")

When rank and elements are both specified, rank must match element count.

// both rank and elements specified
  set newArray = ##class(%Net.Remote.Object).%New(gateway,"int[3]",11,22,33)
Getting and setting array elements

Besides supporting all the normal properties and methods available on an array object, Dynamic Gateway supports two special methods for accessing array elements:

  • %get(index)object.%get(index)is translated to object[index]

  • %set(index,value)object.%set(index,value) is translated to object[index] = value.

For example:

  set max = 5
  set arrSize = "String["_(max+1)_"]"  // "String[6]"
  set arr = ##class(%Net.Remote.Object).%New(gateway,arrSize)

// Populate the array using %set()
  for idx=0:1:max {
    set val = $CHAR(65+idx)  // $CHAR(65)=A
    do arr.%set(idx,val) 
// Print the array using %get()
  for idx=0:1:max {
    set val = arr.%get(idx)
    write "arr("_idx_")="_val_"  " 


arr(0)=A  arr(1)=B  arr(2)=C  arr(3)=D  arr(4)=E  arr(5)=F

Gateway Reentrancy

Reentrancy means that when InterSystems IRIS code sends a request to Java, the Java code can respond with a request of its own using the same physical connection and context as the original request. The following is a typical call sequence:

  • Starting from the InterSystems IRIS side, a connection is made to Java using a %Net.Remote.Gateway object, allowing us to create proxy objects that can make calls to Java methods.

  • From a proxy, the Gateway.GatewayContext.getIRIS() method can be called to create an instance of jdbc.IRIS. The IRIS object uses the same connection and context as the proxy, and provides access to all the methods for invoking Native API calls (see “Using the InterSystems Native API for Java”).

  • The IRIS object can call back into InterSystems IRIS, where it can get and set global values or call classmethods and functions. Making one of these calls puts us back in InterSystems IRIS code again.

  • From here, we can make another inner call back to Java using the same Gateway connection. Method ##class(%Net.Remote.Gateway).%GetContextGateway() returns the Gateway object for the current context.

  • Calls back and forth between InterSystems IRIS and Java can go on indefinitely, always using the same connection and context.

Getting a jdbc.IRIS object from GatewayContext()

The following example gets an IRIS object in Java, and uses it to read a global value from the InterSystems database:

IRIS native = GatewayContext.getIRIS();
// Read the value of global ^GlobalName("value2")
if ( native != null ) {
  String globalVal = native.getString("GlobalName","value2");

If the code is not invoked inside a valid Gateway context, the getIRIS() method will return a null object.

Getting a Gateway context object from within Native API calls

This example gets a %Net.Remote.Gateway object for the current context, and uses it to create a proxy for a Java object in the same context:

set gateway = ##class(%Net.Remote.Gateway).%GetContextGateway()
if gateway'=$$$NULLOREF {
  set objFruit = ##class(%Net.Remote.Object).%New(gateway,"Fruit")

If the context is not valid, the Gateway object will be $$$NULLOREF.


In general, reentrancy support is not compatible with prior versions of the Object Gateway .

The Java Fruit Class

This section lists the Fruit class used by most of the examples in this chapter. This trivial Java class has all the features needed to demonstrate a simple proxy object: static class method id(), and property accessors getFruit() and setFruit().

The Fruit class
package demo;
  public class Fruit {
    public static String id() {
      return "This Java class displays your favorite fruit.";
    public String fruit;
    public Fruit () {
      fruit = "Uglyfruit";
    public void setFruit(String newFruit) {
      fruit = newFruit;
    public String getFruit() {
      return "My favorite fruit is "+fruit;
    public static void main(String []args) {
      System.out.println("\nGenerating output from Java class Fruit: ");
      Fruit myFruit = new Fruit ();