JBoss.org Community Documentation

3.6.2.9. Steps to Expose Any RMI Interface via HTTP

Using the HttpProxyFactory MBean and JMX, you can expose any interface for access using HTTP as the transport. The interface to expose does not have to be an RMI interface, but it does have to be compatible with RMI in that all method parameters and return values are serializable. There is also no support for converting RMI interfaces used as method parameters or return values into their stubs.

The three steps to making your object invocable via HTTP are:

  • Create a mapping of longs to the RMI interface methods using the MarshalledInvocation.calculateHash method. Here for example, is the procedure for an RMI SRPRemoteServerInterface interface:

    import java.lang.reflect.Method;
    import java.util.HashMap;
    import org.jboss.invocation.MarshalledInvocation;
    
    HashMap marshalledInvocationMapping = new HashMap();
    
    // Build the Naming interface method map
    Method[] methods = SRPRemoteServerInterface.class.getMethods();
    for(int m = 0; m < methods.length; m ++) {
        Method method = methods[m];
        Long hash = new Long(MarshalledInvocation.calculateHash(method));
        marshalledInvocationMapping.put(hash, method);
    }
    
  • Either create or extend an existing MBean to support an invoke operation. Its signature is Object invoke(Invocation invocation) throws Exception, and the steps it performs are as shown here for the SRPRemoteServerInterface interface. Note that this uses the marshalledInvocationMapping from step 1 to map from the Long method hashes in the MarshalledInvocation to the Method for the interface.

    import org.jboss.invocation.Invocation;
    import org.jboss.invocation.MarshalledInvocation;
    
    public Object invoke(Invocation invocation)
        throws Exception
    {
        SRPRemoteServerInterface theServer = <the_actual_rmi_server_object>;
        // Set the method hash to Method mapping
        if (invocation instanceof MarshalledInvocation) {
            MarshalledInvocation mi = (MarshalledInvocation) invocation;
            mi.setMethodMap(marshalledInvocationMapping);
        }
    
        // Invoke the Naming method via reflection
        Method method = invocation.getMethod();
        Object[] args = invocation.getArguments();
        Object value = null;
        try {
            value = method.invoke(theServer, args);
        } catch(InvocationTargetException e) {
            Throwable t = e.getTargetException();    
            if (t instanceof Exception) {
                throw (Exception) e;
            } else {
                throw new UndeclaredThrowableException(t, method.toString());
            }
        }
    
        return value;
    }
    

  • Create a configuration of the HttpProxyFactory MBean to make the RMI/HTTP proxy available through JNDI. For example:

    <!-- Expose the SRP service interface via HTTP -->
    <mbean code="org.jboss.invocation.http.server.HttpProxyFactory"
           name="jboss.security.tests:service=SRP/HTTP">
        <attribute name="InvokerURL">http://localhost:8080/invoker/JMXInvokerServlet</attribute>
        <attribute name="InvokerName">jboss.security.tests:service=SRPService</attribute>
        <attribute name="ExportedInterface">
            org.jboss.security.srp.SRPRemoteServerInterface
        </attribute>
        <attribute name="JndiName">srp-test-http/SRPServerInterface</attribute>
    </mbean>
    

Any client may now lookup the RMI interface from JNDI using the name specified in the HttpProxyFactory (e.g., srp-test-http/SRPServerInterface) and use the obtain proxy in exactly the same manner as the RMI/JRMP version.