Applications


XML-RPC is a technology that makes it possible to invoke procedures located on another machine, possibly across the Internet. The applications for XML-RPC are the same ones that exist for regular procedure calls, with a few caveats.

You should be careful not to make your RPCs too fine grained, or your application will spend more time invoking the procedure with XML than it will spend executing the actual procedure on the remote machine. This is a recipe for bad performance. You should also try to design your application so that you minimize the number of RPC calls your application needs to make.

One of the most popular applications for XML-RPC is in the emerging field of social software. Because it’s easy to use and implement, XML-RPC is undergoing significant deployment by the creators of Weblogging software systems. XML-RPC is used to notify aggregation servers about Weblog updates. It’s also used as the basis for APIs that allow rich Weblogging client programs to update Weblogs that reside on hosted Web servers.

Simplifying XML-RPC

We’ll leave you with a program that’s not an application; but, depending on your philosophical bent, it demonstrates a technique that can be helpful when you’re building applications. When you’re using Apache XML-RPC, you can mess up the arguments you pass to XmlRpcClient’s execute method. We’ll show you a way to use Java dynamic proxies along with an interface to make things a bit easier. You’ll define an interface that contains the procedures you want to use via XML-RPC (shown in the following listing). Instead of dealing directly with XML-RPC, you’ll deal with a Java dynamic proxy that implements this interface. The dynamic proxy takes care of translating a call on the interface methods into an XML-RPC call. You’ll use the same interface on the server side to help define the server-side handler. By using the interface, you can eliminate errors that occur due to problems setting up the parameter Vector:

  1: /*   2:  *    3:  * BookHandler.java   4:  *    5:  * Example from "Professional XML Development with Apache Tools"   6:  *   7:  */   8: package com.sauria.apachexml.ch8;   9:   10: public interface BookHandler {  11:     public Boolean createBook(String author, String title,   12:                                String isbn, String month,   13:                                int year, String publisher,   14:                                String address);  15: }

The real work is done by the XmlRpcProxy class shown next. A dynamic proxy is a class that acts as a proxy for another class. (Dynamic proxies are available only in JDK 1.3 and above.) The proxied class must implement some number of interfaces. The dynamic proxy can intercept the invocation of those interfaces’ methods. The neat thing about dynamic proxies is that the proxy relationship can be set up at runtime, not compile time. When a dynamic proxy is created, it needs an object that implements the InvocationHandler interface, because this is how the proxy describes the interception behavior. To keep things neat, the class that implements InvocationHandler normally provides a factory method that creates a dynamic proxy that uses that InvocationHandler. The dynamic proxy usually wraps the methods of the class it’s proxying.

The newInstance method is the factory method used to obtain an XmlRpcProxy. The obj argument is the class that will be proxied, the String url is the URL of the XML-RPC server, and the String handler is the name of the XML-RPC handler on which the proxy will invoke methods:

  1: /*   2:  *    3:  * XmlRpcProxy.java   4:  *    5:  * Example from "Professional XML Development with Apache Tools"   6:  *   7:  */   8: package com.sauria.apachexml.ch8;   9:   10: import java.lang.reflect.InvocationHandler;  11: import java.lang.reflect.Method;  12: import java.lang.reflect.Proxy;  13: import java.util.Vector;  14:   15: import org.apache.xmlrpc.XmlRpcClient;  16:   17: public class XmlRpcProxy implements InvocationHandler {  18:     String url = null;  19:     String handler = null;  20:     Object obj;  21:     XmlRpcClient xmlProxy;  22:       23:     public static Object newInstance(Object obj,   24:                                       String handler,   25:                                       String url) {  26:         return Proxy.newProxyInstance(  27:             obj.getClass().getClassLoader(),   28:             obj.getClass().getInterfaces(),   29:             new XmlRpcProxy(obj, handler, url));  30:     }

Instances of XmlRpcProxy save the object being proxied, the URL of the XML-RPC server, and the XML-RPC handler to invoke. This is more information than you need. You don’t need to save the object being proxied—the method you’re invoking is just a type-safe template you’re using to protect against errors in using XML-RPC. All the real work is done by the remote method. You can see that in the invoke method; you never use obj (the object being proxied):

 31:   32:     public XmlRpcProxy(Object o, String u, String h) {  33:         obj = o;  34:         url = u;  35:         handler = h;          36:     }  37:   38:     public Object invoke(Object proxy, Method method,   39:                          Object[] args)  40:         throws Throwable {

The body of the invoke method is responsible for invoking the XML-RPC procedure. Invoke is called when any proxied method is called. In this example, when someone calls the createBook method on the dynamic proxy, invoke is called to handle it.

Invoke first builds up XML-RPC’s Vector of parameters by iterating over the args[] array. This is how you convert from the type-safe signature method createBook in the BookHandler interface to the non-type-safe Vector of parameters needed by XML-RPC. All you have to do is copy the argument values into the Vector. The type-checking has been done at compile time:

 41:         Object result = null;  42:         Vector params = new Vector();  43:   44:         for (int i = 0; i < args.length; i++) {  45:             params.add(args[i]);  46:         }

Now you create an instance of XmlRpcClient so you can invoke the method:

 47:          48:         xmlProxy = new XmlRpcClient(url);

Finally, the proxy executes the XML-RPC call and returns the result:

 49:         result = xmlProxy.execute(handler+"."+method.getName(),  50:                                   params);  51:           52:         return result;  53:     }  54: }

