Buy this Book
Print Book $34.95 Read it Now!
Print Book £24.95
Add to UK Cart
Reprint Licensing

Programming Web Services with XML-RPC
Programming Web Services with XML-RPC

By Simon St. Laurent, Joe Johnston, Edd Dumbill
Foreword by Dave燱iner
Price: $34.95 USD
£24.95 GBP

Cover | Table of Contents | Colophon


Table of Contents

Chapter 1: Introduction
Have you ever wanted to publish information on the Web so programs beyond browsers could work with it? Have you ever needed to make two or more computers running different operating systems and programs written in different languages share processing? Have you ever wanted to build distributed applications using tools that let you watch the information moving between computers rather than relying on "package and pray?"
Web services are a set of tools that let you build distributed applications on top of existing web infrastructures. These applications use the Web as a kind of "transport layer" but don't offer a direct human interface via the browser. Reusing web infrastructures can drastically lower the cost of setting up these applications and allows you to reuse all kinds of tools originally built for the Web.
XML-RPC is among the simplest (and most foolproof) web service approaches, and makes it easy for computers to call procedures on other computers. XML-RPC reuses infrastructure that was originally created for communications between humans to support communications between programs on computers. Extensible Markup Language (XML) provides a vocabulary for describing Remote Procedure Calls (RPC), which are then transmitted between computers using the HyperText Transfer Protocol (HTTP).
XML-RPC can simplify development tremendously and make it far easier for different types of computers to communicate. By focusing on computer-to-computer communications, XML-RPC lets you use web technologies without getting trapped in the focus on human-readable content that has characterized most previous web development. Most of the XML-RPC framework will be familiar to web developers, but as a web developer, you will probably use off-the-shelf packages to connect your programs.
The rest of this book explores this simple, but powerful, approach more thoroughly using various development techniques. Chapter 3 through Chapter 7 explore the XML-RPC libraries available for Java, Perl, PHP, Python, and Active Server Pages, and Chapter 8 takes a look at XML-RPC's future. But before we can dive into the details of the XML-RPC protocol in Chapter 2, we need to lay some basic groundwork. The rest of this chapter covers what XML-RPC does, where it excels, and when you may not want to use it.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
What XML-RPC Does
At the most basic level, XML-RPC lets you make function calls across networks. XML-RPC isn't doing anything especially new, and that largely explains why XML-RPC is useful. By combining an RPC architecture with XML and HTTP technology, XML-RPC makes it easy to for computers to share resources over a network. This means that you can give users direct access to the information they need to process, not just read and reuse systems you've already built in new contexts, or mix and match programs so that each can focus on what it does best.
Remote Procedure Calls (RPC) are a much older technology than the Web. Although the concept of computers calling functions on other systems across a network has been around as long as networks have existed, Sun Microsystems is usually given credit for creating a generic formal mechanism used to call procedures and return results over a network. RPC fit very well with the procedural approach that dominated programming until the 1990s.
Say you have a procedure that calculates momentum. This function knows the speed and name of the object, but it needs to know the object's mass to calculate the momentum. It needs to call a procedure that returns the mass for a given object. For a local procedure call, this is fairly straightforward. Programming languages let you divide your programs into procedures (or functions or methods) that call one another. The syntax is different, but generally, you can pass parameters and get a result:
mass=getMass(objectID)
Now imagine that getMass( )is implemented on a remote system. In this case, calling the procedure requires your program to know a lot more about a more complex process. Your program needs to know which remote system to contact, how to package and send the parameters, how to receive an answer, and how to unpackage and present that answer to the routine that called it originally.
Although the RPC approach involves considerable extra overhead, with libraries on both sides of the connection creating and processing messages, as well as the possibility of delays in crossing the network, the approach does permit distributed processing and sharing of information.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Where XML-RPC Excels
XML-RPC is an excellent tool for establishing a wide variety of connections between computers. If you need to integrate multiple computing environments, but don't need to share complex data structures directly, you will find that XML-RPC lets you establish communications quickly and easily. Even if you workwithin a single environment, you may find that the RPC approach makes it easy to connect programs that have different data models or processing expectations and that it can provide easy access to reusable logic.
XML-RPC's most obvious field of application is connecting different kinds of environments, allowing Java to talk with Perl to talk with Python to talk with ASP, and so on. Systems integrators often build custom connections between different systems, creating their own formats and protocols to make communications possible, but they often end up with a large number of poorly documented single-use protocols. Each piece might work very well at its appointed task, but developers have to constantly create new protocols for new tasks, and reusing previous protocols can be very difficult.
XML-RPC offers integrators an opportunity to use a standard vocabulary and approach for exchanging information. This means that developers can create open programming interfaces. Sometimes a project has clearly defined needs for connecting two or more specific environments together, and a small set of XML-RPC packages can help create a complete solution. In other cases, developers want to publish a service but don't necessarily know what kinds of clients they have to support.
XML-RPC makes it possible for services like Meerkat (http://meerkat.oreillynet.com) to provide an interface that can be accessed from several different environments. Meerkat, which aggregates news and announcement information from hundreds of sites, can be searched through a traditional web interface or through an XML-RPC interface (documented at http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html). Developers who want to use Meerkat information in their own applications can call functions on the Meerkat server, and Meerkat's maintainers don't need to know anything about the details.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A Quick Tour of the Minefields
Before moving into the details of XML-RPC and exploring its capabilities in depth, it's worth pausing for a moment to examine some possible areas where using XML-RPC may not be appropriate. Although RPC and tunneling over HTTP are both useful technologies, both techniques can get you into trouble if you use them inappropriately. Neither technique is exactly the height of computing elegance, and there are substantial scalability and security issues that you should address at the beginning of your projects rather than at the end.
RPC architectures have some natural limitations. There are plenty of cases when RPC is still appropriate, including some when combining logic with data in objects is either risky or excessively complex, and messaging might require additional unnecessary overhead. On the other hand, RPC lacks the flexibility made possible by the other approaches because of the relative simplicity of its architecture. The level of abstraction in RPC is relatively low, leading to potential complexity as the number of different requests increases.
Although the descriptions in the previous section might suggest that RPC is just a message-passing mechanism, the messages can't be arbitrary. Remote Procedure Calls, like procedure calls in programs, take a procedure name and a set of typed parameters and return a result. Although developers can build some flexibility into the parameters and the result, the nature of procedure calls brings some significant limitations for development, flexibility, and maintenance.
Development methodologies have spent the last 50 years moving toward looser and looser connections between computing components -- on both the hardware and software sides. Looser connections mean more flexibility for consumers of computing products and their developers. XML-RPC provides some flexibility, abstracting away differences between computing environments, but the procedures to which it is applied supply only limited flexibility. Careful API design can help developers create maintainable systems, but changing APIs is often more difficult than adding additional information to a message. If different systems need to see their information in different forms, API complexity can grow rapidly.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 2: The XML-RPC Protocol
This chapter describes the XML-RPC protocol -- that is, the sequence and structure of requests and responses required to invoke computations on a remote machine using XML and HTTP. It also covers XML-RPC's data types, a subset of those commonly found in programming languages. If you plan to use an available XML-RPC library to create XML-RPC clients and servers, you don't need to understand all the details of the XML-RPC protocol. However, when you need to debug your service, you'll find it quite helpful to know about the protocol details. This chapter also provides the information you need to implement your own XML-RPC library, should there not be a library for your particular environment.
This chapter, and the rest of the book for that matter, assume that you have a basic understanding of both XML and HTTP. This knowledge is critical to your ability to understand XML-RPC. If you don't know much about XML or HTTP, or if you just want to refresh your memory about the basics, you should check out Appendix A and Appendix B.
The current chapter explains the XML-RPC specification (found online at http://www.xmlrpc.com/spec), which is the first point of reference for the technology. In addition, the chapter draws upon current practice to recommend guidelines for implementation and use, and to highlight areas for future specialization or extension of the technology.
An XML-RPC call is conducted between two parties: the client (the calling process) and the server (the called process). A server is made available at a particular URL (for example, http://example.org:8080/rpcserv/). To use the procedures available on that server, the following steps are necessary:
  1. The client program makes a procedure call using the XML-RPC client, specifying a method name, parameters, and a target server.
  2. The XML-RPC client takes the method name and parameters and then packages them as XML. Then the client issues an HTTP
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Choreography
An XML-RPC call is conducted between two parties: the client (the calling process) and the server (the called process). A server is made available at a particular URL (for example, http://example.org:8080/rpcserv/). To use the procedures available on that server, the following steps are necessary:
  1. The client program makes a procedure call using the XML-RPC client, specifying a method name, parameters, and a target server.
  2. The XML-RPC client takes the method name and parameters and then packages them as XML. Then the client issues an HTTP POST request containing the request information to the target server.
  3. An HTTP server on the target server receives the POST request and passes the XML content to an XML-RPC listener.
  4. The XML-RPC listener parses the XML to get the method name and parameters and then calls the appropriate method, passing it the parameters.
  5. The method returns a response to the XML-RPC process and the XML-RPC process packages the response as XML.
  6. The web server returns that XML as the response to the HTTP POST request.
  7. The XML-RPC client parses the XML to extract the return value and then passes the return value back to the client program.
  8. The client program continues processing with the return value.
There is nothing to stop a process from being both a server and a client, making and receiving XML-RPC requests. It is important, however, to recognize that in any single XML-RPC request, there are always the two roles of client and server.
The use of HTTP means that XML-RPC requests must be both synchronous and stateless.
An XML-RPC request is always followed by exactly one XML-RPC response; the response is synchronous with the request. This happens because the response must occur on the same HTTP connection as the request.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Data Types
XML-RPC calls closely model function calls in programming languages. An invocation of a remote method is accompanied by data in the form of parameters , and the response to that method contains data as a return value. Although a request may contain multiple parameters, the response must contain exactly one return value.
To represent these values, XML-RPC defines an XML representation for program data. It does this for several basic data types, such as integers and strings, and for compound data structures, such as arrays.
Any data item in an XML-RPC request or response is contained within a <value> ... </value> element.
XML-RPC defines a set of simple data types, from which other, more complex, data structures can be built. These types are common to most programming languages.

Section 2.2.1.1: Integers

XML-RPC has exactly one data type for integers. It is capable of representing a 32-bit signed integer: any integer between -2,147,483,648 (-231) and 2,147,483,647 (231-1). It has two interchangeable representations:
<value><i4>n</i4></value>
or:
<value><int>n</int></value>
(Note that the 4 in i4 is derived from the length of the integer: four octets, 32 bits.)
XML-RPC implementations must recognize both of these representations as input data. No recommendation is given as to which form they should use when generating output data, however. Because XML-RPC is strict about its limitations to 32-bit signed integers, it makes no difference which form is used: if larger integers (or bignums , arbitrarily large integers) are ever incorporated into the specification, another element name must be found anyway.
The character string representing the integer may contain no whitespace or other characters; that is, between <int> and </int> there may only occur the characters
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Request Format
XML-RPC defines an HTTP and XML request sent to a server to cause the server to perform an action. This request has two parts: the HTTP headers, which identify the server; and the XML payload, which contains information about which method to invoke.
The XML section of an XML-RPC request carries the name of the remote method to be invoked, along with all necessary parameters. The entire message is enclosed within <methodCall> </methodCall> tags. The method name is then given in the <methodName> ... </methodName> element. This is followed by a list of parameters, enclosed within <params> ... </params>. Each parameter is an XML-RPC value, as defined in the data types section earlier in this chapter, and must also be enclosed in <param> ... </param> tags.
The following example shows the encoding of a method call analogous to the C-style function call print("Hello, World!"):
<?xml version="1.0"?>
<methodCall>
  <methodName>print</methodName>
  <params>
    <param>
      <value><string>Hello, World!</string></value>
    </param>
  </params>
</methodCall>

Section 2.3.1.1: Parameters

The parameter list enclosed by the <params> element may contain zero or more <param> elements. Even if the method requires no parameters, the <params> element must still be present.
Note that parameters take the form of a simple list. Several programming environments provide the ability to pass parameters referenced by name. For example, in Python you might write updateDetails(name="Fred", age=43). This has no equivalent in XML-RPC, which means you cannot create methods that take a variable number of parameters.
If you need a method that accepts a variable number of parameters, the simplest way around this problem is to use a single struct as the parameter, as follows:
<?xml version="1.0"?>
<methodCall>
  <methodName>updateDetails</methodName>
  <params>
    <param>
      <value><struct>
         <member><name>name</name>
           <value><string>Fred</string></value>
         </member>
         <member><name>age</name>
           <value><int>43</int></value>
         </member>
      </struct></value>
    </param>
  </params>
</methodCall>
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Response Format
Upon receiving an XML-RPC request, an XML-RPC server must deliver a response to the client. The response may take one of two forms: the result of processing the method or a fault report, indicating that something has gone awry in handling the request from the client. As with an XML-RPC request, the response consists of HTTP headers and an XML payload (either the method result or a fault report).
The successful invocation of a method on the server must return exactly one result -- in contrast to the request payload, which may contain many parameters. Of course, with the ability to use either arrays or structs in the return value, this is no real restriction.
A response message is enclosed in <methodResponse> ... </methodResponse> tags and contains a <params> list (with only one <param>) in much the same format as the method request payload. Here's a response to a hypothetical method that asks for the capital city of England:
<?xml version="1.0"?>
<methodResponse>
  <params>
    <param>
      <value><string>London</string></value>
    </param>
  </params>
</methodResponse>
Sometimes a remote method does not need to return any response value: the equivalent of a void function in C. However, XML-RPC mandates that exactly one parameter must be returned from a method invocation. This conflict means that if you want to use valueless methods with XML-RPC, you must use some kind of workaround. Here are some possible finesses:
  • Use a success value: return a Boolean value to indicate the success of the function. This will likely mean hardwiring the return value to true!
  • Return any value that suits you, but document your method to let a user know that the return value is meaningless.
  • Use the proposed nil value as a return value (see Section 2.5 later in this chapter).
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The Nil Value
As observed earlier, XML-RPC has no way to express a null value; that is, an absence of value. This value is commonly found in programming languages (Java's null, Python's None, Perl's undef, as well as in databases, such as NULL). Consequently, many users of XML-RPC have requested its inclusion.
Although there has been no movement to officially incorporate a null value into the XML-RPC specification, there is some experimental support for it in the Java XML-RPC implementation. A small definition of it is available on the Web at http://www.ontosys.com/xml-rpc/extensions.html.
The null value, called nil, has only one expression in XML-RPC:
<value><nil/></value>
Implementations that choose to support it should treat <nil/> as the equivalent of the host language's empty value.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
A DTD for XML-RPC
This section provides a simple Document Type Definition (commonly referred to as a DTD, as explained in Appendix A) for XML-RPC. It is provided for interest only and is not sufficient for the implementation of an XML-RPC processor. In particular, DTDs are not expressive enough to convey the restrictions on elements such as int, which may only contain specific character sequences. Additionally, the introduction of a validating XML parser into an XML-RPC stack (as opposed to hard-coding the validation) may be more overhead than it is worth, especially since the DTD alone is not sufficient to verify an incoming request.
That being said, in systems where XML validation is already used, use of this DTD may aid the integration of XML-RPC:
<!ELEMENT i4 (#PCDATA)>
<!ELEMENT int (#PCDATA)>
<!ELEMENT boolean (#PCDATA)>
<!ELEMENT string (#PCDATA)>
<!ELEMENT double (#PCDATA)>
<!ELEMENT dateTime.iso8601 (#PCDATA)>
<!ELEMENT base64 (#PCDATA)>
<!ELEMENT data (value*)>
<!ELEMENT array (data)>
<!ELEMENT name (#PCDATA)>
<!ELEMENT member (name, value)>
<!ELEMENT struct (member*)>
<!ELEMENT value ( i4 | int | boolean | string | dateTime.iso8601
                 | double | base64 | struct | array )>

<!ELEMENT param (value)>
<!ELEMENT params (param*)>

<!ELEMENT methodName (#PCDATA)>
<!ELEMENT methodCall (methodName, params)>

<!-- note that the content model for fault is underspecified here -->
<!ELEMENT fault (value)>
<!ELEMENT methodResponse (params|fault)>
A more verbose DTD, with more explanation and support for the nil element type, can be found online at http://www.ontosys.com/xml-rpc/xml-rpc.dtd.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 3: Client-Server Communication: XML-RPC in Java
Java was built from the ground up as a network-centric development environment. As a Java developer, XML-RPC offers you an opportunity to extend that foundation in a structured way. Adding XML-RPC to your toolkit makes it easier to integrate a Java application with an application built using another environment or simply to establish lightweight point-to-point communication between Java programs running on different computers. Although XML-RPC goes against the grain of much Java network programming (and even against some of the fundamental principles of object-oriented development), its alternative approach can be useful in many relatively common scenarios.
You already have a wide variety of Java-based XML and HTTP tools to choose from, but you can also take advantage of a prepackaged set of XML-RPC tools. Although understanding the foundations of XML-RPC is very useful for debugging and for establishing connections between systems in different environments, you can treat XML-RPC much like you do any other Java feature. There's some setup work to do, especially for XML-RPC servers, but most of this work is simple and needs to be done only once in the course of a program.
This chapter looks at how XML-RPC fits into Java's many network options. It demonstrates how to build a variety of different XML-RPC clients, servers, and handlers. Some of these examples take advantage of built-in functionality for setting up simple XML-RPC servers and handlers; others explore the possibilities opened up by handling more of the processing directly. The examples cover different styles of XML-RPC programming, from simple library function calls to more complex calls that manipulate information on the server.
Java is already an extremely network-aware environment, complete with its own mechanisms for remote communication and coordination of objects on multiple systems. Remote Method Invocation (RMI) and RMI's support for the broader world of CORBA-based systems provide built-in support for distributing applications across multiple systems. In many ways, Java is well ahead of its competitors, and its network support extends far beyond the simple request-response cycle of XML-RPC.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Why XML-RPC for Java?
Java is already an extremely network-aware environment, complete with its own mechanisms for remote communication and coordination of objects on multiple systems. Remote Method Invocation (RMI) and RMI's support for the broader world of CORBA-based systems provide built-in support for distributing applications across multiple systems. In many ways, Java is well ahead of its competitors, and its network support extends far beyond the simple request-response cycle of XML-RPC.
Despite Java's built-in network computing prowess, XML-RPC offers a few kinds of functionality that Java can't match. XML-RPC is far more lightweight than Java's built in RMI support, passing only parameters rather than objects. Java programs can use XML-RPC to connect directly to any other system supporting XML-RPC, rather than limiting connections to fellow RMI systems or having to use complex (and expensive) CORBA object request brokers.
As illustrated in Figure 3-1, XML-RPC can bring the direct connections RMI makes possible for strictly Java applications to applications that integrate multiple environmentsXML-RPC's use of HTTP as a transport substrate makes it relatively simple to integrate XML-RPC with the web-enabled applications that are already spreading across the computing landscape. At the same time, XML-RPC uses such a tiny subset of HTTP that Java applications can easily avoid the overhead of full-scale HTTP processing, working with a more minimal -- and more efficient -- driver that takes advantage of Java's built-in understanding of TCP/IP.
XML-RPC also offers you a shorter compilation and testing cycle. Unlike RMI, which requires recompilation of interfaces to register method signatures, XML-RPC allows the client to specify which method it wants to use and then looks for a handler. Because the reference is done by name, there aren't any stubs to manage or include, and changes can be made much more easily at runtime.
On the other hand, XML-RPC is definitely not appropriate in plenty of Java application situations. Much of the Enterprise JavaBeans (EJB) work already relies on RMI, and rewriting it to use XML-RPC would be a remarkable waste of time. Although a snippet of XML-RPC code might be useful as a simple bridge between an EJB-based application and code written for other environments, XML-RPC isn't designed explicitly to support the many demands of complex enterprise-scale design. Similarly, if you need to pass objects, rather than parameters, betweensystems, you should look into a more sophisticated set of tools than XML-RPC. XML-RPC lets you pass sets of parameters, not complex nested structures with associated method information, back and forth. As explained later in this chapter, XML-RPC's approach doesn't match cleanly with JavaBeans, either.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
The XML-RPC Java Library
Although you could use the wide variety of XML resources available in Java to create your own XML-RPC package, Hannes Walln枚fer has already built a set of classes that provide XML-RPC capabilities for both clients and servers, including a small XML-RPC server that lets you work without the overhead of a full-scale Web server. Most examples in this chapter rely on his package.
As of this writing, the XML-RPC library for Java in still in beta, at Version 1.0 beta 4. Although it is unlikely that there will be major changes to the API, you should check the index.html file and documentation that come with the library if you encounter problems.
The XML-RPC Library for Java web site is http://classic.helma.at/hannes/xmlrpc/, and additional resources (including a mailing list with archives) are also available there. The examples in the current chapter use the helma.xmlrpc library, which is available at that site.
In addition to core XML-RPC functionality, the helma.xmlrpc package includes:
  • Classes for quick XML-RPC client and server creation
  • A micro-web server useful for setting up XML-RPC on systems that don't already have a web server running or don't want to use the existing server
  • A sample of Java servlet integration
  • A standalone set of classes used for building lightweight XML-RPC applets
The components included in the XML-RPC library include client- and server-specific classes used for creating requests and responses, as well as a more generic core that controls how the library handles HTTP processing and XML parsing.
The helma.xmlrpc library is available for free download as a zip archive at http://classic.helma.at/hannes/xmlrpc/. You'll need an unzipping utility to open the archive, which contains documentation, examples, source code, and three Java archive (
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building XML-RPC Clients
Building XML-RPC clients with the helma.xmlrpc package is a relatively simple operation, involving the creation of an XmlRpcClient object, assigning parameters, and making a call to the XmlRpcClient's execute method. There are a number of exceptions that can be thrown, and there may be delays in getting a response, but for the most part, calling XML-RPC routines requires only a small amount of extra coding, much of which actually deals with exception handling.
The constructor and the execute( ) methods are the core of the XmlRpcClient class. The easiest way to handle them is in a try/catch structure, though you can encapsulate them in methods that throw the exceptions to a higher-level handler. The constructor may throw a MalformedURLException, a subclass of IOException; the execute( ) method may throw either IOException (when connections are refused, impossible, etc.) or XmlRpcException, which is issued when the XML-RPC server reports an error. The constructor accepts a String object representing a URL, a URL object, or the combination of a String for the hostname and an int for the port.
XmlRpcClient objects are reusable, though they only connect to the server originally specified when they were constructed. Applications that establish repeated connections to the same server may want to reuse the objects, but many applications just create the client, call a method, and disappear. In these cases, the constructor and execute( ) method may appear inside a single try/catch statement. When the constructor and execute( ) method appear together, the MalformedURLException may be treated as just another IOException, making it one fewer exception to catch.
The following example creates a client that can connect to port 8899 on the computer with the IP address 192.168.126.42. It sends a double (retrieved from user input through the args[] array) to a method identified as area.circleArea, expecting to get back the area of a circle whose radius is the double sent as the parameter. This code doesn't do anything with the result; it just sends the request and handles any exceptions that might be thrown.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Building XML-RPC Servers
Building XML-RPC servers is a bit more complex than building clients. In addition to building the core logic of your application, you need to publish your services to the XML-RPC library so it can manage requests. Your application may do this in the context of a servlet running within a larger Web server, or it may use the library's built-in WebServer class to create a minimal server handling only XML-RPC requests.
The simplest way to build an XML-RPC server relies on the WebServer class and uses the XmlRpcServer class's built-in ability to recognize Java classes and methods during the registration process. If you just need to publish methods whose parameters conform to the XML-RPC data types described earlier in this chapter, this is usually straightforward.
The helma.xmlrpc package includes a simple WebServer class that makes it easy to set up XML-RPC on systems that don't have a web server installed previously or to add an extra server listening on a nonstandard port. The WebServer class provides only the core of HTTP functionality used by XML-RPC, not the full set of functionality used to distribute web pages. This limitation should reduce the fears of network administrators who don't want to install internal web sites, while giving Java developers a small-footprint approach to adding XML-RPC to computers that aren't intended to be web servers.
Creating a new web server that uses the built-in WebServer class requires calling its constructor with a port number. For example, to create a web server that listens for XML-RPC requests on port 9876, you can call its constructor as follows:
WebServer server = new WebServer(9876);
If the WebServer can't start on the specified port, it throws a java.io.IOException. Depending on how you structure the program, you may want to enclose the constructor (and subsequent registrations) in a try/catch statement, or you may want the method managing the XML-RPC interface to pass the exception on to another handler.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Creating XML-RPC Handlers
Both WebServer and XmlRpcServer employ the same set of methods for registering and unregistering classes whose methods can be used through XML-RPC. Java classes whose methods accept the standard data types (described earlier in this chapter) can use the WebServer and XmlRpcServer classes' built-in logic for mapping XML-RPC calls to Java methods; other classes can be extended with a single execute( ) method for mapping XML-RPC requests to Java methods. In both cases, the addHandler( ) and removeHandler( ) methods are used the same way to add and remove classes that can handle XML-RPC methods.
If the methods you want to use for processing XML-RPC requests are written so that they only accept and return the data types described, you can use the automatic registration process. The following code sample demonstrates these methods using a simple testing procedure that accepts two strings and returns a new string that concatenates the strings in the reverse order of how they were received:
public class testHandler {

        public String nameTester(String first, String last) {
                return "Reversed: " + last + ", " + first;
        }
}
Making the nameTester( ) method available as an XML-RPC procedure requires two steps. First, set up a web server to handle the HTTP transactions. Second, register this method with that server to make it available via XML-RPC. Once the server object has been created, the testHandler can be registered with the server using the addHandler( ) method. The server then accepts and processes requests for the method:
WebServer server = new WebServer(9876);
server.addHandler("test", new testHandler(  ));
The server examines the testHandler class and extracts its method signatures for mapping to XML-RPC requests. XML-RPC clients may now send requests for the test.nameTester method, sending two strings as parameters. They'll receive a single string back, which begins with the text "Reversed:" and then concatenates the strings in reverse order.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Three Practical Examples
Although XML-RPC itself is very simple, it can be applied to a number of programming styles. The approach that most directly fits "remote procedure calls" is one that calls procedures across a network, as shown in the library function example in the next section. Procedure calls can also be used easily for client-to-server reporting, shown in an example that logs error reports from clients. Finally, just as Java itself uses get and set methods to manipulate the properties of objects, XML-RPC can extend that functionality to expose those methods to other systems on the network.
This example creates a simple Java library that performs mathematical calculations without any side effects on the server. The calculations performed -- determining the areas of circles and squares -- aren't very complex, but this same approach could be used for much more intensive algorithms. Although the average applet is certainly capable of calculating the area of a square on its own, many fields of computing rely on mathematical tools that demand extraordinary amounts of processing power.
As shown in Example 3-3, the AreaHandler class has two methods and no properties. The first method takes two arguments, length and width, and returns the area of a rectangle; the second method takes a single argument, radius, and returns the area of a circle.
Example 3-3. Library function implemented as XML-RPC handler
public class AreaHandler {

        public Double rectArea(double length, double width) {
        return new Double(length*width);
    }

    public Double circleArea(double radius) {
        double value=(radius*radius*Math.PI);
        return new Double (value);
    }

}
This code is run as an XML-RPC client on the server, with a simple client to pass it values. The code for the server builds on the generic code created in the previous section, using the helma.xmlrpc library's built-in WebServer
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Moving Toward Cross-Platform Peer-to-Peer
The three preceding examples have moved from clients using servers as remote processors to clients reporting information to servers to clients actually controlling servers. XML-RPC's basic client-server foundation makes exchanging information in a wide variety of different ways possible, and its variable structures are flexible enough that single methods can have different behaviors, depending on the kinds of parameters they are sent.
The flexibility you need to move from client-server XML-RPC to a more peer-to-peer model is already there, thanks to arrays and structs. Clients can send any quantity of information that the application can then pick through, and servers can return any quantity of information for the client. Some clients may be capable of sending more information than others; servers can send extra information to clients, understanding that only some of their targets will use the entire set of information. There's no need for clients to play a purely client role or for servers to play purely server roles. Every program can be both a client and a server, if and when that seems appropriate.
As long as that flexibility is sufficient for your needs, the helma.xmlrpc package can provide you with a foundation for communication with non-Java systems with which you can define the roles of client and server as you find appropriate.
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Chapter 4: XML-RPC and Perl
XML-RPC and the Perl scripting language are a particularly powerful combination for creating flexible web services rapidly. Perl has long been the language of choice to obtain and manipulate data for the Web, and it is moving into the growing field of web services. One of Perl's guiding philosophies is "Easy things should be easy, and hard things should be possible." The Perl module for XML-RPC, Frontier::RPC, embodies this.
To show how easy Perl's XML-RPC library, Frontier::RPC, makes remote procedure calls, consider the following code snippet:
use Frontier::Client;
my $client = Frontier::Client->new 
           ( url => "http://example.com:1080");
print "helloWorld('Bob') returned: ",
           $client->call('helloWorld', 'Bob'), "\n";
Assume that on a machine called example.com, there is an XML-RPC server running on port 1080 that has implemented a procedure named helloWorld( ). Given these assumptions, these three lines of Perl code are all that's needed to make an XML-RPC call. Although this chapter explores the details of using this library more thoroughly, many XML-RPC Perl clients aren't any more complicated than this example.
This chapter begins with a discussion of the history, requirements, and architecture of Perl's XML-RPC library, Frontier::RPC. Then it covers how to create XML-RPC clients and servers using Perl, including instructions for running an XML-RPC server from a web server.
As of this writing, there's only one XML-RPC implementation on the Comprehensive Perl Archive Network (CPAN) (http://www.cpan.org). It's named Frontier::RPC and consists of several Frontier modules, a number of examples, and Apache::XMLRPC , which embeds an XML-RPC server in the Apache web server using mod_perl.
Why is this implementation tagged "Frontier" and not "XMLRPC"? Because way back in 1998, when Ken MacLeod was first putting Frontier::RPC together, the XML-RPC specification didn't exist. The protocol was merely "RPC over HTTP via XML," the one used at Dave Winer's UserLand site, implemented in the Frontier language. Ken's work was, in fact, the first third-party implementation of the protocol to be released. Note that this chapter is based on Version 0.07 of
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Perl's Implementation of XML-RPC
As of this writing, there's only one XML-RPC implementation on the Comprehensive Perl Archive Network (CPAN) (http://www.cpan.org). It's named Frontier::RPC and consists of several Frontier modules, a number of examples, and Apache::XMLRPC , which embeds an XML-RPC server in the Apache web server using mod_perl.
Why is this implementation tagged "Frontier" and not "XMLRPC"? Because way back in 1998, when Ken MacLeod was first putting Frontier::RPC together, the XML-RPC specification didn't exist. The protocol was merely "RPC over HTTP via XML," the one used at Dave Winer's UserLand site, implemented in the Frontier language. Ken's work was, in fact, the first third-party implementation of the protocol to be released. Note that this chapter is based on Version 0.07 of Frontier::RPC. There are significant changes from the previous version, including the introduction of a new module, Responder, so be sure to upgrade if you have an earlier version.
Frontier::RPC uses other modules for much of its work: Data::Dumper, MIME::Base64, MD5, HTML::Parser, URI, various Net:: modules from the libnet distribution, various modules from the libwww-perl (LWP) suite, and XML::Parser. These are all available from CPAN.
All but one of these Perl modules should install without difficulty. However, the latest version of the XML::Parser module (a front end to the expat XML parser, written in C) does not include the expat C source. You must download this source from http://sourceforge.net/projects/expat. Fortunately, expat compiles cleanly on most versions of Unix, and Windows users of ActiveState Perl will find that XML::Parser is already installed.
A Perl script that wants to be an XML-RPC client uses the Frontier::Client module. An XML-RPC client script creates a Frontier::Client object and makes remote procedure calls through methods of that object.
A standalone Perl script that wants to be an XML-RPC server uses the Frontier::Daemon module. ("daemon" is the traditional Unix term for a long-running server process.) The script creates a long-lived
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
Data Types
The interesting part of an XML-RPC call is how language-specific data types are turned into XML-RPC tagged data. Each XML-RPC parameter must have one of the data types documented in the XML-RPC specification and introduced in Chapter 2. For example, here's how the floating-point value 2.718 is encoded as a parameter:
<param><value><double>2.718</double></value></param>
Table 4-1 shows the correspondence (or lack thereof) between XML-RPC data types and Perl data types.
Table 4-1: Data types: XML-RPC versus Perl
XML-RPC data type(XML element)
Perl built-in data type
Frontier::RPC2 module
<int> (or <i4>)
scalar
Frontier::RPC2::Integer 
<double>
scalar
Frontier::RPC2::Double 
<string>
scalar
Frontier::RPC2::String 
<boolean>
scalar
Frontier::RPC2::Boolean
<dateTime.iso8601>
scalar
Frontier::RPC2::DateTime::ISO8601
<base64>
scalar
Frontier::RPC2::Base64
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
XML-RPC Clients
Now that you understand how XML-RPC data types work in Perl, we can get to actually creating a Perl XML-RPC client -- a script that makes calls to an XML-RPC server and gets responses back from it. We'll start with an overview of the method-call process and then describe how to create a client that does the job.
To call one or more XML-RPC methods on a particular server, a Perl script creates a Frontier::Client object. This object represents a connection to that server. The script can then invoke the Client object's call( ) method as many times as desired to make XML-RPC calls. The call( ) method:
  • Accepts a user-specified string as the method name
  • Converts each user-specified argument from Perl format (scalar or object) to XML format
  • Packages Perl data in an XML <methodCall> message and sends it to the server
  • Decodes the <methodResponse> message returned by the XML-RPC server into Perl data
Here are the steps involved in making an XML-RPC call:
  1. Create a Frontier::Client object.
  2. Call the method, passing arguments.
  3. Get the response to the call.

Section 4.3.2.1: Creating the client object

The only Perl module you need to import explicitly is the one that defines the Frontier::Client package:
use Frontier::Client;
Create an object in the Frontier::Client package in the regular way, using the package's new( ) method. You must specify a url argument, which sets the web address (URL) of the XML-RPC server host. For example:
Additional content appearing in this section has been removed.
Purchase this book now or read it online at Safari to get the whole thing!
XML-RPC Servers
Now we can turn to the operation and construction of a Perl XML-RPC server -- a script that receives calls from an XML-RPC client and sends responses back to it. After presenting an overview of server operation, we describe how to create a server.
To set up a server to handle incoming XML-RPC calls, a Perl script creates a Frontier::Daemon object. This object implements a server process that listens for XML-RPC calls on a particular port. The server dispatches each call to a corresponding Perl subroutine, and then it sends the subroutine's return value back to the client as the response to the XML-RPC call.
The Frontier::Daemon object gets its knowledge of HTTP communications by being a specialization of the standard Perl HTTP::Daemon object. The Daemon object:
  • Uses an XML parser to interpret the incoming XML-RPC <methodCall> message.
  • Determines the method name (a string).
  • Converts each parameter from XML format to a Perl scalar value or object.
  • Invokes a Perl subroutine that corresponds to the specified method name. The Daemon passes