Tuesday, February 28, 2012

RPC Practice: Practice of Redstone RPC Server and RPC Client

XML-RPC is a remote procedure call (RPC) protocol which
uses XML to encode its calls and HTTP as a transport mechanism.

Redstone XML-RPC Library is a implementation of the XML-RPC specification.

This post practice create the RPC server and
call service by RPC client with Redstone XML-RPC Library.

1. The RPC Server
1.1 The XmlRpcServlet and related classes

TestService.java

package test;

import javax.servlet.*;

import redstone.xmlrpc.XmlRpcServlet;

/**
 * The servlet that extends redstone.xmlrpc.XmlRpcServlet
 */
public class TestService extends XmlRpcServlet {
    /**
     * auto-generated serial version UID
     */
    private static final long serialVersionUID = 7764199825847356985L;

    public void init( ServletConfig servletConfig )
        throws ServletException {
        // init
        super.init( servletConfig );
        // regist the Service
        // HelloClockService is the service name for client to invoke
        // new HelloClock() is the instance that provide this service
        getXmlRpcServer().addInvocationHandler( "HelloClockService", new HelloClock());
    }
}

only one handler in this servlet named "HelloClockService" handled by
an instance of HelloClock

HelloClock.java

package test;

/** this class provide the HelloClockService,
  * only one service 'sayHello'
  */
public class HelloClock {
    /**
     * sayHello service of HelloClockService
     * @param name the name to say hello
     * @return HelloClockMessage contains hello message and current time
     */
    public HelloClockMessage sayHello (String name) {
        return new HelloClockMessage(name);
    }
}

HelloClock provide one service, sayHello, with one String parameter.
It will return an instance of HelloClockMessage

HelloClockMessage.java


package test;

import java.util.*;

/**
 * The message that will reply to client by
 * HelloClockService.sayHello
 */
public class HelloClockMessage {
    private String _msg;
    private Date _date;
    public HelloClockMessage () {
        
    }
    public HelloClockMessage (String name) {
        _msg = "Hello " + name;
        _date = new Date();
    }
    public HelloClockMessage (String msg, Date date) {
        _msg = msg;
        _date = date;
    }
    public String getMsg () {
        return _msg;
    }
    public Date getDate () {
        return _date;
    }
}

HelloClockMessage create the msg by the input name,
and create a Date object

The return message of HelloClockService will contains two parameter,
msg and date, with respect to the getter getMsg () and getDate () in HelloClockMessage

1.2 The servlet config (in web.xml)

config for xml-rpc

<servlet>
        <servlet-name>xml-rpc</servlet-name>
        <servlet-class>test.TestService</servlet-class>
        <init-param>
            <param-name>streamMessages</param-name>
            <param-value>1</param-value>
        </init-param>
        <init-param> <!-- Optional! Defaults to text/xml and ISO-8859-1 -->
            <param-name>contentType</param-name>
            <param-value>text/xml; charset=UTF-8</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>xml-rpc</servlet-name>
        <url-pattern>/xml-rpc/*</url-pattern>
    </servlet-mapping>

2. The RPC Client

TestRPCClient.java

package test;

import java.util.*;

import redstone.xmlrpc.XmlRpcCallback;
import redstone.xmlrpc.XmlRpcClient;
import redstone.xmlrpc.XmlRpcException;
import redstone.xmlrpc.XmlRpcStruct;
/**
 * test RPC call
 */
public class TestRPCClient {
    // the callback for async RPC
    private static XmlRpcCallback xrc = new XmlRpcCallback() {
        public void onException(XmlRpcException exception) {
            exception.printStackTrace();
        }
        public void onFault(int faultCode, java.lang.String faultMessage) {}
        public void onResult(java.lang.Object result) {
            System.out.println("########## Async RPC Callback ##########");
            // get the HelloClockMessage object by the response
            HelloClockMessage hcm = XmlToHelloClockMessage((XmlRpcStruct)result);

            // Show the value of created HelloClockMessage
            System.out.println(hcm.getMsg());
            System.out.println(hcm.getDate().getHours() + ":" + hcm.getDate().getMinutes());
        }
    };
    /**
     * convert XmlRpcStruct to HelloClockMessage
     * @param resp the XmlRpcStruct response
     * @return HelloClockMessage object
     */
    public static HelloClockMessage XmlToHelloClockMessage (XmlRpcStruct resp) {
        HelloClockMessage hcm =
            new HelloClockMessage((String)resp.get("msg"), (Date)resp.get("date"));
        return hcm;
    }
    public static void main( String[] args ) throws Exception {
        // create client
        XmlRpcClient client =
            new XmlRpcClient( "http://localhost:8080/RPCServer/xml-rpc", true);
        // invoke RPC method with param "Ben"
        // get the response
        XmlRpcStruct resp =
            (XmlRpcStruct)client
                .invoke( "HelloClockService.sayHello", new Object[] {"Ben"});
        // get the HelloClockMessage object by the response
        HelloClockMessage hcm = XmlToHelloClockMessage(resp);

        // show the Class of response parameter
        System.out.println(resp.get("date").getClass());
        System.out.println(resp.get("msg").getClass());

        // Show the value of created HelloClockMessage
        System.out.println(hcm.getMsg());
        System.out.println(hcm.getDate().getHours() + ":" + hcm.getDate().getMinutes());

        System.out.println();

        // invoke RPC Asynchronously
        client.invokeAsynchronously("HelloClockService.sayHello",
                new Object[] {"Benbai"}, xrc);
    }
}

This client call RPC twice,
one sync call, one async call with a callback object.

The HelloClockMessage is the same with server's one.

3. Test result

Run TestRPCClient as Java Program:


Download:

The full project is at github
RPCClient:
https://github.com/benbai123/JSP_Servlet_Practice/tree/master/Practice/WebServicePractice/RPC/RPCClient
RPCServer:
https://github.com/benbai123/JSP_Servlet_Practice/tree/master/Practice/WebServicePractice/RPC/RPCServer

References:

Redstone:
http://xmlrpc.sourceforge.net/

wiki:
http://en.wikipedia.org/wiki/XML-RPC

No comments:

Post a Comment