docs.intersystems.com
Home / Using the Java Gateway / Using Dynamic Object Gateways

Using the Java Gateway
Using Dynamic Object Gateways
Previous section           Next section
InterSystems: The power behind what matters   
Search:  


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:
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())
}
Note:
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 !,proxyFruit.id()
write !,"Current fruit preference: ",!,"   "_proxyFruit.getFruit()
do proxyFruit.setFruit("Jujube")
write !,"Fruit preference has been reset: ",!,"   "_proxyFruit.getFruit()
Prints:
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:
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_"  " 
  }
Prints:
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:
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.
Note:
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 ();
      System.out.println(myFruit.getFruit());
    }
  }


Previous section           Next section
Send us comments on this page
View this book as PDF   |  Download all PDFs
Copyright © 1997-2019 InterSystems Corporation, Cambridge, MA
Content Date/Time: 2019-05-24 07:30:26