SOAP Message Handlers

As depicted earlier in Figure 19-2, you may associate a chain of SOAP message handlers with a web service operation. SOAP message handlers are a part of the JAX-RPC standard. A SOAP message handler can be tied to a web service endpoint either on the client side or on the server side. It is used simply to provide additional logic for handling the SOAP messages. Each SOAP handler in the chain intercepts the request and response SOAP messages, and processes the SOAP message before passing it on to the next member in the chain. Each message handler has access to the SOAP message and can transform the incoming request or outgoing response before passing it on to the next SOAP handler. For this reason, SOAP handlers are best suited to implement a number of useful add-on features such as logging, encryption and decryption, and caching.

The rest of this section describes how to write and deploy SOAP message handlers, and how to associate a chain of SOAP handlers with operations of WebLogic web services. If you need to create message handlers that process SOAP messages on the client side, you should refer to the JAX-RPC specification for more information.

19.7.1 Life Cycle of a SOAP Handler

Every SOAP handler implements the javax.xml.rpc.handler.Handler interface. Example 19-13 describes the methods exposed by the Handler interface.

Example 19-13. The javax.xml.rpc.handler.Handler interface

package javax.xml.rpc.handler; public interface Handler { public boolean handleRequest(MessageContext ctx); public boolean handleResponse(MessageContext ctx); public boolean handleFault(MessageContext ctx); public void init(HandlerInfo hi); public void destory( ); public QName [] getHeaders( ); }

WebLogic invokes the init( ) method to create an instance of the Handler object, and invokes the destroy( ) method when it determines that the SOAP handler is no longer needed. These methods give you the opportunity to acquire and release any resources needed by the Handler object. The init( ) method is passed a HandlerInfo object, which lets you access any information about the SOAP handler in particular, any initialization parameters configured in the web-services.xml descriptor file. In fact, you should invoke the HandlerInfo.getHandlerConfig( ) method to obtain a Map object that holds a list of name-value pairs, one for each of the initialization parameters. These parameters are quite useful for several things for instance, to enable debugging, or perhaps to specify the name of the web service with which the SOAP handler is going to be associated (there is no other way of accessing this information).

The handleRequest( ) method is invoked to intercept incoming SOAP requests before they are processed by the backend component, and the handleResponse( ) method is invoked to intercept outgoing SOAP responses before they are delivered back to the client. If a single SOAP handler implements both the handleRequest( ) and handleResponse( ) methods, it intercepts both incoming and outgoing SOAP messages. The handleFault( ) method is invoked when WebLogic needs to process any SOAP faults generated by the handleRequest( ) or handleResponse( ) methods, or even by the backend component. These methods also have access to a MessageContext object that models the message context in which the SOAP handler has been invoked. Typically, you would use the SOAPMessageContext subinterface to access or update the contents of the SOAP message. Remember, a SOAP handler is free to update the contents of the incoming SOAP request or the outgoing SOAP response before it forwards the message to the next SOAP handler in the chain.

Once the handleRequest( ) method has processed the incoming SOAP request, it can determine how the SOAP message is subsequently handled in the following ways:

In the same way, once the handleResponse( ) method has processed the outgoing SOAP response, it can determine how the SOAP message is subsequently handled in the following ways:

Remember, the handleFault( ) method is used to handle any SOAP faults generated during the processing of the SOAP message request/response. The handleFault( ) methods can be invoked in a chain: if the handleFault( ) method on a Handler object returns true, the handleFault( ) method of the next handler in the chain is invoked. Otherwise, the rest of the chain is skipped.

WebLogic also provides a convenient abstract base class that lets you easily create your own handlers: weblogic.webservices.GenericHandler. Example 19-14 shows how to construct a simple handler in this way.

Example 19-14. Using the GenericHandler interface

public class MyHandler extends GenericHandler { public boolean handleResponse(MessageContext ctx) { SOAPMessageContext sMsgCtx = (SOAPMessageContext) ctx; SOAPMessage msg = sMsgCtx.getMessage( ); SOAPPart sp = msg.getSOAPPart( ); try { SOAPEnvelope se = sp.getEnvelope( ); SOAPHeader sh = se.getHeader( ); sh.addChildElement("TheStorkBroughtMe"); } catch (SOAPException e) { e.printStackTrace( ); } return true; } }

