11.4. The Real World
I'll conclude this chapter with a short look at some important details of using XML-RPC in the real world. This continues the focus on allowing you to use XML not because it is the newest and neatest technology, but because it is the best for solving certain situations. All of the knowledge within this book, the XML specifications, and other XML books will not make your application operate as well as it could if you do not know when and how to use XML and XML-RPC correctly! This section highlights some of the common issues that arise in using XML-RPC.
11.4.1. Where's the XML in XML-RPC?
After working through this chapter, you may have been surprised that you didn't have to write any SAX, DOM, or JDOM code. In fact, you used very little XML directly at all. This is because the XML-RPC libraries were responsible for the encoding and decoding of the requests that your clients sent to and from the servers. While this may seem a little bit of a letdown, as you didn't write any code that directly manipulates XML, you are definitely using XML technology. The simple request to the sayHello( ) method was actually translated to an HTTP call that looks like Example 11-10.
Example 11-10. XML for XML-RPC request
POST /RPC2 HTTP/1.1 User-Agent: Tomcat Web Server/3.1 Beta (Sun Solaris 2.6) Host: newInstance.com Content-Type: text/xml Content-length: 234 <?xml version="1.0"?> <methodCall> <methodName>hello.sayHello</methodName> <params> <param> <value><string>Brett</string></value> </param> </params> </methodCall>
The XML-RPC libraries on the server receive this and decode it, matching it with a handler method (if one is available that matches). The requested Java method is then invoked, and the server encodes the result back into XML, as shown in Example 11-11.
Example 11-11. XML underlying an XML-RPC response
HTTP/1.1 200 OK Connection: close Content-Type: text/xml Content-Length: 149 Date: Mon, 11 Apr 2000 03:32:19 CST Server: Tomcat Web Server/3.1 Beta-Sun Solaris 2.6 <?xml version="1.0"?> <methodResponse> <params> <param> <value><string>Hello Brett</string></value> </param> </params> </methodResponse>
This communication all happens without you having to worry about the details.
11.4.2. Shared Instances
In the examples, I looked at using static data objects to share data across multiple instances of the same class. However, there are times when an instance itself is shared. This may not be because of an XML-RPC need, but because of a need to use the class differently on the server. For example, the singleton design pattern in Java mandates that only one instance of a class ever be created, and that instance is shared across all applications. This is usually accomplished by using a static method called getInstance( ) instead of constructing the object:
Scheduler scheduler; // Get the single instance, which is managed in the Scheduler class scheduler = Scheduler.getInstance( ); // Add an event for right now scheduler.addEvent("Picnic", new Date( ));
To ensure that no classes directly instantiate the Scheduler class, the constructor is usually made private or protected. While this forces clients to use this code to get an instance, it can also cause confusion when using the class as an XML-RPC handler. Remember that registering a handler has always been accomplished with the instantiation of the handler class. However, the WebServer class requires only a valid instance as a parameter, not necessarily a new instance. For example, the following code is a perfectly acceptable way to add a handler:
WebServer server = new WebServer(8585); // Create a handler class HelloHandler hello = new HelloHandler( ); server.addHandler("hello", hello);
The server class does not distinguish between these methodologies, as long as the handler class is instantiated when it gets passed into the addHandler( ) method. So you can make a small change to this code if you want to add an instance of the singleton Scheduler class described previously:
WebServer server = new WebServer(8585); // Pass in the singleton instance server.addHandler("scheduler", Scheduler.getInstance( ));
This passes in the shared instance just as if the class were being instantiated through a constructor with the new keyword, and preserves any information shared across the singleton class. Many classes used in services such as XML-RPC are built as singletons to avoid the use of static data variables, as a shared instance allows the data to be stored in member variables; the single instance then operates upon those member variables for all client requests.
11.4.3. To Servlet or Not To Servlet
The use of a servlet as an XML-RPC server has become a popular option recently. For more details on servlets, see Jason Hunter's Java Servlet Programming (O'Reilly). In fact, the XML-RPC Java classes that you downloaded include a servlet with the distribution. It is both legal and common to use a servlet in this way, having the servlet do nothing but field XML-RPC requests. However, it is not always the best idea.
If you have a machine that must serve other HTTP requests for Java tasks, then a servlet engine is a good choice for handling the details of these requests. In this case, running a servlet as an XML-RPC server is a good idea. However, one of the advantages of XML-RPC is it allows handler classes with complex, process-intensive tasks to be separated from other application code. The Scheduler class could be placed on a server with classes that performed complex indexing, algorithmic modeling, and perhaps graphical transformations. All of these functions are very expensive for application clients to perform. However, adding a servlet engine and accepting application requests for other tasks as well as the XML-RPC handling greatly reduces the processing power available to these handler classes. In this case, the only requests that should be coming to the server are for these handler classes.
In the case where only XML-RPC requests are accepted (as indicated previously), it is rarely a good idea to use a servlet for the XML-RPC server. The provided WebServer class is small, light, and designed specifically for handling XML-RPC requests over HTTP. A servlet engine is designed to accept any HTTP request, and is not tuned as well for XML-RPC requests in particular. Over time, you will begin to see performance degradation in the servlet engine as compared to the WebServer class. Unless you have a compelling reason to use a servlet for other non-XML-RPC tasks, stick with the lightweight XML-RPC server designed for the purpose you need.
Copyright © 2002 O'Reilly & Associates. All rights reserved.