java left logo
java middle logo
java right logo
 

Home arrow Java EE Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4091
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
Writing a Handler in JAX-WS E-mail
User Rating: / 142
PoorBest 

This Tech Tip reprinted with permission by java.sun.com

Handlers are interceptors that can be easily plugged into the Java API for XML-Based Web Services (JAX-WS) 2.0 runtime environment to do additional processing of inbound and outbound messages. JAX-WS defines two types of handlers: protocol handlers and logical handlers. Protocol handlers are specific to a protocol such as SOAP. They can access or change any part of the message, including protocol-specific parts such as the message header. Logical handlers are protocol-agnostic. They cannot change any protocol-specific parts of a message. Logical handlers act only on the payload of the message.

This tip shows you how to write a SOAP protocol handler and a logical handler for use with JAX-WS. Handler Basics.

Handler Basics

SOAP handlers are generally used to process SOAP-specific information, such as SOAP headers. For example, a SOAP Handler can process security headers in a message and pass the request to the endpoint if the message has the required credentials. Logical handlers are commonly used if the processing does not need access to SOAP headers, for validation of the payload, and with Representational State Transfer ("REST") style web services. In addition, logical handlers can use Java API for XML Binding (JAXB) for processing the payload. If you have the JAXBContext object, it's simple to alter something in a message with a logical handler. You can get the JAXB objects and call Java methods on them rather than dealing with Source objects or SOAPMessage objects using the SOAP with Attachments API for Java (SAAJ) in a SOAP handler.

Handlers are invoked with a message context, which provides methods that the handler uses to access and modify inbound or outbound messages. The message context also has properties that the handler can process. These properties can be used to communicate additional information or metadata that is not specified in the message. The additional information can be exchanged between a handler and service implementation or between a handler and a web service client. (For more information about message context in JAX-WS, see the article A little bit about Message Context in JAX-WS.)

SOAP handlers extend javax.xml.ws.handler.soap.SOAPHandler. The JAX-WS specification defines the SOAPHandler class for SOAP binding. When a SOAP handler is invoked, a SOAPMessageContext object is specified in the request. The SOAPMessageContext object provides methods to access a SOAPMessage (the class for SOAP messages). Specifically, the method getMessage() in SOAPMesageContext retrieves the SOAPMessage. After getting a SOAPMessage, you can use SAAJ to manipulate it.

Logical handlers extend javax.xml.ws.handler.LogicalHandler. They provide access to the message context and the message payload. If you use SOAP over HTTP for the message exchange, the content of the SOAP body forms the payload. If you use XML over HTTP, the XML content of the primary part of the message forms the payload. When a logical handler is invoked, a LogicalMessageContext object is specified in the request. The method getMessage() in LogicalMessageContext returns a LogicalMessage. The LogicalMessage represents a protocol-neutral XML message and contains methods that provide access to the payload of the message.

The following figure illustrates the relationship between the message contexts, the objects they can be used to retrieve, and the parts of a message those objects cover.


Image

Logical handlers can coexist with SOAP handlers in a handler chain. During runtime, the handler chain is reordered so that for an outbound message the logical handlers execute before the SOAP handlers. For an inbound message, the SOAP handlers execute before the logical handlers.

The following figure shows how logical and SOAP handlers are invoked during a request and response.


Image

Writing a SOAP Message Handler

