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
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.
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 can start the Java Gateway server in one of the following ways:
, by adding a Java Gateway business service to the production. The Java Gateway server starts when the production starts.
, by entering a command at the Terminal command prompt.
If you are using JMS on the Java side, you must start the Java Gateway server in JMS mode (the command is slightly different).
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:
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 to the production.
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.
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()
Connecting to a Java Gateway Worker Thread
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()
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 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.
The external Java object is represented within Ensemble by a wrapper
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.
Java Gateway Operational Model
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
The Java Gateway API %Import()
method sets off the chain of sequential events (1), (2), and (3) shown in the following diagram:
Importing Java Classes
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
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.
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 %ServiceRequest(serviceName As %String, arguments As %String, ByRef response As %String) As %Status
is the name of the implementing Java service class, arguments
corresponds to the Java service args
corresponds to the Java service 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.