2. RMI over HTTP

Offering services over HTTP is the most common solution employed today. The following sections explain how to prepare and deploy a Java Object as a service over HTTP with SwitchRMI.

Preparing Your Class

Your class does not have to be a subclass of any SwitchRMI class, it does not have to implement a "remote" interface. There is no code generation processing step involoved in preparing your class. It must, however, declare an interface with the methods available for remote access and live within the restrictions documented below for the supported protocols.

  1. Develop a Java Interface for the methods containing the services you wish to offer.

    Be aware of the following restrictions on method arguments and return types:

    1. To use the "raw" RMI protocol, all method arguments and return types must implement java.io.Serializable .. This of course includes any objects referenced directly, or indirectly by the objects in the argument list or return object.

    2. The XMLRPC protocol as currently implemented supports only primitive arguments of type, int, double and the wrapper classes Integer and Double. String and java.util.Date arguments are supported as are arguments of type java.util.List (mapped to ) and java.util.Map (mapped to ).

      The same restrictions apply to the return type.

    Some of these restrictions may be relaxed as SwitchRMI matures

  2. Implement a class which conforms to the interface.
  3. Make the interface available for client applications.

    The interface declaration will be required to construct the remote proxy to your object

Writing the Deployment Descriptor

The SwitchRMI web application requires a deployment description for each object to be published. The descriptor gives:

  • The object name, which must be unique
  • The Java type of the class to be used to provide the services.
  • A list of Java interfaces containing the methods accessible to remote clients.
  • A scope declaration indicating the "lifecycle" of the object providing the services.

    The scope can have one of three values:

    1. application - All clients access a single instance of the object.

    2. session - Each client accesses it's own copy of the object for the duration of a session.

    3. request - A new instance is created for each method invocation.

    .
  • A list of the RMI protocols by which the object's methods can be called.

The deployment descriptor is placed into an XML formatted file, containing all of the information required by the SwitchRMI servlet. The full file format will be documented at a later date, however, the following example shows an excerpt of the test-suite file with the deployment descriptor for the XMLRPC validation object:

			
			<object name="echo" scope="session"">;
				<java class="com.mjh.switchrmi.transport.test.IEchoImpl" />
				<interface class="com.mjh.switchrmi.transport.test.IEcho" />;
				<description>
					The echo object is included to allow testing of the SwitchRMI installation.
				</description>
			</object>
			
			

The format is simple to follow.

Configuring the RMI Servlet in your Web Application

Your object's deployment descriptor must be pasted into a definition:

			
			<?xml version="1.0"?>
			<switchrmi>
				<service>
					<!--
						Your deployment descriptors go here.
					-->;
				<service>
			<switchrmi>
			
			

The full format of this file will be documented at a later date.

In the web.xml file pass the URL of the configuration file to the servlet as an .The following example is taken from the web application built to run the JUnit test suites for SwitchRMI;

			
			<servlet>
				<servlet-name>rmi</servlet-name>
					<servlet-class>com.mjh.switchrmi.transport.http.HttpRmiServlet</servlet-class>
	
					<init-param>
						<param-name>switchrmi.configuration</param-name>
						<param-value>http://localhost:8080/test/jndi/TestSuiteConfiguration.xml</param-value>
					</init-param>
			</servlet>
			
			

Once you have deployed the object and started your web application you should be able to browse it with the HTML interfac with the URL: http://hostname:port/rmi/index.html . Of course if you have deployed the SwitchRMI servlet with a different path prefix than /rmi you will have to use the appropriate URL. This will give you an HTML listing of objects hosted by the servlet. you can then click through for more detail on each object.

Invoking a Remote Method

In order to invoke a remote method from a client application you must have access to the class files for one, or more, of the interfaces with with the object is deployed in the RMI Servlet. You also need to know the URL of the deployed object.

The URL format is straightforward, URLs are valid HTTP UIRLs in all respects. The distinguishing factor is the last element in the path part of the URL. This last element consists of a "filename" part, which is the published name of the object as declared in the configuration file, and a "file-suffix" part which is the name of the RMI protocol to be used to encode and decode the remote method invocation request and response.

For example in the JUnit test suite which comes with the full SwitchRMI distribution you will see the URL's:

  • http://localhost:8080/rmi/echo.raw
  • http://localhost:8080/rmi/echo.xmlrpc

Both URLs refer to the same published object, "echo", but the first suffix, "raw" declares to the client-side API that the raw, serializable RMI protocol will be used and the second that the XMLRPC protocol will be used.

The same published object in the same servlet instance can be accessed by different clients using different protocols.

SwitchRMI uses a dynamic proxy interface to remote services. The client API is simple, obtain a RMIClient for the underlying transport to be used (HTTP, SMTP, etc.) and then use the client to connect to the remote object via a proxy:

			
			import com.mjh.switchrmi.*;
				
				private RmiClient rmi;
				private IEcho     proxy;
					
				try {
					rmi = new RmiClient();
						proxy = rmi.connect("http://localhost:8080/rmi/echo.xmlrpc", IEcho.class);
				}
				catch (Exception ex) {
				}

			
			

Once you have successfully obtained a proxy to the remote object you can then invoke the methods from the requested interface on the proxy:

			
				try {
					String string = "this is a string";
					String echoed = proxy.echo(string);
					System.out.println("echoed.equals(string) = " + echoed.equals(string));
				}
				catch (Exception ex) {
				}

			
			

Since this is a remote method invocation you should always wrap method calls to the proxy in a try/catch block in case any network problem breaks the RMI call.