Revision History | |
---|---|
Revision $Revision: 1.1 $ | $Date: 2002/02/12 10:57:35 $ |
RMI adaptors allow clients to connect to a JMX Agent from a remote JVM using RMI.
OpenJMX's features two RMI adaptors:
The JRMP Adaptor supports also SSL for secure connections, and both the adaptors support remote notification listeners and filters.
Note that RMI is not a protocol, and here must be intended as "Remote Method Invocation using Java". The underlying protocol can be anyone, and in fact two protocols are supported by the OpenJMX's RMI adaptors: JRMP and IIOP.
JRMP is the Java Remote Method Protocol, and it's the RMI default protocol.
IIOP is the Internet Inter ORB Protocol, and it's the CORBA default protocol.
Remote Method Invocation in Java can have JRMP or IIOP as underlying protocols, and the remote
invocation process is usually referred to, respectively, as "RMI" and "RMI over IIOP".
"RMI" is a short for "RMI over JRMP".
The JRMP adaptor exposes the JMX Agent to RMI over JRMP calls from remote JVMs.
It needs a naming service such as the rmiregistry or the NamingService MBean (see OpenJMX documentation)
to be active before being started, and proper directives to find the naming service (such as a jndi.properties file
in the classpath).
Below you can see the snippet of the code needed in the server
to create, register and start the JRMP adaptor.
Example 3.3. Deploying the JRMP adaptor
public class Server { public static void main(String[] args) throws Exception { // Create a MBeanServer MBeanServer server = MBeanServerFactory.createMBeanServer(); // Create and start the naming service ObjectName naming = new ObjectName("Naming:type=rmiregistry"); server.createMBean("openjmx.tools.naming.NamingService", naming, null); server.invoke(naming, "start", null, null); // Create the JRMP adaptor ObjectName adaptor = new ObjectName("Adaptor:protocol=JRMP"); m_server.createMBean("openjmx.adaptor.rmi.jrmp.JRMPAdaptor", adaptor, null); JRMPAdaptorMBean mbean = (JRMPAdaptorMBean)StandardMBeanProxy.create(JRMPAdaptorMBean.class, server, adaptor); // Set the JNDI name with which will be registered String jndiName = "jrmp"; mbean.setJNDIName(jndiName); // Register the JRMP adaptor in JNDI and start it mbean.start(); } }
Let's look now at the client, and how it can interact with the JRMP Adaptor.
All you need is an RMIConnector (class openjmx.connector.rmi.RMIConnector),
and proper directives to find the naming service. To find the naming service, you need a jndi.properties
file, or a Hashtable with the suitable naming properties to be passed to the RMIConnector.
Below you can see the code snippet necessary to connect to the adaptor.
Example 3.4. Deploying the JRMP adaptor
public class Client { public static void main(String[] args) throws Exception { // Create an RMIConnector, passing it the JNDI name of the JRMP Adaptor String jndiName = "jrmp"; RMIConnector connector = new RMIConnector(jndiName); // Use the connector as it is an MBeanServer String remoteHostName = connector.getRemoteHostName(); ObjectName objName = new ObjectName("examples:mbean=MyService"); ObjectInstance instance = connector.createMBean("examples.mbeans.rmi.MyRemoteServiceObject", objName, null); NotificationListener listener = new NotificationListener() { public void handleNotification(Notification n, Object handback) { // Do something } }; connector.addNotificationListener(objName, listener, null, null); // and so on } }
It is VERY important to use the RMIConnector class in the client, and not to try to lookup directly the
adaptor in JNDI.
This because the RMIConnector does some trick to understand which is the underlying
transport protocol (JRMP or IIOP), and handles the listeners to be invoked remotely by the server.
It is definitely simpler to use the RMIConnector class.
The JRMP adaptor can be setup to use SSL to allow secure RMI connections.
Using SSL with RMI over JRMP requires the use of custom RMI socket factories, and requires the server to
setup a keystore where a private key and the corresponding public key wrapped in a X509 self-signed
certificate are stored.
The certificate is then sent to the client when the connection is established, and the client must trust
the server's certificate by looking it up in a truststore (in the client JVM). If the certificate found
in the truststore matches the one sent by the server, the SSL connection is complete and data exchange may
begin.
The operations needed to setup the JRMP adaptor over SSL are the following:
The operations needed to setup the client are the following:
Below you can find the code snippets for the server; the client is exactly equal as before.
Example 3.5. Deploying the JRMP adaptor over SSL
// Generate the keystore keytool -genkey -v -keystore key.store -storepass storepwd -keypass keypwd -dname "CN=Simone Bordet, OU=Project Administrator, O=OpenJMX, L=Torino, S=TO, C=IT" -validity 365 // Export the X509 certificate keytool -export -v -storepass storepwd -keystore key.store | keytool -import -v -storepass storepwd -keystore trust.store -noprompt // Deploy the MBeans public class Server { public static void main(String[] args) throws Exception { // Create a MBeanServer MBeanServer server = MBeanServerFactory.createMBeanServer(); // Create the SSL ServerSocket factory ObjectName ssl = new ObjectName("Adaptor:service=SSLServerSocketFactory"); server.createMBean("openjmx.adaptor.ssl.SSLAdaptorServerSocketFactory", ssl, null); SSLAdaptorServerSocketFactoryMBean factory = (SSLAdaptorServerSocketFactoryMBean)StandardMBeanProxy.create(SSLAdaptorServerSocketFactoryMBean.class, server, ssl); factory.setKeyStoreName("key.store"); factory.setKeyStorePassword("storepwd"); factory.setKeyManagerPassword("keypwd"); // Create and start the naming service ObjectName naming = new ObjectName("Naming:type=rmiregistry"); server.createMBean("openjmx.tools.naming.NamingService", naming, null); server.invoke(naming, "start", null, null); // Create the JRMP adaptor ObjectName adaptor = new ObjectName("Adaptor:protocol=JRMP"); m_server.createMBean("openjmx.adaptor.rmi.jrmp.JRMPAdaptor", adaptor, null); JRMPAdaptorMBean mbean = (JRMPAdaptorMBean)StandardMBeanProxy.create(JRMPAdaptorMBean.class, server, adaptor); // Set the JNDI name with which will be registered String jndiName = "jrmp"; mbean.setJNDIName(jndiName); // Set the SSL ServerSocket Factory mbean.setSSLFactory(ssl.toString()); // Register the JRMP adaptor in JNDI and start it mbean.start(); } }
The IIOP adaptor exposes the JMX Agent to RMI over IIOP calls from remote JVMs.
It needs a naming service such as tnameserv
to be active before being started, and proper directives to find the naming service (such as a jndi.properties file
in the classpath). Below you can see the snippet of the code needed in the server
to create, register and start the IIOP adaptor.
Example 3.6. Deploying the IIOP adaptor
public class Server { public static void main(String[] args) throws Exception { // Create a MBeanServer MBeanServer server = MBeanServerFactory.createMBeanServer(); // Remember to start tnameserv ! // Create the IIOP adaptor ObjectName adaptor = new ObjectName("Adaptor:protocol=IIOP"); m_server.createMBean("openjmx.adaptor.rmi.iiop.IIOPAdaptor", adaptor, null); IIOPAdaptorMBean mbean = (IIOPAdaptorMBean)StandardMBeanProxy.create(IIOPAdaptorMBean.class, server, adaptor); // Set the JNDI name with which will be registered String jndiName = "jrmp"; mbean.setJNDIName(jndiName); // Register the IIOP adaptor in JNDI and start it mbean.start(); } }
The client is exactly equal as before, as the RMIConnector is smart enough to understand the underlying protocol and act properly.