Write and Configure JAX-RPC Handlers
Avoid the limitations of an interceptor model to provide services. See how to write and configure handler components for generic and specific implementations
by Kevin Jones
Posted January 7, 2004
Developers can use Java API for XML-based Remote Procedure Calls (JAX-RPC) to map Web service operations onto Java method calls. The concept is fairly straightforward. A Web service consists of one or more operations, and each operation typically contains an input message and an output message. Each operation typically maps to a method on a Java interface, with the input message mapping to method parameters and the output message mapping to the method return type.
This scenario is very similar to many RPC APIs and has similar advantages and disadvantages to those APIs. One obvious issue is that of providing service. If each operation requires the same set of services, such as security or logging, how do you provide those services?
One solution is to have each method call some helper class and have that class provide the services. However, this solution is far from ideal. In J2EE the typical way of providing layered services is by an interceptor model. For example, in Web applications there are filters, while in EJB the container provides an interposer that is configured declaratively to provide a set of services for an end point.
JAX-RPC implementations are typically performed as either Web application-based or Enterprise JavaBeans (EJB)-based solutions; however, using filters or interposers in these cases is not the best solution. Filters are there to file raw HTTP messages, so any filter would need to intercept the HTTP request and then read in and process the XML before passing the request on. EJB does, but as yet there is no direct support in EJB for providing interposition of SOAP messages.
To overcome these limitations the JAX-RPC specification defines something called handlers. A handler is a component that can be associated with an entire Web service or with a particular Web service interface. A Web service can have a number of ports—a port is analogous to a Java interface—and a handler can be associated with just an interface. Handlers can be very generic, such as logging or caching handlers, or very specific, such as handlers that want to process an application-specific SOAP header. Here we will look at how to write generic handlers and how to configure them for a JAX-RPC client and a JAX-RPC server.
Writing Handlers
A handler is a Java class that implements the javax.xml.rpc.handler.Handler interface. This interface has six methods, and you usually don't need to implement all of them. To help developers the JAX-RPC API also contains a GenericHandler adapter class that implements all of the methods of Handler apart from getHeaders (the details are beyond the scope of this article). The easiest way to write a handler is to extend GenericHandler:
public class LoggingHandler
extends GenericHandler
{
// must implement this
public QName[] getHeaders(){
return new QName[0];
}
}
You then have to decide what the handler will do. Handlers will be called to handle the request message and the response message (which could be a normal response or a fault response). The example we will write here needs to process both the SOAP request and the SOAP response, which means that the handler needs to override two methods—handleRequest and handleResponse:
public class LoggingHandler
extends GenericHandler
{
handleRequest(
MessageContext ctx)
{
logMessage(
messageContext, System.out);
}
handleResponse(
MessageContext ctx)
{
logMessage(
messageContext, System.out);
}
}
Both of these methods are passed a reference to a MessageContext, which is really a SOAPMessageContext. The SOAPMessageContext is used for several things. A reference to the context is passed to each handler when the handler executes and can be used to pass data from one handler instance to another or from one handler method to another. The SOAPMessageContext also gives the handler access to the actual SOAPMessage. Both methods log the SOAP message (to System.out in this case) by calling logMessage:
private void logMessage(
MessageContext messageContext,
OutputStream out)
{
SOAPMessageContext smc =
(SOAPMessageContext)
messageContext;
SOAPMessage msg =
smc.getMessage();
try
{
msg.writeTo(out);
out.write(
"\r\n".getBytes());
}
catch (Exception e)
{
throw new
JAXRPCException(e);
}
}
This method simply retrieves the SOAPMessage from the context and displays that message.
That's it as far as writing this simple handler is concerned. The next issue is how does the handler get called? To do this the handler has to be configured.
Configuring Handlers
Configuration will be JAX-RPC-implementation dependant. Here we will see how the JAX-RPC reference implementation (RI) works, which is part of the Java Web Services Developers Pack (JWSDP) that is available from Sun.
In the RI handler configuration is carried out in a file called config.xml-which is the usual name, though it can be named something else. This file contains the configuration information for the Web service. If you are building a JAX-RPC service starting from the Java interface and implementation, the file specifies the name of the service and the name of the Java class and interface (see Listing 1). You add the information about the handler to this file, either to the service element or to the interface element—we will use service.
Handlers are configured as part of a handler chain, and a chain will be configured for the server or the client and will contain one or more handlers. For our logging handler the chain looks like this:
<handlerChains>
<chain runAt="server" >
<handler className=
"com.develop.ejws.jaxrpc.
LoggingHandler"/>
</chain>
</handlerChains>
You can see the entire configuration in Listing 2.
The handler will be called for each request and each response into this service and will display the soap messages received and returned by the service. This handler is independent of the service, so it can be used anywhere.
In a subsequent article, I'll discuss how to code and configure general-purpose handlers that process SOAP headers in specific ways for specific applications.
About the Author
Kevin Jones is a developer who has spent the last four years researching and teaching Java programming and most recently investigating HTTP and XML. Kevin lives in the U.K. and works for Developmentor, a training company based in the United States and Europe that specializes in technical training on Java and Microsoft platforms. Contact Kevin at .
|