Chapter 11. XML-RPC
XML-RPC is actually a specific flavor of RPC, which stands for remote procedure calls. If you are new to programming, or have worked with the Java language only a short time, remote procedure calls may be new for you; if you've been around the block in the development world, you may be a bit rusty, as RPC has fallen out of vogue in recent years. In this chapter I look at why those three little letters in front of RPC are revolutionizing what was becoming a computing dinosaur, and how to use XML-RPC from the world of Java. I also spend some time at the end of this chapter looking at real-world applications of XML-RPC, trying to shed some light not only on how to use this technology, but when to use it.
If you are part of the tidal wave of object-oriented development that has come along in the past three to five years, even hearing the word "procedure" may send shivers down your back. Procedural languages such as PL/SQL and ANSI C are not popular for a long list of very good reasons. You have probably been scolded for calling a Java method a function or procedure before, and almost certainly know better than to write "spaghetti code," code that has method after method chained together in a long line. RPC has fallen by the wayside much as these languages and techniques have. There are new, object-oriented ways of achieving the same results, often with better design and performance. Surprisingly, though, the rise of XML has brought with it the rise and prominence of APIs specifically built for XML-RPC, and a gradual trend toward using XML-RPC in specific situations despite the connotations it carries.
Before trying to use these APIs, it is worth spending some time looking at what RPC is and how it compares to similar Java technologies, most notably remote method invocation (RMI). If you do choose to use XML-RPC in your applications (and you almost surely will want to at some point), be assured that you will probably have to justify your choice to other developers, particularly those who may have just read books on EJB or RMI. Certainly there are places for all these technologies. Understanding the proper application of each is critical to your success not only as a developer, but as a team member and mentor. Keeping in mind these reasons for understanding the concepts behind these remote methodologies, let's take a look at the two most popular ways to operate upon objects across a network: RPC and RMI.
11.1. RPC Versus RMI
If you haven't been under a rock for the last several years, you should be aware that EJB and RMI have taken the Java world by storm. The entire EJB (Enterprise JavaBeans) specification is founded upon RMI principles, and you will be hard-pressed to write a three-tier application without using RMI, even if indirectly. In other words, if you don't know how to use RMI yet, you may want to pick up Java Enterprise in a Nutshell by David Flanagan, Jim Farley, William Crawford, and Kris Magnusson, or Java Distributed Computing by Jim Farley (both published by O'Reilly) and spend some time looking into this useful technology.
11.1.1. What Is RMI?
In short, RMI is remote method invocation. RMI allows a program to invoke methods on an object when the object is not located on the same machine as the program. This is at the heart of distributed computing in the Java world, and is the backbone of EJB as well as many enterprise application implementations. Without getting into too much detail, RMI uses client stubs to describe the methods a remote object has available for invocation. The client acts upon these stubs (which are Java interfaces), and RMI handles the "magic" of translating requests to a stub into a network call. This call invokes the method on the machine with the actual object, and then streams the result back across the network. Finally, the stub returns this result to the client that made the original method call, and the client moves on. The main idea is that the client doesn't typically worry about the RMI and network details; it uses the stub as if it were the actual object with implemented methods. RMI (using JRMP, Java's remote protocol) makes all this network communication happen behind the scenes, allowing the client to deal with a generic exception (java.rmi.RemoteException) and spend more time handling business rules and application logic. RMI can also use different protocols such as Internet Inter-ORB Protocol (IIOP), allowing communication between Java and CORBA objects, often in different languages such as C or C++.
RMI carries a cost, though. First, using RMI is resource-intensive. JRMP provides very poor performance, and writing a remote protocol to replace it is not a simple task. As clients issue RMI calls, sockets must be opened and maintained, and the number of sockets can affect system performance, particularly when the system is accessible via a network (which then requires more sockets to be opened for HTTP access). RMI also requires a server or provider to bind objects to. Until an object is bound to a name on one of these providers, the object is not accessible to other programs. This requires using an RMI registry, a Lightweight Directory Access Protocol (LDAP) directory server, or a variety of other Java Naming and Directory Interface (JNDI) services. Finally, RMI can involve a lot of coding, even with all the helpful RMI server classes you get with the JDK; a remote interface describing the methods available to be invoked must be coded (as well as quite a few other interfaces if you are using EJB). This also means that adding an additional method to the server class results in a change to the interface and recompilation of the client stubs, something that is often not desirable and sometimes not possible.
11.1.2. What Is RPC?
RPC is remote procedure calls. Where RMI lets you interoperate directly with a Java object, RPC is built in more of a dispatch fashion. Instead of dealing with objects, RPC lets you use standalone methods across a network. Although this limits interactivity, it does make for a slightly simpler interface to the client. You can think of RPC as a way to use "services" on remote machines, while RMI allows you to use "servers" on remote machines. The subtle difference is that RMI typically is driven entirely by the client, with events occurring when methods are invoked remotely. RPC is often built more as a class or set of classes that works to perform tasks with or without client intervention; however, at times these classes service requests from clients, and execute "mini" tasks for the clients. I will show you some examples shortly to clarify these definitions.
RPC, while not as interactive an environment as RMI, does offer some significant advantages. RPC allows disparate systems to work together. While RMI allows the use of IIOP for connecting Java to CORBA servers and clients, RPC allows literally any type of application intercommunication, because the transport protocol can be HTTP. Since virtually every language in use today has some means of communicating via HTTP, RPC is very attractive for programs that must connect to legacy systems. RPC is also typically more lightweight than RMI (particularly when using XML as the encoding, which I'll cover next); while RMI often has to load entire Java classes over the network (such as code for applets and custom helper classes for EJB), RPC only has to pass across the request parameters and the resulting response, generally encoded as textual data. RPC also fits very nicely into the API model, allowing systems that are not part of your specific application to still access information from your application. This means that changes to your server do not have to result in changes to other clients' application code; with pure textual data transfer and requests, additional methods can be added without client recompilation, and minor changes are sufficient to use these new methods.
The problem with RPC has traditionally been the encoding of data in transfer; imagine trying to represent a Java Hashtable or Vector in a very lightweight way through textual formats. When you consider that these structures can, in turn, hold other Java object types, the data representation quickly becomes tricky to write; it also has to remain a format that is usable by all the disparate programming languages, or the advantages of RPC are lessened. Until recently, an inverse relationship had been developing between the quality and usability of the encoding and its simplicity; in other words, the easier it became to represent complex objects, the more difficult it became to use the encoding in multiple programming languages without proprietary extensions and code. Elaborate textual representations of data were not standardized and required completely new implementations in every language to be usable. You can see where this discussion is leading.
The greatest obstacle to using RPC has traditionally been its encoding. But then XML came along with a solution. XML provided not only a very simple, textual representation of data, but a standard for the structure of that data. Concerns about proprietary solutions became moot when the W3C released the XML 1.0 specification, reassuring RPC coders that XML was not going anywhere. In addition, SAX provided a lightweight, standard way to access XML, making it much easier to implement RPC libraries. This left only transmission over HTTP (something people have been doing for many years) and the specific encoding and decoding APIs for XML-RPC implementers to write. After a few beta implementations of XML-RPC libraries, it became clear that XML was also a very fast and lightweight encoding, resulting in better performance for XML-RPC libraries than expected. XML-RPC is now a viable and stable solution for remote procedure calls.
For you, the Java developer, XML-RPC provides a way to handle simple creation of "hooks" into your application and its services, for your own use as well as for other application clients in different divisions or even different companies. It also uncouples these APIs from Java if clients are unable to use the Java language directly. Finally, XML-RPC removes RMI from the technologies that have to be learned to use distributed services (at least initially). I'll spend this chapter looking at how to implement an XML-RPC server and client; I'll show an example of how a server can operate independently of clients, yet still provide XML-RPC accessible interfaces to interoperate with and query its data. Although I'm not going to look at RMI in depth in this chapter, I continually compare the XML-RPC solution to RMI, pointing out why XML-RPC is a better solution for some specific types of tasks.
Copyright © 2002 O'Reilly & Associates. All rights reserved.