XML-RPC: A Simpler Calling Plan

Over the years, there have been numerous attempts to create a standard protocol for remote procedure calls (RPC). While the techniques and technology for remote procedure calls have differed, the intent of RPC was and is the same to this day: enable an application running on one machine to call a procedure in a separate process running on another machine. Ideally, a well-designed RPC protocol can connect any two machines interconnected via the Internet or some other network, even if the machines have different hardware or run different operating systems.

Over the years, there have been numerous attempts to create a standard protocol for remote procedure calls (RPC). While the techniques and technology for remote procedure calls have differed, the intent of RPC was and is the same to this day: enable an application running on one machine to call a procedure in a separate process running on another machine. Ideally, a well-designed RPC protocol can connect any two machines interconnected via the Internet or some other network, even if the machines have different hardware or run different operating systems.

Java has its own technology for remote procedure calls named Remote Method Invocation (RMI). However, like other RPC technologies such as the Common Object Request Broker Architecture (CORBA) and Open Network Computing RPC from Sun, RMI is very complex.

A refreshingly simple, but effective alternative to RMI (and SOAP and others) is XML-RPC. XML-RPC, which was intentionally designed to be easy to learn and easy to implement, exchanges information using a combination of HTTP and XML.

XML-RPC was first released in 1998 as a draft specification by Dave Winer of UserLand Software, and was first implemented in Frontier, UserLand’s content management system. However, the draft took on a life of its own, and now appears in software from Red Hat (the Red Hat Network, a subscription service that enables Linux systems to be updated over the Internet, makes heavy use of XML-RPC) and many other developers in the commercial and open source world.

Using XML-RPC, clients and servers exchange data using HTTP for transport and XML for encoding. The XML-RPC protocol supports these data types:

  • *base64 represents binary data in Base 64 format.

  • *boolean is self-evident, where 1 is true, and 0 is false.

  • *dateTime.iso8601 is a string containing the date and time in ISO8601 format (for example, 20030113T08:45 :05 is 8:45:05 p.m. on January 13, 2003).

  • *double represents eight-byte signed floating-point numbers

  • *int (also called i4) represents signed integers ranging in value from -2,147,483,648 to 2,147,483,647, the same size as int values in Java

  • *string is arbitrary text.

  • *struct is a set of name-value pairs, where the name is a string and the value can be any of the other data types. struct is comparable to Java’s HashMap class.