Note how the handleResponse( ) method uses the SOAPMessage class. This class is part of the SOAP with Attachments API for Java 1.1 (SAAJ) specification, and gives you access to all parts of the SOAP message. In this case, we used it simply to add a child element to the SOAP header of the response.

19.7.2 Configuring a Handler Chain

A handler chain represents an ordered group of SOAP message handlers. Any SOAP handler that needs to participate in a web service must be defined in the web-services.xml descriptor file. In fact, the descriptor file also lets you configure the sequence in which the SOAP handlers are invoked. The following excerpt from the web-services.xml descriptor shows how to declare a chain of SOAP message handlers:

Notice how we've defined an initialization parameter for the first handler in the chain. The order in which the handlers are defined is very important because it determines the sequence in which the handlers are invoked; that order is detailed here:

  1. The handleRequest( ) methods of all SOAP handlers in the chain are invoked in the order in which they're defined. In case of the preceding SOAP handler chain, the handlers will be invoked in the following sequence:

    H1.handleRequest( ) H2.handleRequest( ) H3.handleRequest( )

  2. Once the handleRequest( ) method of the last Handler object in the chain has completed, WebLogic then invokes the backend component that implements the web service. This occurs only if a backend component has been configured for the web service operation.
  3. When the backend component has finished processing, the handleResponse( ) method of all SOAP handlers in the chain are invoked, this time in the reverse order in which they're defined. In case of the preceding SOAP handlers, the response chain will be invoked in the following order:

    H3.handleResponse( ) H2.handleResponse( ) H1.handleResponse( )

  4. Once the handleResponse( ) method of the first Handler object in the chain has completed, the final SOAP message then is sent back to the client.

19.7.3 Creating and Registering SOAP Handlers

A SOAP message handler can either directly implement the Handler interface or can extend the abstract class GenericHandler provided by WebLogic. This class offers a simple and sensible implementation of the Handler interface and maintains a reference to the HandlerInfo object passed during the initialization of the Handler object. The following example shows how a SOAP message handler can access the SOAP message and its headers:

public class MyHandler extends weblogic.webservice.GenericHandler { public boolean handleRequest(MessageContext ctx) { System.err.println("In MyHandler.handleRequest( )"); // type cast MessageContext to access the SOAP message SOAPMessageContext sMsgCtx = (SOAPMessageContext) ctx; SOAPMessage msg = sMsgCtx.getMessage( ); SOAPPart sp = msg.getSOAPPart( ); SOAPEnvelope se = sp.getEnvelope( ); SOAPHeader sh = se.getHeader( ); // ... return true; } public boolean handleResponse(MessageContext ctx) { System.err.println("In MyHandler.handleResponse( )"); return true; } }

Once you create the SOAP message handler, you must modify the web-services.xml descriptor file in order to register the handler. In WebLogic 8.1, you simply need to modify the servicegen Ant task as follows:

handlers="com.oreilly.wlguide.webservices.handler.MyHandler"/>

The handlers attribute can take a comma-separated list of fully qualified class names. When you update the servicegen task in this way, every operation will be associated with the handler chain. If you want to be more selective, you have to edit the web-services.xml by hand. Likewise, if you are using WebLogic 7.0, you must edit the web-services.xml descriptor manually, as WebLogic 7.0's servicegen Ant task doesn't support handler chains. In these cases, you will need to edit the descriptor file to look something like this:

Only after you've registered the handler chain can you bind it to a web service operation. For this, you need to modify the particular operation element in the web-services.xml descriptor file to which the handler chain will be linked. Here you can see how the handler-chain attribute allows you to associate the handler chain myChain with the makeUpper operation defined earlier:

handler-chain="myChain">

Once you've deployed the web service with these changes to the descriptor file, any SOAP requests and responses for the makeUpper operation will pass through the configured handler chain (myChain).

19.7.3.1 Using only SOAP handlers to implement an operation

Typically, a web service operation is implemented by a backend component. However, a web service operation also may be implemented through a handler chain alone, without the aid of any backend component. This means a SOAP message is processed by the handleRequest( ) methods of each handler in the chain, and then by the handleResponse( ) methods of each handler in the chain, but in reverse order. A web service operation implemented solely through a chain of SOAP message handlers can be configured as follows:

name="myChainService" handler-chain="myChain">

In this case, you can completely ignore the component and method attributes for the web service operation.

Категории