XML-RPC Library for JavaThis is a Java implementation of the XML-RPC developed by UserLand. XML-RPC is a lightweight remote protocol that uses XML to encode procedure calls and responses. This library has been designed to be easy to use and as independent from other class libraries as possible.
Download xmlrpc-java.zip. The current version is 1.0 beta 3 and was released on April 18 2000. I'll watch bug reports for a few week and evantually drop the beta tag. Click here to see what has changed since the last release.
There is a mailing list for XML-RPC/Java. Please direct all questions to this list, you'll have better chances to get a quick reply than if you send mail directly to me.
API documentation is also available. The API docs also contain information about the new applet and FESI packages, which are not described in this document.
Server side XML-RPC
Defining an XML-RPC handler
Embedding XML-RPC into an existing web server framework
Using the built-in dedicated web server
Client side XML-RPC
Choosing an XML parser
Type mapping between XML-RPC and Java
Release History
History and CreditsOn the server side, you can either embed the XML-RPC library into an existing server framework, or use the built-in special purpose HTTP server. But let's first look at how you can do something useful with XML-RPC, that is, how to tell the XML-RPC library what to do when a request comes in from a client.
Defining an XML-RPC handler
The XML-RPC server defines two methods that let your register and unregister Java objects as XML-RPC handlers:addHandler (String name, Object handler);
removeHandler (String name);Depending on what kind of handler object you give to the server, it will do one of the following things:
- If you pass the XmlRpcServer any Java object, the server will try to look up the corresponding method by looking at the method name and the parameter types of incoming requests. The input parameters of incoming XML-RPC requests must match the argument types of the Java method (see conversion table below), or otherwise the method won't be found. The return value of the Java method must be supported by XML-RPC.
- If you pass the XmlRpcServer an object that implements interface helma.xmlrpc.XmlRpcHandler you'll be in full control of how the XML-RPC request is processed, including input and output parameter conversion, special error handling etc. Note that the XmlRpcClient in this library also implements XmlRpcHandler, so it can act as an XML-RPC proxy. This is very useful for applets that can only connect to the server they came from. (Click here for a demo.)
In both cases, incoming requests will be interpreted as handlerName.methodName with handlerName being the String that the handler has been registered with, and methodName being the name of the method to be invoked. You can work around this scheme by registering a handler with the name "$default", in which case you can drop the handlerName. part from the method name.Embedding XML-RPC into an existing Web server framework
The XML-RPC library can be embedded into any Web server framework that supports reading HTTP POSTs from an InputStream. The typical code for processing an incoming XML-RPC request looks like this:XmlRpcServer xmlrpc = new XmlRpcServer ();
xmlrpc.addHandler ("examples", new ExampleHandler ());
...
String result = xmlrpc.execute (request.getInputStream ());
response.setContentType ("text/xml");
response.setContentLength (result.length ());
PrintWriter writer = response.getWriter();
writer.write (result);
writer.flush ();Note that the execute method does not throw any exception, since all errors are encoded into the XML result that will be sent back to the client.A full example servlet is included in the package.
Using the built-in dedicated Web server
Client side XML-RPC
The XML-RPC library comes with its own built-in HTTP server. This is not a general purpose web server, its only purpose is to handle XML-RPC requests. The HTTP server can be embedded in any Java application with a few simple lines:WebServer webserver = new WebServer (port);
webserver.addHandler ("examples", someHandler);You can also start the web server from the command line by typing
java helma.xmlrpc.WebServer
You can specify the server port, but there's no way to manipulate RPC handlers in command line mode, so you'll either have to modify WebServer.java for your purposes or embed it into your own application.
A special bonus when using the built in Web server is that you can set the IP addresses of clients from which to accept or deny requests. This is done via the following methods:
webserver.setParanoid (true); // deny all clients
webserver.acceptClient ("192.168.0.*"); // allow LAN access
webserver.denyClient ("192.168.0.3"); // except for this one
...
webserver.setParanoid (false); // disable client filterIf the client filter is activated, entries to the deny list always override those in the accept list. Thus, webserver.denyClient ("*.*.*.*") would completely disable the web server.
Note that the XML-RPC client in Frontier 5 has its requests hard-coded to URI /RPC2. To work with these clients, you have to configure your server environment to respond to /RPC2. This should be fixed in a newer version.
Using the XML-RPC libray on the client side is quite straightforward. Here is some sample code:Choosing an XML parserXmlRpcClient xmlrpc = new XmlRpcClient
("http://localhost:8080/RPC2");
Vector params = new Vector ();
params.addElement ("some parameter");
// this method returns a string
String result = (String) xmlrpc.execute
("method.name", params);Note that execute can throw XmlRpcException and IOException, which must be caught or declared by your code.
To quickly test your installation you can issue the following command:
java helma.xmlrpc.XmlRpcClient 12
This should call examples.getStateName(12) at nirvana.userland.com:80.
An XML parser is needed both on the client and the server side of an XML-RPC call. The XML-RPC library uses the SAX API to allow different parsers to be plugged in. A list of parsers that support the SAX API is available at that site. The default parser used is now the OpenXML parser. To parser can be set directly by calling:
XmlRpc.setDriver ("your.sax.driver");
Alternatively you can set the parser by defining the System property sax.driver.
java -Dsax.driver=your.sax.driver helma.xmlrpc.WebServerYou can use user friendly shortcuts for some drivers. These drivers/shurtcuts are:
jview /d:sax.driver=your.sax.driver helma.xmlrpc.WebServer
- "ibm1" for IBM's XML4J 1.x
- "ibm2" for IBM's XML4J 2.x
- "xp" for James Clark's XP
- "aelfred" for Microstar's AElfred
- "oracle1" for Oracle's XML Parser 1
- "oracle2" for Oracle's XML Parser 2
- "openxml" for the OpenXML parser (default)
If you use a different parser let me know and I'll add it to the shortcut list for the next version.
Type mapping between XML-RPC and JavaThe following table shows type conversions from XML-RPC to Java.Release History
Note that the automatic invocation mechanism expects your classes to take the primitive data types as input parameters. If your class defines any other types as input parameters (including java.lang.Integer, long, float), that method won't be usable from XML-RPC unless you write your own handler.
For return values, both the primitive types and their wrapper classes work fine.
XML-RPC data type Data Types generated
by the ParserTypes expected by the
Invoker as input parameters
of RPC handlers<i4> or <int> java.lang.Integer int <boolean> java.lang.Boolean boolean <string> java.lang.String java.lang.String <double> java.lang.Double double <dateTime.iso8601> java.util.Date java.util.Date <struct> java.util.Hashtable java.util.Hashtable <array> java.util.Vector java.util.Vector <base64> byte[ ] byte[ ] <nil/> null null 1.0 beta 3 April 17, 2000History and Credits1.0 beta 2 April 17, 2000
- Solved performance issue introduced in beta 2
- Made Keep-Alive connections switchable and disabled by default
- Made the main method of XmlRpcClient more useful than it used to be.
1.0 beta April 17, 2000
- Solved interoperability problem with Python XML-RPC
- Cleaned up WebServer, XmlRpcClient and XmlRpcApplet in the process
0.5.1 July 15, 1999
- Switched to OpenXML as default XML parser
- Support for experimental <nil/> element
- Updated FESI support to version 1.1.4
- Adding a handler named "$default" remote methods can be called without specifying the handler in the method name
- Quite a few bug fixes
0.5 July 5, 1999
- Fixed bug where error state was not reset in XmlRpc.java.
- Updated XmlRpcServlet to use single XmlRpcServer
0.4.2 March 18, 1999 (based in part on feedback to 0.4)
- Improved error handling. With this version, a decent fault message should be reported on the client side even when something very unexpected happens.
- Improved performance by adding initial HTTP/1.1 support, namely persistent (keep-alive) connections.
- Renamed the addXXXArg methods in the LiveConnect applet (JSXmlRpcApplet).
- Changed the Benchmark class to work around bugs in JITs.
- Updated list of known SAX parsers.
- Brushed this page.
0.4 March 17, 1999
- Added URI parameter to XmlRpcApplet tags to enable changing the HTTP request path.
- XmlRpcClient now uses the HTTP request path passed in the constructor (previously always used /RPC2).
- Switched debugging output off in WebServer.
- Fixed some problems with FESI support
0.3 January 29, 1999
- Made XmlRpcClient thread-save too. That means that clients will neither block nor return wrong results when being called simultaneously by different threads.
- XmlRpcClient now implements XmlRpcHandler and can therefore act as an XML-RPC Proxy when registered within a server.
- Added XmlRpcApplet classes.
- Added support for the FESI EcmaScript interpreter.
- Removed XmlRpcClient constructors that take XML-RPC method name and argument list as parameter. If you used these constructors you have to pack the method name and argument list in the actual XML-RPC method call. This seems cleaner to me, but if you'd still like to have the old constructors let me know.
0.2 January 24, 1999 initial release
- Added setDebug method to XmlRpc.
- Made XmlRpcServer thread-save.
- Made XmlRpcClient synchronized.
The initial idea for implementing XML-RPC in Java came from Tom Fürstner at the time we were working together at the Austrian Broadcasting Corporation's online division. Tom is a big supporter of both Userland Frontier and XML and has helped me to see the value of XML-RPC.
Since the first release there have been a lots of improvements and bug fixes contributed by a lot of people. Although I' sure to forget some of them I'd like to thank Matthew Woodard, Colin Sampaleanu, Daniel Beaudry, Matthew Dornquast, John Jordano, Bernd-Christoph Schwede, Scott McLoughlin, Roger Wright, Oleg Moroz, John Snell, Josh Lucas and Skip Montanaro for their feedback and contributions. If I forgot to mention you let me know.