Introduction to the Java Gateway
This chapter introduces the Java Gateway, which provides an easy way for Ensemble to interoperate with Java components. It discusses the following topics:
The Java Gateway server runs within a JVM, which can be on the same machine as Ensemble 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.7.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\jre7
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.7.0_67" Java(TM) SE Runtime Environment (build 1.7.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, Ensemble uses information contained in the production.
Starting and Stopping the Gateway
When using the Java Gateway with an Ensemble 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 Ensemble 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 business service StartGateway() method.
Manually, by calling the %New() method of %Net.Remote.Gateway.
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 Ensemble session that needs to invoke Java class methods must create its own connection to the Java Gateway server. You can connect Ensemble 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:
Caché Basic or 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 Ensemble session remains established until it is explicitly disconnected.
Caché Basic or 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. Caché Basic or 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 Ensemble.
Stateless Service Mode — Allows you to make simple calls to Java methods and return the results from within Ensemble.
Proxy Object Mode
Proxy Object Mode provides an easy way for Ensemble 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 Ensemble.
Proxy Object Mode Architecture
The external Java object is represented within Ensemble by a “wrapper” or “proxy” class. The proxy object appears and behaves just like any other Ensemble object, but it has the capability to issue method calls out to a Java virtual machine (JVM), either locally or remotely over a TCP/IP connection. Any method call on the proxy object triggers the appropriate class method inside the JVM.
You can use the Java Gateway to create proxy Caché classes for custom Java components. However, the most powerful feature of the Java Gateway is that it easily creates proxy mappings to entire Java interface specifications, such as the Java Database Connection (JDBC), Java Message Service (JMS), Enterprise Java Beans (EJB), Java Connector Architecture (JCA), etc. Ensemble can use this mapping to work with any implementation that is compliant with one of these specifications.
In general, the best approach to using the Java Gateway 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 Ensemble 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 Ensemble and the Java Gateway at runtime while using Proxy Object Mode.
The Java Gateway server runs in the JVM. Ensemble 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 Ensemble 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 Ensemble 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 Ensemble 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 Ensemble proxy method initiates the following sequence of events:
All Ensemble proxy parameters are marshaled onto the wire. This is a very simple process in the vast majority of cases — parameters are simply written into the output TCP/IP buffer.
A message is sent over the TCP/IP connection to the Java Gateway worker thread. The message consists of the method name, marshaled parameters and, in some instances, other minor load.
The Java Gateway worker thread consumes the message, unmarshals 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 marshaled onto the wire and sent back to the Ensemble side over the same TCP/IP channel.
The Ensemble proxy consumes the response; any return values are unmarshaled 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.intersys.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 Ensemble, 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 Caché, 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 Ensemble as this newly added component is not designed to be reentrant.
For a simple implementation using GSON please see Stateless Service Mode Example.