Introduction to the Java Gateway
This chapter introduces the Java Gateway, which provides an easy way for InterSystems IRIS® to interoperate with Java components.
The Java Gateway server runs within a JVM, which can be on the same machine as InterSystems IRIS or on a different machine. Complete the following setup steps on the machine on which the Java Gateway will run:
Install the Java Runtime Environment (for example, JRE 1.8.0_67).
Make a note of the location of the installation directory for JRE. This is the directory that contains the subdirectories bin and lib.
This is the value that you would use for JAVA_HOME environment variable. For example: c:\Program Files\Java\jre8
You use this information later when you configure your production.
Also make a note of the Java version. If you are uncertain about the Java version, open a DOS window, go to the bin subdirectory of your Java installation, and enter the following command:
You should receive output like the following, depending on your platform:
java version "1.8.0_67" Java(TM) SE Runtime Environment (build 1.8.0_67-b24) Java HotSpot(TM) 64-Bit Server VM (build 23.19-b22, mixed mode)
It is not necessary to set any environment variables. To access the JVM, InterSystems IRIS uses information contained in the production.
Starting and Stopping the Gateway
When using the Java Gateway with a production, it is a good practice to have the production start the Java Gateway server at production startup, and stop it at production shutdown. This happens automatically if you add a Java Gateway business service (EnsLib.JavaGateway.Service) to the production.
Before you can use the Java Gateway, you must use some mechanism to start the Java Gateway server and tell InterSystems IRIS the name of the host on which the Java Gateway server is running. You cannot start the Java Gateway from a remote server. You can start the Java Gateway server in one of the following ways:
Automatically, by adding a Java Gateway business service (EnsLib.JavaGateway.Service) to the production. The Java Gateway server starts when the production starts.
Manually , by using the Management Portal (System Administration > Configuration > Connectivity > Object Gateways ).
Manually , by calling the %New() method of %Net.Remote.Gateway .
Manually, by calling the business service StartGateway() method.
Manually, by entering a command at the Terminal command prompt.
Once started, the Java Gateway server runs until it is explicitly shut down. You can stop the Java Gateway server in one of the following ways:
Automatically, by adding a Java Gateway business service to the production. The Java Gateway server stops when the production stops.
Manually, by calling the StopGateway() method of the business service.
If you make changes to your Java classes and want them available to the Java Gateway, you can stop and then restart the Java Gateway using any of these methods.
Connecting and Disconnecting
Once the Java Gateway server is running, each InterSystems IRIS session that needs to invoke Java class methods must create its own connection to the Java Gateway server. You can connect InterSystems IRIS with the Java Gateway server by calling the ConnectGateway method of the business service, or by calling the Java Gateway API %Connect() method.
The Connect command sets off the chain of sequential events (1), (2), and (3) shown in the following Connecting to a Java Gateway Worker Thread diagram:
ObjectScript code sends a connection request.
Upon receiving the request, the Java Gateway server starts a worker thread in which the Java class methods subsequently run.
The connection between this Java Gateway worker thread and the corresponding InterSystems IRIS session remains established until it is explicitly disconnected.
ObjectScript code that establishes a worker thread must explicitly disconnect before exiting. Otherwise, the assigned port for the connection stays “in use” and is unavailable for use in other connections. ObjectScript code can disconnect its thread by calling the Java Gateway API %Disconnect() method.
Java Gateway Modes
Java Gateway has two main modes of manipulation of Java objects:
Proxy Object Mode — Allows you to statefully manipulate Java Objects from within InterSystems IRIS.
Stateless Service Mode — Allows you to make simple calls to Java methods and return the results from within InterSystems IRIS.
Proxy Object Mode
Proxy Object Mode provides an easy way for InterSystems IRIS to interoperate with Java components. It allows Java Gateway to instantiate an external Java object and manipulate it as if it were a native object within InterSystems IRIS.
There are currently two kinds of proxy objects:
Static proxies (described in this section) 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 (described in the next chapter, Using Dynamic Gateways) are created at runtime by introspecting the current version of the Java class. They are not projected and stored as standard ObjectScript classes; they are simply created and used as needed by your application, and always reflect the current version of the Java class.
In use, dynamic proxies look and work exactly like static proxies. The only difference is how they are created. Static proxies have some useful features, and will continue to be supported, but dynamic proxies are recommended for most new development.
Proxy Object Mode Architecture
The external Java object is represented within InterSystems IRIS by a “wrapper” or “proxy” class. The proxy object appears and behaves just like any other InterSystems IRIS object, but it has the capability to issue method calls out to a Java virtual machine (JVM), either locally or remotely. Any method call on the proxy object triggers the appropriate class method inside the JVM.
You can use the Java Gateway to create proxy InterSystems IRIS classes for custom Java components. You can also create proxy mappings to existing Java interface specifications, such as the Java Database Connection (JDBC), Java Message Service (JMS), Enterprise Java Beans (EJB), Java Connector Architecture (JCA), etc. InterSystems IRIS can use this mapping to work with any implementation that is compliant with one of these specifications.
When generating proxies from large Java libraries and frameworks, the best approach is to build a small wrapper class that exposes just the functionality you want and then create a proxy for this wrapper. This makes the API between InterSystems IRIS and Java very clean and eliminates many potential issues dealing with how to map more esoteric features to a proxy object.
The following diagram provides a conceptual view of InterSystems IRIS and the Java Gateway at runtime while using Proxy Object Mode.
The Java Gateway server runs in the JVM. InterSystems IRIS and the JVM may be running on the same machine or on different machines. The items (1), (2), and (3) in the preceding diagram represent the relationships established by the commands that set up this operational model:
Later sections in this chapter explain how these commands work to set up InterSystems IRIS proxy classes for Java code, as well as how the proxies work once these relationships are set up; see “Proxy Call Sequence” for details.
Importing Java Classes
The Java Gateway API %Import() method sets off the chain of sequential events (1), (2), and (3) shown in the following diagram:
The InterSystems IRIS session sends an import request.
Upon receiving the request, the Java Gateway worker thread introspects the indicated Java packages and classes.
If it finds any Java classes that are new or changed, or that have no proxy classes on the InterSystems IRIS side, the thread generates new proxy classes for them.
The Java Gateway import only imports classes, methods, and fields marked as public.
Proxy Call Sequence
A call to any InterSystems IRIS proxy method initiates the following sequence of events:
All InterSystems IRIS proxy parameters are written into the output buffer.
A message containing the method name and parameters is sent to the Java Gateway worker thread.
The Java Gateway worker thread consumes the message, reads the parameters, finds the appropriate method or constructor call, and invokes it using Java reflection. If the given method is an overloaded method, the gateway uses a method overload algorithm to find the right Java method version. For details, see “Overloaded Methods” in the chapter “Mapping Specification.”
The results of the method invocation (if any) are sent back to the InterSystems IRIS side over the same connection.
The InterSystems IRIS proxy processes any return values and the method call returns.
Stateless Service Mode
The Stateless Service Mode allows simple and efficient calls out to a particular Java service. A Java service is any implementation of the com.intersystems.gateway.Service interface. Only the following method needs to be implemented:
public byte execute(byte args) throws Throwable;
This method takes a byte array, performs whatever service it needs to do, and produces a byte result. In order to invoke the above Java service method from InterSystems IRIS, call the following %Net.Remote.Gateway method:
Method %ServiceRequest(serviceName As %String, arguments As %String, ByRef response As %String) As %Status
Where serviceName is the name of the implementing Java service class, arguments corresponds to the Java service args and
response corresponds to the Java service result. arguments and result are represented as %Strings on the InterSystems IRIS, and byte arrays on the Java side, meaning any values serialized as such will be accepted by the underlying engine.
The following static method to %Net.Remote.Gateway directly allows invocation of an external Java service:
ClassMethod %RemoteService(host As %String, port As %Integer, serviceName As %String, arguments As %String, additionalClassPaths As %ListOfDataTypes = "") As %String;
The implementation of Java service should never include a callback to InterSystems IRIS as this newly added component is not designed to be reentrant.
For a simple implementation using GSON please see Stateless Service Mode Example.