Remote MMBase Cloud Interface


Table of Contents

1. Remote MMBase Cloud Interface
1.1. What is RMMCI?
2. RMMCI examples
2.1. Server setup
2.2. Using BeanShell
2.3. BeanShell, a more realistic example
3. RMI over HTTP
4. RMMCI implementation details
4.1. RMMCI uses the MMCI Local implementation
4.2. The current MMBase MMCI architecture
4.3. How the RMMCI code generation works
4.4. Security concerns
4.5. Integration process
5. When RMMCI/RMI doesn't work
5.1. java compatibility
5.2. Installing server side
5.3. Client side
6. Example and TODO
6.1. Example
6.2. TODO

To be able to understand RMMCI some basic knowledge about java, MMBase and the MMBase Cloud Interface is required. Lets try to do this in a few line. MMBase is a object / relation object management system. Object instances in MMBase are known as nodes. They Are much like other (java)objects they have data members and behavior. Each nodes has a type. The type or as mmbase calls it node manager defines what behavior and data members a node may have. A node manager is a combination of a java class and an xml configuration. In java term the node manager with nodes is much like a container managed entity bean (but better). A strong aspect of MMBase is the way it handle relations. The difference between a java object and an MMBase node is that the nodes are persistent. The combination of the object and node managers is called the cloud.

The MMBase cloud is an abstract definition the of world that MMBase knows. An MMBase cloud can run distributed over multiple machines.

The MMBase Cloud Interface (MMCI) is a java interface that provides access to the MMBase cloud. The interface is defined in the java package org.mmbase.bridge. There are currently 2 implementations of the MMCI. on known as the local implementation and one known as the remote implementation. The local implementation uses the mmbase core packages to implement the bridge interface. The remote implementation (what this document is about) is a wrapper around the local implementation that makes it possible to access a cloud instance from a "remote" location.

Since an MMBase cloud can run distributed over multiple machines/instances why use RMMCI? Well running multiple MMBase instances can be to much for what you want. If you just want to connect to a cloud ant change some nodes of install new node types RMMCI is what you are looking for. An other reasons for using RMMCI is that is also makes is possible to connect to multiple MMBase clouds and send data over(agents).

RMMCI stand for Remote MMBase Cloud Interface, RMMCI is a set of java files that makes it possible to connect to an MMBase cloud using the MMCI (MMBase Cloud Interface) without the need to start a own MMBase Cloud instance.

RMMCI allows scripting. get mmbase-rmmci.jar from /WEB-INF/lib . Download http://www.beanshell.org/ (in the example bsh-1.2b7.jar was downloaded) copy both files to a directory and create a files called bshdemo.bsh with the content of this listing. If now you make the program executable (chmod 755 bshdemo.bsh) and run the program you will have created and run your first RMMCI BeanShell script.

#!/bin/sh
#! The following hack allows java to reside anywhere in the PATH.
//bin/sh -c "exec java -classpath bsh-1.2b7.jar bsh.Interpreter $0 $*"; exit
addClassPath("mmbase-rmmci.jar");
import org.mmbase.bridge.*;

cloud = ContextProvider.getCloudContext("rmi://127.0.0.1:1111/remotecontext").getCloud("mmbase");
list = cloud.getNodeManager("mmservers").getList(null,null,null);
for (x =0 ; x < list.size() ; x++){
  print(list.getNode(x).getStringValue("host"));
}

If your application has to be accessed via the internet your probably need to use the HTTP protocol for communication between the client and server. While again this is not very good for performance it is possible. MMBase provides a servlet that acts a a HTTP to rmi gateway servlet org.mmbase.servlet.rmi.RMIHandlerServlet (it is a drop in replacement for the java-rmi.cgi provided with the java jdk) . make the servlet available under the /cgi-bin/java-rmi.cgi servlet mapping

<servlet>
  <servlet-name>javarmi</servlet-name>
  <description>java http rmi gateway</description>
  <servlet-class>org.mmbase.servlet.rmi.RMIHandlerServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
  <servlet-name>javarmi</servlet-name>
  <url-pattern>/cgi-bin/java-rmi.cgi</url-pattern>
</servlet-mapping> 

In your client code to force RMI over HTTP add the following lines

java.rmi.server.RMISocketFactory.setSocketFactory(new
      sun.rmi.transport.proxy.RMIHttpToCGISocketFactory());

now if you want to access the cloud from a remote location still access the cloud via a rmi url.

