JBoss.org Community Documentation
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.