XmlRpcProxyTest is the test class that shows off how this technique works. Lines 10-21 show how you implement the BookHandler interface, and the main method shows how you use it:

  1: /*   2:  *    3:  * XmlRpcProxyTest.java   4:  *    5:  * Example from "Professional XML Development with Apache Tools"   6:  *   7:  */   8: package com.sauria.apachexml.ch8;   9:   10: public class XmlRpcProxyTest implements BookHandler {  11:   12:     public Boolean createBook(  13:         String author,  14:         String title,  15:         String isbn,  16:         String month,  17:         int year,  18:         String publisher,  19:         String address) {  20:         return null;  21:     }  22:   23:     public static void main(String[] args) {  24:         Object o = XmlRpcProxy.newInstance(  25:                        new XmlRpcProxyTest(),   26:                        "http://localhost:8080",  27:                        "books");  28:                          29:         BookHandler h = (BookHandler) o;

You call the factory method on XmlRpcProxy to create a proxy instance that uses the XML-RPC server at http://localhost:8080 and dispatches to the handler named books that’s registered on that serer. You also need to cast the proxy class to the BookHandler interface.

All that’s left to do is call the createBook method and print the result. Note that the call to createBook is a regular Java method invocation, which is type-checked at compile time:

 30:   31:         Boolean b = h.createBook(  32:             "Theodore W. Leung",  33:             "Professional XML Development with Apache Tools",  34:             "0-7645-4355-5",  35:             "December",  36:             2003,  37:             "Wrox",  38:             "Indianapolis, Indiana");  39:         System.out.println(b);  40:     }  41: }

To round out the picture, here’s a version of BasicServer that uses the BookHandler interface. It ensures that changes to BookHandler’s methods are reflected on both the client side and the server side:

  1: /*   2:  *    3:  * BasicHandlerServer.java   4:  *    5:  * Example from "Professional XML Development with Apache Tools"   6:  *   7:  */   8: package com.sauria.apachexml.ch8;   9:   10: import java.io.FileWriter;  11: import java.io.IOException;  12: import java.io.PrintWriter;  13:   14: import org.apache.xmlrpc.WebServer;  15:   16: public class BasicHandlerServer implements BookHandler {

The only change needed to BasicServer is to make it implement BookHandler, which "coincidentally" already has the proper createBook method:

 17:   18:     public Boolean createBook(String author, String title,   19:                               String isbn, String month,   20:                               int year, String publisher,   21:                               String address) {  22:         try {  23:             PrintWriter w =   24:                 new PrintWriter(new FileWriter(isbn+".txt"));  25:             w.println(author);  26:             w.println(title);  27:             w.println(isbn);  28:             w.println(month);  29:             w.println(year);  30:             w.println(publisher);  31:             w.println(address);  32:             w.close();  33:         } catch (IOException e) {  34:             e.printStackTrace();  35:             return Boolean.FALSE;  36:         }  37:         return Boolean.TRUE;  38:     }  39:   40:     public static void main(String[] args) {  41:         BasicHandlerServer handler = new BasicHandlerServer();  42:           43:         WebServer s = null;  44:           45:         try {  46:             s = new WebServer(8080);  47:         } catch (IOException ioe) {  48:             ioe.printStackTrace();  49:         }  50:   51:         s.addHandler("books", handler);  52:     }  53: }

This concludes our tour of XML-RPC. If you need something simple and lightweight to connect a client and a server, or if you need to talk to minority languages like Python or Ruby, then XML-RPC is a good choice. For larger applications in an enterprise context, you might consider XML-RPC’s bigger cousin, SOAP. We’ll look at Apache Axis, the ASF SOAP and WSDL engine, in Chapter 9.




Professional XML Development with Apache Tools. Xerces, Xalan, FOP, Cocoon, Axis, Xindice
Professional XML Development with Apache Tools: Xerces, Xalan, FOP, Cocoon, Axis, Xindice (Wrox Professional Guides)
ISBN: 0764543555
EAN: 2147483647
Year: 2003
Pages: 95

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net