ContextProvider.getCloudContext("rmi://myhost:1111/remotecontet");

The MMCI interface provides access to the MMBase cloud. The MMCI interface is defined in the package org.mmbase.bridge. Examples of such definitions are the org.mmbase.bridge.Cloud and the org.mmbase.bridge.Node interface. Depending on your configuration a security model is chosen. the MMCI implementation (LocalContext) interfaces with the core MMBase classes.

        ---------------------
        |MMCI interface     |
        ---------------------
                | uses
        ---------------------
        |MMCI implementation|
        ---------------------
                | uses
        ---------------------
        |  security         |
        ---------------------
                | uses
        ---------------------
        |MMbase cloud       |
        ---------------------
                | uses
        ---------------------
        |database support   |
        ---------------------
            |          |
         database    file system
      

RMMCI adds a network layer to the MMCI by re-implementing the MMCI and using the current MMCI implementation.

RMMCI uses Remote Method Invocation(RMI). To use RMI it is required to write an interface that extends java.rmi.Remote and every method in the class should throw RemoteException. Since we have an existing interface we decided to create a new interface based on the current one but that extended the java.rmi.Remote interface and throws RemoteExceptions. We also decided to generate the new interface. The first step is to create a XML description of the current interface. this is done in a class found in org.mmbase.bridge.remote.generator.MMCI that class uses ClassToXML also found in org.mmbase.bridge.remote.generator.ClassToXML. the resulting XML file MMCI.xml look like this:

<mmci>
 <class shortname="Cloud" name="org.mmbase.bridge.Cloud" implements="">
        <method name="getName">
            <input/>
            <output>
                <sunclass name="java.lang.String"/>
            </output>
        </method>
        <method name="getDescription">
            <input/>
            <output>
                <sunclass name="java.lang.String"/>
            </output>
        </method>
        <method name="createTransaction">
            <input>
                <sunclass name="java.lang.String"/>
                <primitiveclass shortname="boolean" name="boolean" classname="java.lang.Boolean"/>
            </input>
            <output>
                <classReference name="org.mmbase.bridge.Transaction"/>
            </output>
        </method>
        ...........
    </class>
    <class shortname="CloudContext" name="org.mmbase.bridge.CloudContext" implements="">
    ..........
</mmci>
      

based on this XML file org.mmbase.bridge.remote.generator.RemoteGenerator creates the interface. for example org.mmbase.bridge.Cloud becomes org.mmbase.bridge.remote.RemoteCloud

public interface RemoteCloud extends  Remote {
   public java.lang.String getName() throws RemoteException;
   public java.lang.String getDescription() throws RemoteException;
......
      

for every MMCI interface class RemoteGenerator also create 2 more classes. One implementation of the RemoteCloud (org.mmbase.bridge.remote.rmi.RemoteCloud_Rmi

public class RemoteCloud_Rmi extends  UnicastRemoteObject implements RemoteCloud  {
  Cloud originalObject;
      public java.lang.String getName() throws RemoteException{
         return originalObject.getName();
   }
      

and

public class RemoteCloud_Impl implements Cloud  {
   //original object
   RemoteCloud originalObject;
   public java.lang.String getName() {
      try {
         return originalObject.getName();
      } catch (Exception e){throw new RuntimeException(e.getMessage());}
   }
}
      

The last class implements the original interface and uses the RemoteInterface for network traffic. The RemoteCloud_Rmi should be compiled using the java rmic

The final picture looks like this:

        org.mmbase.bridge.remote.implementation.RemoteCloud
                                |                  |
                                |                  | uses
                                |                 \ /
                                | implements       org.mmbase.bridge.remote.rmi.RemoteCloud_Stub
                                |                                 |
                                |                                 | implements
                               \ /                               \ /
                   org.mmbase.bridge.Cloud <--looks like--> org.mmbase.bridge.remote.RemoteCloud
                               / \                               / \
                                |                                 | implements
                                |                                 |
                                | implements      org.mmbase.bridge.remote.rmi.RemoteClound_Skel
                                |                 |
                                |                 | uses
                                |                \ /
        org.mmbase.bridge.implementation.BasicCloud
      

We now have 2 implementation of the MMCI org.mmbase.bridge.implementation that uses MMBase core classes and org.mmbase.bridge.remote.implementation that uses the RMI classes and the org.mmbase.bridge.implementation classes.


This is part of the MMBase documentation.

For questions and remarks about this documentation mail to: [email protected]