Focusing on open APIs for enterprise applications

Open Web Magazine

Subscribe to Open Web Magazine: eMailAlertsEmail Alerts newslettersWeekly Newsletters
Get Open Web Magazine: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

Open Web Authors: Jnan Dash, Jayaram Krishnaswamy, Bob Gourley, Kevin Benedict, Pat Romanski

Related Topics: Apache Web Server Journal, XML Magazine, Java Developer Magazine, Open Web Magazine

Apache Web Server: Article

Combining RMI with SOAP

Combining RMI with SOAP

At the end of last year, I was given a rather unpleasant assignment. This company had several Java Remote Method Invocations (RMI) services that were interacting with the legacies of the organization and I needed to open up an XML interface for them.

My first idea was to use the Simple Object Access Protocol (SOAP). But the current W3C specification and implementation of the SOAP API from Apache presented only the HTTP binding for SOAP. Because of this, the SOAP services had to be deployed in a Web server container. The possibility of opening up a SOAP-based interface to the existing RMI services was limited by the following factors:

  • If we convert the existing RMI services as SOAP-based and deploy them in a Web server container, the existing clients to those services have to be rewritten or reconfigured in order to be able to talk to the SOAP server in a SOAP-recommended way. In the worst-case scenario, we can maintain two interfaces (RMI and SOAP) for the same set of services, which is not desirable.
  • The services were interacting with many legacies and in turn with the native programs, which could not be accessed from the Web server system for various security reasons.

    We could have implemented a proprietary XML-based solution to overcome the problem. I chose to use SOAP because it's slowly emerging as the new standard for XML-based distributed computing. Moreover, by following a standard, it's easier for other applications to use the services without any particular knowledge of their internals.

    In this article, we want to develop a framework that soap-enables the existing RMI services by keeping the interfaces intact so they can still be used as normal RMI services. In addition, the framework will demonstrate how to write a SOAP message handler that will receive a SOAP request document, parse it to invoke the requested service, and construct a SOAP response document. We'll also develop a mechanism to specify, deploy, and configure the services with the help of a deployment descriptor file. Then we'll build a client program to access these services.

    The framework will be developed by defining a very simple RMI service; we'll be using the Apache SOAP implementation (version 2.2) to build a SOAP client to use the RMI services. Note: This framework is just one approach that can be used to talk SOAP over RMI. (The source code can be downloaded from the JDJ Web site, java/sourcec.cfm.)

    Anatomy of SOAP
    SOAP provides a simple and lightweight mechanism to exchange structured information in a decentralized and distributed environment. In essence, it's a model for encoding data in a standardized XML format for use in a variety of situations, such as messaging and remote procedure calls (RPC). SOAP consists of three essential parts:

    1.   Envelope: This is the top-level XML element or the root element in an XML-encoded SOAP message. The Envelope may contain any or all of the following information: the recipient of the message, the content of the message, and the processing instructions for the message.

    2.   Encoding rules: These specify the way the application-defined data-type instances will be exchanged.

    3.   RPC: These define a convention for representing the remote procedure calls and the responses to them.

    To understand the three parts of the SOAP message let's look at Listing 1.This listing shows a typical SOAP message in an HTTP request binding. The Envelope element is namespace qualified (SOAP-ENV) in order to separate it from any other application-specific identifier. It also contains information about namespace encoding. The immediate child element of the envelope in this example is the Body element. This element must be present in a SOAP message; it holds the information about the name of the remote procedure (GetLastTraderPrice) to be invoked and also encodes the parameters required by the remote procedure. In this particular message the remote procedure requires the name of the company (DIS) from which to retrieve the last trade price. Optionally, the Body element contains information about any error that occurred during the RPC and is encoded in a Fault element. The Fault element contains the error/status information with a SOAP message and, if present, can appear only once as a child element of the Body element.

    In complex cases, the Envelope element may contain another child element named Header. If this element is present in a SOAP Envelope, it must be the immediate child of the Envelope element. The Header element can typically hold information regarding authentication, transaction management, and more. In our particular example, we would not be using this header information.

    A SOAP response document contains a similar structure (see Listing 2). The Envelope element contains the Body element, which in turn contains the requested information, or a fault string, should there be any fault generated during the service call.

    For the purpose of this article we'll develop a remote procedure call framework to invoke RMI services, and we'll be using and dissecting the three parts of the SOAP specification.

    Conceptual Framework for Sending SOAP Messages over RMI
    The basic idea of how to achieve SOAP over RMI relies on the fact that if we can send and receive SOAP request and SOAP response documents over the wire using RMI protocol, we'll be able to achieve our goal. In the process, we'll create a SOAP Envelope document, serialize it, and send it to an RMI service that will decode the SOAP Envelope message, invoke the specified method on the specified Remote object, construct a Response object containing the return value or a fault string in case there's a problem, and again serialize it back to the caller (see Figure 1). The caller then parses the received SOAP response document and processes the result or the fault string accordingly. As the Apache SOAP implementation defines and implements the SOAP-HTTP binding, the objects provided in the API are not serializable in the context of Java RMI, and there lies the challenge - to overcome the present limitation until a more standard implementation of SOAP-RMI comes up.

    The Components
    Since the requirement is to continue using RMI services and to add a SOAP interface around them, we need to build a SOAP wrapper around the existing RMI services. Also, we need to build a SOAP client following the Apache SOAP implementation. But at the moment the Apache SOAP implementation handles HTTP binding only, so we need to extend it so it can call RMI services. Also, on the RMI server side, we need some mechanism to configure, deploy, and load these SOAP-aware services. Remember, not all the RMI services may need a SOAP interface, so you should be able to specify and configure the services that are required to be SOAP-enabled. Thus, the following components need to be developed:

    • SOAP wrapper
    • SOAP service manager
    • Configuration file - the deployment descriptor
    • Apache SOAP extension (this will be a custom Call object, as we will see)
    • SOAP client
    The SOAP Client
    It's unusual to start with the last component specified in the list, but it helps me explain the flow better. As mentioned earlier, we'll be using the Apache SOAP API version 2.2 to write a SOAP client. It's beyond the scope of this article to provide a complete introduction and tutorial of the API, but I'll scheme through the necessary sections as and when required.

    First, it's important to understand that to invoke a remote service deployed as a Web service over HTTP or to invoke a remote service over RMI protocol, as we'll be doing, we're essentially making a remote procedure call (RPC). In an RPC, we make a call to the remote procedure and receive a response back. The API provides us with a call and a response object. Also, we often need to pass a few parameters to invoke the remote procedure, and these parameters can be encapsulated in the Parameter object.

    The main task is to provide the Call object with the Universal Resource Locator or the URI of the remote service, the name of the method to be invoked as a part of the remote call, and the parameters required by the remote method. The parameters may frequently be complex user-defined data types and objects such as a Person or an Address object. It's also required to define a serialization and deserialization mechanism for these complex objects. By default, the API provides default serializers and deserializers for data types such as Boolean, Double, Float, and Vector. If the data type is complex and user-defined, as an implementer of the SOAP client we have to define our own serializer and deserializer and register it with SOAP by setting a SOAPMappingRegistry for the particular data type.

    The term serialization/deserialization as used in the SOAP context is different from the serialization notion of Java RMI. In the SOAP context, serialization in a broader term means the XML encoding and decoding of the data types. Again, our example focuses on how to implement these remote procedure calls over RMI and use simple data types to avoid extra work in defining serializers and deserializers for complex data types.

    The Call object implemented in the API is tailored to the HTTP binding of SOAP. However, as explained earlier, we want to perform the RPC over RMI. Thus it's required to customize the Call object and extend it as RMICallObject and build the mechanism to achieve the RPC over RMI.

    The Envelope object in the API is not serializable to perform an RMI operation. Hence the first step in our framework will be to reproduce a SOAP Envelope element in the form of an XML Document object, which is serializable in the RMI context.

    public class RMICallObject extends Call
    public Response invoke(URL url, String s) throws SOAPException
    private Document buildDocument()throws IllegalAddException
    private Response buildResponse
    (Document doc) throws Exception

    This class structure represents the RMICallObject class that's designed to handle the RMI call. The class overrides the invoke() method from the Call class and defines two private helper methods to construct the Document object, which will be serialized over the RMI call, and another method to construct a Response object out of the returned Document object from the RMI call. For ease of use, I've used the JDOM API from Apache for XML data handling.

    The invoke() method takes the URL of the configuration file where the location and name of the RMI server is specified and looks up and obtains a remote reference of the same. As we'll see later, this RMI service will act as an entry point to all other RMI services we want to access (see Listing 3).

    SOAPRMIInterface is the remote interface that the RMI service implements in order to parse the Document object that's passed as a result of the SOAP call. The implementation of the SOAPRMIInterface is given a binding in the RMI registry under the name assigned through the variable server-Name.

    A Document object is constructed out of the generated Call object, which represents the SOAP Envelope.

    //construct a Document object from the Call object entries
    doc = buildDocument();

    After obtaining a remote reference of the RMI service, execute the remote method named "invokeMethod()" on this reference by passing the Document object to it. This method is responsible for parsing the Document object and acts as the gateway to all the SOAP RMI services.

    //calling the invoke method
    responseDoc = obj.invokeMethod(doc);

    Once the Document object is handed over to the remote service, the client-side process waits for a return Document object from the RMI server. The remote server object processes the passed Document object.

    Once we've extended the Call object to the RMICallObject and incorporated the functionality to perform an RMI call, the rest of the client programming follows what we do for a normal SOAP client ( (see Listing 4).

    This listing is an example of the SOAP client. First, we obtain the reference to an RMICallObject, then pass the target remote service name as it's bound to the RMI registry, pass the name of the remote method to be invoked, create the Parameter object to pass the required parameters to the remote method, and, finally, invoke the remote method by calling the invoke() method on the RMICallObject. It's important to note that we pass the URL as the address of the configuration file (conf.txt) that holds the name and location of the SOAP server manager. As shown in Listing 4, the conf.txt file should be placed under the current working directory.

    Once this URL is passed to the invoke() method of the RMICallObject class, it constructs a Properties file out of the given configuration file conf.txt and an RMI lookup URL with the server name and the location.

    Once the returned XML Document object is obtained from the RPC, we can analyze the entries of the Document to obtain the returned result of the method call or the fault string associated with this method call, and construct the Response object out of that to return it to the Caller RMI client.

    SOAP Wrapper
    A major part of building this framework is to develop a SOAP wrapper around RMI services, which can parse and handle incoming SOAP requests. So, the basic idea of this framework is to serialize the SOAP request over RMI in the form of an XML Document object, and the SOAP wrapper is required to be an RMI service that can accept the serialized Document object. As a matter of fact, this is an RMI service acting as an entry point to all other RMI services deployed as SOAP-enabled, so it's vital to ensure that this service is up and running so other services can be accessed and used.

    First, declare a Remote interface for this RMI service.

    public interface SoapRMIInterface extends Remote
    public Document
    invokeMethod(Document doc) throws RemoteException,

    Our SOAP wrapper RMI service will implement this interface, and, as a result, define the invokeMethod() method. As we can see, apart from throwing the usual RemoteException, this service also throws a customized RMISoapException to differentiate between normal RMI failures and any SOAP-related ones. This design is guided by the fact that to build a Response object, we need to pass the proper fault string information back to the caller object.

    The implementation of the invokeMethod() method must perform the following tasks:

  • Parse the received document and retrieve the Body element of the SOAP request.
  • Identify the name of the remote service, the name of the remote method, and the parameters passed to it.
  • Locate the remote service from the registry by analyzing the deployment descriptor (to be discussed in the following section).
  • Check whether the method specified is exposed as a part of the given service and if the service is defined in the deployment descriptor. If it can't locate the specified service, it throws an exception and eventually propagates it as a SOAP fault string back to the caller.
  • Create a new instance of the specified service implementation class and invoke the specified method by passing the parameters obtained as a part of the SOAP request, if the method specified is a part of the deployed service. If the method name could not be located, it throws an exception and propagates it back to the caller as a SOAP fault string.
  • Create and return a response XML document to the caller as an RPC response once the service is successfully invoked. After receiving this XML document, the RMICallObject then constructs the Response object out of it and passes it to the SOAP client object.

    This process is large in scope; the source code for SoapRMIServer is available on To check if the method exists for a given service, the service uses the Java reflection mechanism. It also uses this mechanism when it constructs a Response XML Document object out of the returned value of the service, in case the returned value is an object. While creating a response XML document to maintain the SOAP response specification, it uses the received SOAP request document to maintain the integrity of the namespace and encoding style used.

    The Deployment Descriptor
    SOAP utilizes an XML file called deployment descriptor to supply information to the SOAP runtime environment. The deployment descriptor contains the Universal Resource Name (URN) for the service, the name of the method, the Java implementation class if the SOAP service is deployed as a Java class, and more regarding serialization and deserialization (in a SOAP context and not in an RMI context). The amount of information that can and should be supplied depends on the SOAP runtime requirements. In the example we're following, which is a simplistic model, we need information regarding the RMI services that are deployed as SOAP-enabled services.

    Typically, our deployment descriptor(s) will contain the following information:

    • The URN of the service as the name that binds it to the RMI registry
    • The name of the Java class deployed as the specified service
    • The method that's exposed as the interface to the service
    • Whether or not the method is implemented as static
    The other bits of information that normally become a part of the SOAP service, such as the scope of the service (application/session, etc.), are not relevant to the framework we're developing, because in this particular framework I've tried to avoid the complications of session management.

    The deployment descriptor is typically encoded within a top-level element <isd:service>, which is namespace-qualified to avoid conflict with any other user-defined entity. An example of a deployment descriptor is as follows:

    <isd:service xmlns:isd=
    "" id="urn:greetingserver">
    <isd:provider type="java" scope="Application" methods="sayHello">
    <isd:java class="Greeting" static="false"/>

    This descriptor particularly defines a service named "greetingserver" with an exposed method "sayHello", and the implementation Java class of the service is "Greeting" and the method is nonstatic.

    The basic idea is to provide an XML file in which we can describe the deployed services. To deploy all the services in a single file, I've put the individual descriptors under a root element called "<soapservices>" (soap.xml).

    The Apache SOAP implementation provides a utility class called DeploymentDescriptor to load and parse the deployment descriptor files. I've used the same to load and access my consolidated deployment descriptor file, along with a ConfigDescriptor class designed to parse the file and retrieve everything or a descriptor for a particular service against its service ID.

    The Service Manager
    So far on the server side we've created the SOAP wrapper RMI service, which is the gateway to all other SOAP-enabled RMI services, and have also devised a deployment descriptor to specify and describe all the services that are to be deployed and loaded as SOAP-enabled. As a precondition to these specific services working, we need to load all the services specified in the deployment descriptor file along with the wrapper RMI service and bind them to the RMI registry. Binding is straightforward. The only difficulty I faced was in using the DeploymentDescriptor class of the Apache SOAP API, as it doesn't accept the fact that more than one service can be specified within the same descriptor file.

    I designed a ConfigDescriptor class ( that parses the deployment descriptor XML file and creates an individual DeploymentDescriptor object by taking each child node of the <soapservices> root element. I added a few convenient methods to retrieve all or one particular DeploymentDescriptor object given the service ID (the URN) of the service. The SoapServerManager class uses the ConfigDescriptor object and retrieves all the DeploymentDescriptor objects specified in the descriptor file. It then finds all the Java classes specified as the service implementation and binds them to the RMI registry with the names specified in the ID attribute of the <isd:service> element.

    This brings all the specified RMI services up and running, with all the methods specified in the deployment descriptor file exposed as SOAP-accessible remote service methods. Once this is done, the last job of the SoapServerManager class is to load the SOAP wrapper RMI service. The additional functionality of starting up an individual service or taking down one or all of the services can be provided through the SoapServerManager class.

    A Simple RMI Service
    Consider a simple RMI service. This service is named "addressserver" and the remote service method is "getAddress", which takes two parameters - the name and surname of a person. Given the name and surname, the service returns the person's address. To make it a very small example service, I've hard-coded the address inside the code, although in real life this service might interact with a database and fetch the address. I've created an Address object that holds the name, city, and zip code. The service returns the Address object in response to a SOAP call ( (see Listing 5).

    This listing explains the structure of the addressserver service, which is also designed as an RMI service.

    Running the Server
    To run the server, we need to ensure the following:

  • Place all the .jar files (mail.jar, xerces.jar, activation.jar, soap.jar, and jdom.jar) under the lib directory of your install directory.
  • Set the CLASSPATH to include the current working directory and the lib directory under it.
  • Generate the stubs and skeletons of all the RMI services to be deployed (included in the source code). For the SoapRMIServer, it's important to provide all the .jar files in the rmic -classpath option.

    rmic -classpath .;

  • Run the Service Manager (SoapServerManager). This will read the deployment descriptor file, load all the specified RMI services there, and bind them to the RMI registry under the name specified as the service ID.
  • Provide the deployment descriptor in the CLASSPATH.
  • Check your security policy for problems starting up or accessing the RMI services. For this example, I created and supplied a policy file (myPolicy.txt) that grants all permissions. If you create/use this policy file, pass it to the runtime with the following command:

    java -

    Running the Client
    The client program, as explained, is ready to call the deployed addressservice. We can run the client program using the following command from a DOS prompt - java rmi.client.RMIClient.

    The address of the rmi server: rmi://localhost:1099/soapserver
    Target obj: urn:addressserver
    The return value:
    person...Samudra Gupta
    post...SS1 2RQ

    This shows the result of the client call and we receive the address of the specified person.

    To find out how the framework behaves in case of erroneous inputs, I changed the method name to "getLocation" instead of the correct exposed method "getAddress, and received the following error message:

    The address of the rmi server: rmi://localhost:1099/soapserver
    Target obj: urn:addressserver
    The fault code: SOAP-ENV:Server.BadTargetObjectURI
    The return value:
    faultstring...Could not invoke the specified method

    It's important to note that the client will also need all the .jar files to be set in the CLASSPATH as they're used by the Apache SOAP implementation as well as our own extended RMICallObject class.

    This framework served my purpose very well, and I could use the existing RMI services both as normal RMI as well as SOAP deployed over RMI. This framework is tailored to meet my requirements, so it may not meet yours. The ability to handle a user-defined data type as a parameter to the remote services is surely one of the main areas to be incorporated; although it's used in the real project, I didn't explain it here due to space constraints. I strongly believe that more experimentation with SOAP will eventually help it become a mature and robust technology.


  • Apache SOAP API for an API download, mailing list, and FAQ:
  • An introduction to RMI:
  • More Stories By Samudra Gupta

    Samuda has five years of experience in Java and web technology related fields. He is presently working as an independent Java Consultant in the United Kingdom, providing solutions for different e-commerce projects.

    Comments (1)

    Share your thoughts on this story.

    Add your comment
    You must be signed in to add a comment. Sign-in | Register

    In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.