We 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, all 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, then, highlights some of the common issues that arise in using XML-RPC.
After working through this chapter, you may have been surprised that
we didn’t write any SAX, DOM, or JDOM code. In fact, we 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 our client sent to and from the server. 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 10.10.
Example 10-10. XML-RPC Request After Encoding
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 10.11.
Example 10-11. XML-RPC Response After Encoding
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>
All this communication happens without you having to worry about the details.
In our examples, we 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 works fine in that it forces clients
to use the code shown above to get an instance, it can also cause
confusion when trying to use 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 would be 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 we can make a small
change to this code if we 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 was being
instantiated through a constructor with the new
keyword, and preserves any information shared across the singleton
class. You will find that 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.
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 & Associates]). 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, this is not always the best idea.
If you have a machine that must serve other HTTP requests for Java
tasks, then certainly 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 would be 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.
Our 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, to add a
servlet engine and accept 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
above), it is rarely a good idea to use a servlet for the XML-RPC
server. The provided WebServer
class is very
small, very light, and designed specifically for handling XML-RPC
requests over HTTP. A servlet engine is designed for accepting 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, it would be wise to stick with the lightweight
XML-RPC server designed for the purpose you need.
3.135.248.37