Let's look at a simple SOAP handler. A sample package (http://java.sun.com/developer/EJTechTips/download/ttjun2006handler.zip) accompanies this tip. Download the sample package and extract its contents. You'll see two source files. One of them, SOAPLoggingHandler, is a SOAP handler that logs calls to a web service. Here's a code snippet from SOAPLoggingHandler:

   public class SOAPLoggingHandler implements 
    SOAPHandler<SOAPMessageContext> {
   ... 
   
      public boolean handleMessage(SOAPMessageContext smc) {
          logToSystemOut(smc);
          return true;
      }
       
      public boolean handleFault(SOAPMessageContext smc) {
          logToSystemOut(smc);
          return true;
      }
       
      public void close(MessageContext messageContext) {
      }
      
   ...  

Like all SOAP handlers, SOAPLoggingHandler implements the SOAPHandler interface. Notice that SOAPLoggingHandler also implements three methods: handleMessage(), handleFault(), and close(). The SOAPHandler interface is a subinterface of the Handler interface. The handleMessage(), handleFault(), and close() methods are the three methods defined in the Handler interface, and should be implemented in all basic handlers. Here's how the methods are used:

  • handleMessage() is called for normal processing of inbound and outbound messages.
  • handleFault is called when a message contains a protocol fault.
  • close( ) is called after the completion of message processing by all handlers for each web service invocation, that is, after the completion of a SOAP method exchange pattern (or "MEP").

The logging is done in the handler's logToSystemOut() method that both the handleMessage() and handleFault() methods call:

    private void logToSystemOut(SOAPMessageContext smc) {
        Boolean outboundProperty = (Boolean)
            smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        
        if (outboundProperty.booleanValue()) {
            out.println("\nOutbound message:");
        else {
            out.println("\nInbound message:");
        }
        
        SOAPMessage message = smc.getMessage();
        try {
            message.writeTo(out);
            out.println("");   
        catch (Exception e) {
            out.println("Exception in handler: " + e);
        }
    }

Notice that the logToSystemOut() method accesses a SOAPMessageContext property, MESSAGE_OUTBOUND_PROPERTY, and uses a SOAPMessageContext method, getMessage(). The value of MESSAGE_OUTBOUND_PROPERTY indicates the message direction. A value of true means that the message is outbound. A value of false indicates an inbound message. Based on the property value, logToSystemOut() prints either "Outbound message" or "Inbound message." It then uses getMessage() to get the SOAP message, and prints it.

Writing a Logical Message Handler

As its name suggests, the LogicalLoggingHandler file in the sample package is a logical message handler. Like the SOAPLoggingHandler, it logs calls to a web service. Here's a code snippet from LogicalLoggingHandler:

   public class LogicalLoggingHandler implements 
    LogicalHandler<LogicalMessageContext> {
   ...
   
       public boolean handleMessage
        (LogicalMessageContext context) {
           return processMessage(context);
       }
       
       public boolean handleFault
        (LogicalMessageContext context) {
           return processMessage(context);
       }
       
       public void close(MessageContext context) {
           // Clean up Resources
       }

Like all logical handlers, LogicalLoggingHandler implements the LogicalHandler interface. And like all handlers it implements the handleMessage(), handleFault(), and close() methods.

The logging is done in the handler's processMessage() method that both the handleMessage() and handleFault() methods call:

   private boolean processMessage
    (LogicalMessageContext context) {
       Boolean outboundProperty = (Boolean)
          context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
   
          if (outboundProperty) {
              out.println("\nOutbound message:");
          else {
              out.println("\nInbound message:");
          }
          LogicalMessage lm = context.getMessage();
          Source payload = lm.getPayload();
   
          // Process Payload Source
          printSource(payload);
          // ....
          
          // If the payload is modified, 
          // Do lm.setPayload(source) to be safe. Without it, 
          // behavior may vary on the kind of source returned in 
          // lm.getPayload().
          // See LogicalMessage JavaDoc for more details.
          // lm.setPayload(modifiedPayload);
          return true;

The processMessage() method accesses and manipulates the message payload using the logical message context for the logical handler. It calls the LogicalMessage method, getPayload(), to get the payload of the message. The payload is returned as a Source object.

Notice the commented out portion of processMessage(). In some cases, you might need to call the LogicalMessage method, setPayload(), after a modification is made to the payload. The source returned by getPayload() depends on the JAX-WS runtime. If the returned source is DOMSource, a modification to the encapsulated DOM tree changes the message payload in place. In that case, there is no need to subsequently call setPayload(). However, other types of returned source provide only read access to the message. In those cases, you need to call setPayload() after any modifications.

You can also pass a JAXBContext object in the call to getPayload(), to get the payload as a JAXB object. Here's an example:

   LogicalMessage lm = context.getMessage();
   Object jaxbObject = lm.getPayload(jaxbContext);
   // Modify JAXB Object
   lm.setPayload(modifiedJaxbObject,jaxbContext);

Note that there is no connection between the returned object and the message payload -- to change the payload, you need to call setPayload().

Handlers are flexible to plug-in and can be a powerful addition to your application. For another JAX-WS handler example, see "Handler example using JAXWS 2.0" in Stephen DeMilla's blog (http://blogs.sun.com/roller/page/sdimilla?entry=implementing_handlers_using_jaxws_2)

About the Author

Rama Pulavarthi is a Member of Technical Staff in the Java Web Services group at Sun Microsystems. He currently works on the development of the JAX-WS Reference Implementation. He previously lead the Software Quality Engineering effort for JAX-RPC.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.


 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.