XML-RPC also supports the array data type, which holds any other kind of data, including other arrays. (The protocol’s full specification can be read on the Web at http://www.xmlrpc.com/spec.)

An XML-RPC client is a program that connects to a XML-RPC server, calls a method on that server, and stores the result.

An XML-RPC server is a program that accepts an incoming XML-RPC client request, calls a method in response to the incoming request, and returns the result. The XML-RPC server also maintains a list of methods clients are allowed to call.

Data To and Fro: Requests and Responses

An XML-RPC request is XML data that’s sent to a server as part of an HTTP POST. POST requests are normally used to transmit data from a Web browser to a Web server. Programs such as Common Gateway Interface scripts and Java servlets take the request, act on the data, and send HTML back in response. Similarly, XML-RPC uses HTTP as a convenient protocol for communicating with a server and receiving a response.

An XML-RPC request consists of two parts: the HTTP headers required for a POST transmission, and the actual remote procedure call encoded using XML.

Here’s an example of a request to the XML-RPC server located at http://www.advogato.org/XMLRPC:

Host: www.advogato.org
Connection: Close
Content-Type: text/xml
Content-Length: 151
User-Agent: OSE/XML-RPC

<?xml version=”1.0″?>

The HTTP headers start with POST and end with User-Agent. The XML-RPC service being called (http://www.advogato.org/XMLRPC) is reflected in the POST and Host headers. The actual remote procedure call is encapsulated in the methodCall element: the method name is test.square, and the method is being called with one argument, the (int) 14.

Method names in an XML-RPC request do not include parentheses. Instead, method names consist of either a program name followed by a period and a method name, or just a method name, depending on the configuration of the XML-RPC server. An XML-RPC request can also contain more than one argument; each is simply enclosed in its own <param> element.

An XML-RPC response is just another XML sequence returned from the server using HTTP. Like XML-RPC requests, responses also consist of HTTP headers and an XML response. Here’s an example:

HTTP/1.0 200 OK
Date: Wed, 03 Jan 2003 22:08:09 GMT
Server: Apache/1.3.26 (Unix) Debian GNU/Linux mod_virgule/1.40PHP/4.1.2
ETag: “PbT9cnw52OqREFNAAMgXsX==”
Content-MD5: PbT9cnw52OqREFNAAMgXsX==
Content-Length: 157
Connection: close
Content-Type: text/xml

<?xml version=”1.0″?>

An XML-RPC response is similar to a request, but <methodResponse> encapsulates the data instead of <methodCall>. As indicated by the Content-Length header, the response is 157 bytes long, uses the text/xml MIME type, and returns one value, (int) 196.

An XML-RPC response must contain one return value, even if the remote method does not need to return anything. The return value in the response can be any of the supported data types.

(The previous two XML-RPC examples are based on the Advogato XML-RPC interface, which is documented on the Web at http://www.advogato.org/xmlrpc.html. If you’d like to see more examples, Dumpleton Software’s free XML-RPC debugger can be used to call remote methods and capture the request and response. To get the debugger, visit http://www.dscpl.com.au/xmlrpc-debugger.php.)

Though it’s possible to work with XML-RPC by producing and consuming XML directly, Java programmers are likely to prefer a class library that abstracts the specifics of the XML-RPC protocol. Apache XML-RPC, composed of the org .apache.xmlrpc package and three related packages, does just that, and can be used to implement an XML-RPC client and server with a trivial amount of code.

Apache XML-RPC is part of Apache XML, a collection of open source Java projects that includes the Cocoon publishing framework, Xerces XML parser, and Xalan XSLT processor. Apache XML-RPC, currently at version 1.1, is available from the project home page at http://xml.apache. org/xmlrpc. The project is offered in a compressed tar archive that contains the JAR files xmlrpc-1.1.jar and xmlrpc-1.1-applet.jar. These JAR files should be installed in a convenient location and added to the CLASSPATH environmental variable.

XML-RPC Java Clients

Using Apache XML-RPC, calling a remote procedure is very similar to any other method call in Java — better yet, there’s no need to create or parse XML or use Java’s networking classes to communicate with the server.

The org.apache.xmlrpc.XmlRpcClient class represents a client. It has three constructors, and each requires the URL of a server:

  • XmlRpcClient(String) creates a client of the server specified by the String argument, which must be a valid Web address such as http://www.example.com/RPC2, or a valid Web address and port number such as http://www.example.com/RPC2:7422.

  • XmlRpcClient(URL) creates a client of the server specified by the URL argument.

  • XmlRpcClient(String, int) creates a client of the server specified by the host name (String) and port number (int) arguments.

The constructors that require a String argument throw java.net.MalformedURLException if the argument is not a valid URL.

Here’s an example of using the first constructor to create a client:

XmlRpcClient client = new XmlRpcClient (“http://cadenhead.org:4413“);

This statement creates a client to an XML-RPC server on the host cadenhead.org at port 4413.

A remote method request is sent to the server by calling the XmlRpcClient method execute() after the arguments to the method (if any) have been prepared.

If a remote method takes one or more arguments, they should be stored in a java. util.Vector object, a data structure that can hold objects of different classes. The easiest way to fill a Vector is to call its constructor with no arguments and repeatedly call its addElement(Object) method to add each object. Apache XML-RPC automatically converts the objects in the Vector to XML-RPC data types.

The following Java data types can be used as arguments:

  • byte[] arrays for base64 data.

  • Boolean objects for boolean values.

  • java.util.Date objects for dateTime.iso8601 values.

  • Double objects for double values.

  • Integer objects for int values.

  • String objects for XML-RPC string values.

  • Hashtable objects for struct values.

  • Vector objects for arrays.

Objects must be added to a Vector in the same order as the remote procedure call’s formal arguments. For example, if an XML-RPC server has a method that requires a String and a Double argument, this code creates an appropriate Vector:

String studentName = “Rogers Cadenhead”;
Double gpa = new Double(2.25);
Vector parameters = new Vector();

If a remote method does not require any arguments, simply create a Vector using new(), and leave it empty.

After the argument list is prepared, the XML-RPC request is sent by calling the XmlRpcClient object’s execute (String, Vector) method with two arguments: the name of the method as a String, and the Vector that holds the method’s arguments. The method name should be specified without parentheses or arguments.

For example, one method on the http://cadenhead.org XML-RPC server is dmoz.getRandomSite, which expects no arguments and returns a string containing information about a randomly selected Web site from the Open Directory Project at http://www.dmoz.org. Here’s how to create an XML-RPC client to call this method:

XmlRpcClient client = new XmlRpcClient(“http://cadenhead.org:4413“);
// Create an empty vector
Vector params = new Vector();
Object result = client.execute (“dmoz.getRandomSite”, params);

The execute() method throws java.net.IOException if something goes wrong during the client/server connection, and throws XmlRpcException if the server reports an XML-RPC error.

The response from the XML-RPC method is returned as an Object by the execute() method. This object can be cast to any of the XML-RPC-compatible Java data types (Boolean, byte[], Date, Double, Integer, String, Hashtable, or Vector).

Listing One shows AdvogatoClient, a Java application that uses an XML-RPC interface provided by the open source site Advogato for reading and writing user diaries. AdvogatoClient calls two methods: diary.len(String username), which returns a count of the number of entries in a user’s diary, and diary.get(String username, int index), which returns a specific diary entry written by that user.

Listing One: An XML-RPC client

import java.io.*;
import java.util.*;
import java.net.*;
import org.apache.xmlrpc.*;

public class AdvogatoClient {
public static void main(String arguments[]) {
AdvogatoClient client = new AdvogatoClient();
try {
} catch (IOException ioe) {
System.out.println(“IO Exception: ” + ioe.getMessage());
} catch (XmlRpcException xre) {
System.out.println(“XML-RPC Exception: ”
+ xre.getMessage());

public void readEntries(String username)
throws IOException, XmlRpcException {

// Create the client
XmlRpcClient client = new XmlRpcClient(
// Create the parameters for the request
Vector params = new Vector();
// Send the request and get the response
Integer result = (Integer)client.execute(“diary.len”, params);
for (int i = result.intValue() – 1; i > 0; i–) {
Integer index = new Integer(i);
// Create a request to read an entry
// Send the request
String entry = (String)client.execute(“diary.get”, params);
System.out.println(entry + “\n”);

As you can see, Apache XML-RPC handles the XML parsing and all of the networking. All a Java programmer has to do is create an object, prepare some arguments, and make the remote method call — just like any other Java procedure call.

XML-RPC Servers

Just like writing a client, writing a server with Apache XML-RPC is very simple: just write the code for the remote method, and make sure that it’s accessible. And the simplest way to implement a server is to use the WebServer class, an HTTP Web server that only responds to XML-RPC requests.

The WebServer class has two constructors:

  • WebServer(int) creates a server that listens on the specified port number.

  • WebServer(int, java.net.InetAddress) creates a server at the specified port and IP address.

Both constructors throw IOException to signal an input/output problem.

Here’s an example that creates an XML-RPC Web server on port 3314:

int port = Integer.parseInt(“3314″);
WebServer server = new WebServer(port);

The WebServer can contain the remotely-callable methods or they can be contained in other classes. A class that contains a remote method is called a handler. A handler must be added to a WebServer by calling the WebServer method addHandler(String, Object), where String is the handler name and Object is the handler object.

Many existing Java classes can be put to use as XML-RPC handlers without modification. The WebServer will allow any public method in the handler to be called, so access control must be used to keep clients out of methods they should not be able to call.

Clients use the handler’s name, which doesn’t have to be a class name, when calling the handler’s public methods. For example, the AdvogatoClient in Listing One calls the remote method diary.len(). The first part of the method name, diary, refers to a handler named diary.

Here’s an implementation of an XML-RPC server:

int port = Integer.parseInt(portString);
WebServer server = new WebServer(port);
WebLogHandler wh = new WebLogHandler(
server.addHandler(“weblog”, wh);

This code creates a handler for a WebServer object, and adds, it to the server.

Remember, a handler can be any Java class that contains public methods, as long as the methods take arguments that correspond with the data types supported by Apache XML-RPC.

Listing Two: An XML-RPC server

import java.io.IOException;
import org.apache.xmlrpc.WebServer;
import org.apache.xmlrpc.XmlRpc;

public class WebLogServer {
public static void main(String[] arguments) {
if (arguments.length < 1) {
System.out.println(“Usage: java WebLogXmlRpcServer[port]“);
try {
} catch (IOException ioe) {
System.out.println(“Server error: ” +

public static void startServer(String portString)
throws IOException {

// Start the server
int port = Integer.parseInt(portString);
System.out.println(“Starting server …”);
WebServer server = new WebServer(port);

// Register the handler
WebLogHandler wh = new WebLogHandler(
server.addHandler( “weblog”, wh);
System.out.println(“Accepting requests …”);

Listing Two contains the source code for WebLogServer, a Java application that processes XML-RPC requests using one handler, a WebLogHandler object named weblog. WebLogHandler is shown in Listing Three. The server should be run with a port number:

Listing Three: An XML-RPC handler

import java.io.*;
import java.util.*;

public class WebLogHandler {
String access = “/etc/httpd/logs/access_log”;
String error = “/etc/httpd/logs/error_log”;

public WebLogHandler(String access, String error) {
this.access = access;
this.error = error;

public Vector getRecentLogs(String type, int count) {
Vector lastEntries = new Vector();
BufferedReader in = null;
try {
Runtime run = Runtime.getRuntime();
Process proc;
if (type.equals(“access”))
proc = run.exec(“tail -” + count + ” ” + access);
proc = run.exec(“tail -” + count + ” ” + error);
if (proc == null)
throw new IOException(“Could not run process”);
in = new BufferedReader(new InputStreamReader(
String line;
while ((line = in.readLine()) != null)
} catch (IOException io) {
return lastEntries;

# java WebLogServer 4000

Call Me Sometime

XML-RPC was designed to be the “lowest common denominator” of remote procedure call protocols, capable of exchanging information with any software that supports HTTP and XML parsing. Indeed, XML-RPC forms the basis of Web services implemented by many software developers on Windows, Macintosh, Linux, and Unix.

If Apache XML-RPC doesn’t suit your needs or if you need a non-Java library (to deploy a client, say), there are more than two dozen XML-RPC implementations available for Java, C++, PHP, and other languages. UserLand Software maintains a directory of XML-RPC implementations at http://www.xmlrpc.com.

Next month, we’ll take a look at Enterprise Java Beans (EJB), the component architecture for Java that enables the rapid development of scalable enterprise applications.

Rogers Cadenhead is a Web application developer and the coauthor of Teach Yourself Java 2 in 21 Days, Third Edition from Sams Publishing. To contact Cadenhead, visit his weblog at http://www.cadenhead.org/workbench. You can download the source code used in this column at http://www.linux-mag.com/downloads/2003-01/java.

Comments are closed.