9 Creating and Using SOAP Message Handlers

The following sections provide information about creating and using SOAP message handlers:

Overview of SOAP Message Handlers

Some Web services need access to the SOAP message, for which you can create SOAP message handlers.

A SOAP message handler provides a mechanism for intercepting the SOAP message in both the request and response of the Web service. You can create handlers in both the Web service itself and the client applications that invoke the Web service.

A simple example of using handlers is to access information in the header part of the SOAP message. You can use the SOAP header to store Web service specific information and then use handlers to manipulate it.

You can also use SOAP message handlers to improve the performance of your Web service. After your Web service has been deployed for a while, you might discover that many consumers invoke it with the same parameters. You could improve the performance of your Web service by caching the results of popular invokes of the Web service (assuming the results are static) and immediately returning these results when appropriate, without ever invoking the back-end components that implement the Web service. You implement this performance improvement by using handlers to check the request SOAP message to see if it contains the popular parameters.

The following table lists the standard JWS annotations that you can use in your JWS file to specify that a Web service has a handler chain configured; later sections discuss how to use the annotations in more detail. For additional information, see the Web services MetaData for the Java Platform (JSR-181) specification at http://www.jcp.org/en/jsr/detail?id=181.

Table 9-1 JWS Annotations Used To Configure SOAP Message Handler Chains

JWS Annotation Description
javax.jws.HandlerChain

Associates the Web service with an externally defined handler chain. Use this annotation when multiple Web services need to share the same handler configuration, or if the handler chain consists of handlers for multiple transports.

javax.jws.soap.SOAPMessageHandlers

Specifies a list of SOAP handlers that run before and after the invocation of each Web service operation. Use this annotation (rather than @HandlerChain) if embedding handler configuration information in the JWS file itself is preferred, rather than having an external configuration file.

The @SOAPMessageHandler annotation is an array of @SOAPMessageHandlers. The handlers are executed in the order they are listed in this array.

Note; This annotation works with JAX-RPC Web services only.

javax.jws.soap.SOAPMessageHandler

Specifies a single SOAP message handler in the @SOAPMessageHandlers array.


The following table describes the main classes and interfaces of the javax.xml.rpc.handler API, some of which you use when creating the handler itself. These APIs are discussed in detail in a later section. For additional information about these APIs, see the JAX-RPC 1.1 specification at http://java.net/projects/jax-rpc/.

Table 9-2 JAX-RPC Handler Interfaces and Classes

javax.xml.rpc.handler Classes and Interfaces Description
Handler

Main interface that is implemented when creating a handler. Contains methods to handle the SOAP request, response, and faults.

GenericHandler

Abstract class that implements the Handler interface. User should extend this class when creating a handler, rather than implement Handler directly.

The GenericHandler class is a convenience abstract class that makes writing handlers easy. This class provides default implementations of the life cycle methods init and destroy and also different handle methods. A handler developer should only override methods that it needs to specialize as part of the derived handler implementation class.

HandlerChain

Interface that represents a list of handlers. An implementation class for the HandlerChain interface abstracts the policy and mechanism for the invocation of the registered handlers.

HandlerRegistry

Interface that provides support for the programmatic configuration of handlers in a HandlerRegistry.

HandlerInfo

Class that contains information about the handler in a handler chain. A HandlerInfo instance is passed in the Handler.init method to initialize a Handler instance.

MessageContext

Abstracts the message context processed by the handler. The MessageContext properties allow the handlers in a handler chain to share processing state.

soap.SOAPMessageContext

Sub-interface of the MessageContext interface used to get at or update the SOAP message.

javax.xml.soap.SOAPMessage

Object that contains the actual request or response SOAP message, including its header, body, and attachment.


Adding SOAP Message Handlers to a Web Service: Main Steps

The following procedure describes the high-level steps to add SOAP message handlers to your Web service.

It is assumed that you have created a basic JWS file that implements a Web service and that you want to update the Web service by adding SOAP message handlers and handler chains. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml file that includes a target for running the jwsc Ant task. For more information, see in Getting Started With JAX-RPC Web Services for Oracle WebLogic Server:

Table 9-3 Steps to Add SOAP Message Handlers to a Web Service

#
Step Description

1

Design the handlers and handler chains.

See Designing the SOAP Message Handlers and Handler Chains.

2

For each handler in the handler chain, create a Java class that extends the javax.xml.rpc.handler.GenericHandler abstract class.

See Creating the GenericHandler Class.

3

Update your JWS file, adding annotations to configure the SOAP message handlers.

See Configuring Handlers in the JWS File.

4

If you are using the @HandlerChain standard annotation in your JWS file, create the handler chain configuration file.

See Creating the Handler Chain Configuration File.

5

Compile all handler classes in the handler chain and rebuild your Web service.

See Compiling and Rebuilding the Web Service.


For information about creating client-side SOAP message handlers and handler chains, see Creating and Using Client-Side SOAP Message Handlers.

Designing the SOAP Message Handlers and Handler Chains

When designing your SOAP message handlers and handler chains, you must decide:

  • The number of handlers needed to perform all the work

  • The sequence of execution

Each handler in a handler chain has one method for handling the request SOAP message and another method for handling the response SOAP message. An ordered group of handlers is referred to as a handler chain. You specify that a Web service has a handler chain attached to it with one of two JWS annotations: @HandlerChain or @SOAPMessageHandler. When to use which is discussed in a later section.

When invoking a Web service, WebLogic Server executes handlers as follows:

  1. The handleRequest() methods of the handlers in the handler chain are all executed in the order specified by the JWS annotation. Any of these handleRequest() methods might change the SOAP message request.

  2. When the handleRequest() method of the last handler in the handler chain executes, WebLogic Server invokes the back-end component that implements the Web service, passing it the final SOAP message request.

  3. When the back-end component has finished executing, the handleResponse() methods of the handlers in the handler chain are executed in the reverse order specified in by the JWS annotation. Any of these handleResponse() methods might change the SOAP message response.

  4. When the handleResponse() method of the first handler in the handler chain executes, WebLogic Server returns the final SOAP message response to the client application that invoked the Web service.

For example, assume that you are going to use the @HandlerChain JWS annotation in your JWS file to specify an external configuration file, and the configuration file defines a handler chain called SimpleChain that contains three handlers, as shown in the following sample:

<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
   xmlns:soap1="http://HandlerInfo.org/Server1"
   xmlns:soap2="http://HandlerInfo.org/Server2"
   xmlns="http://java.sun.com/xml/ns/j2ee" >

   <jwshc:handler-chain>

     <jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>

     <jwshc:handler>
       <handler-name>handlerOne</handler-name>
       <handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
     </jwshc:handler>

     <jwshc:handler>
       <handler-name>handlerTwo</handler-name>
       <handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
     </jwshc:handler>

     <jwshc:handler>
       <handler-name>handlerThree</handler-name>
       <handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler3</handler-class>
     </jwshc:handler>

   </jwshc:handler-chain>

</jwshc:handler-config>

The following graphic shows the order in which WebLogic Server executes the handleRequest() and handleResponse() methods of each handler.

Figure 9-1 Order of Execution of Handler Methods

Description of Figure 9-1 follows
Description of "Figure 9-1 Order of Execution of Handler Methods"

Each SOAP message handler has a separate method to process the request and response SOAP message because the same type of processing typically must happen for the inbound and outbound message. For example, you might design an Encryption handler whose handleRequest() method decrypts secure data in the SOAP request and handleResponse() method encrypts the SOAP response.

You can, however, design a handler that process only the SOAP request and does no equivalent processing of the response.

You can also choose not to invoke the next handler in the handler chain and send an immediate response to the client application at any point.

Creating the GenericHandler Class

Your SOAP message handler class should extend the javax.rpc.xml.handler.GenericHandler abstract class, which itself implements the javax.rpc.xml.handler.Handler interface.

The GenericHandler class is a convenience abstract class that makes writing handlers easy. This class provides default implementations of the life cycle methods init() and destroy() and the various handleXXX() methods of the Handler interface. When you write your handler class, only override those methods that you need to customize as part of your Handler implementation class.

In particular, the Handler interface contains the following methods that you can implement in your handler class that extends GenericHandler:

Sometimes you might need to directly view or update the SOAP message from within your handler, in particular when handling attachments, such as image. In this case, use the javax.xml.soap.SOAPMessage abstract class, which is part of the SOAP With Attachments API for Java 1.1 (SAAJ) specification at https://saaj.dev.java.net/. For details, see Directly Manipulating the SOAP Request and Response Message Using SAAJ.

The following example demonstrates a simple SOAP message handler that prints out the SOAP request and response messages to the WebLogic Server log file:

package examples.webservices.soap_handlers.global_handler;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.JAXRPCException;

import weblogic.logging.NonCatalogLogger;

/**
 * This class implements a handler in the handler chain, used to access the SOAP
 * request and response message.
 * <p>
 * This class extends the <code>javax.xml.rpc.handler.GenericHandler</code>
 * abstract classs and simply prints the SOAP request and response messages to
 * the server log file before the messages are processed by the backend
 * Java class that implements the Web Service itself.
 */

public class ServerHandler1 extends GenericHandler {

  private NonCatalogLogger log;

  private HandlerInfo handlerInfo;

  /**
   *  Initializes the instance of the handler.  Creates a nonCatalogLogger to
   *  log messages to.
   */

  public void init(HandlerInfo hi) {

    log = new NonCatalogLogger("WebService-LogHandler");
    handlerInfo = hi;
  }

  /**
   * Specifies that the SOAP request message be logged to a log file before the
   * message is sent to the Java class that implements the Web Service.
   */

  public boolean handleRequest(MessageContext context) {

   SOAPMessageContext messageContext = (SOAPMessageContext) context;

   System.out.println("** Request: "+messageContext.getMessage().toString());
   log.info(messageContext.getMessage().toString());
   return true;

  }

  /**
   * Specifies that the SOAP response message be logged to a log file before the
   * message is sent back to the client application that invoked the Web
   * service.
   */

  public boolean handleResponse(MessageContext context) {

    SOAPMessageContext messageContext = (SOAPMessageContext) context;

    System.out.println("** Response: "+messageContext.getMessage().toString());
    log.info(messageContext.getMessage().toString());
    return true;

  }

  /**
   * Specifies that a message be logged to the log file if a SOAP fault is
   * thrown by the Handler instance.
   */

  public boolean handleFault(MessageContext context) {

   SOAPMessageContext messageContext = (SOAPMessageContext) context;

   System.out.println("** Fault: "+messageContext.getMessage().toString());
   log.info(messageContext.getMessage().toString());
       return true;

  }

  public QName[] getHeaders() {

    return handlerInfo.getHeaders();

  }

}

Implementing the Handler.init() Method

The Handler.init() method is called to create an instance of a Handler object and to enable the instance to initialize itself. Its signature is:

  public void init(HandlerInfo config) throws JAXRPCException {}

The HandlerInfo object contains information about the SOAP message handler, in particular the initialization parameters. Use the HandlerInfo.getHandlerConfig() method to get the parameters; the method returns a java.util.Map object that contains name-value pairs.

Implement the init() method if you need to process the initialization parameters or if you have other initialization tasks to perform.

Sample uses of initialization parameters are to turn debugging on or off, specify the name of a log file to which to write messages or errors, and so on.

Implementing the Handler.destroy() Method

The Handler.destroy() method is called to destroy an instance of a Handler object. Its signature is:

  public void destroy() throws JAXRPCException {}

Implement the destroy() method to release any resources acquired throughout the handler's life cycle.

Implementing the Handler.getHeaders() Method

The Handler.getHeaders() method gets the header blocks that can be processed by this Handler instance. Its signature is:

  public QName[] getHeaders() {}

Implementing the Handler.handleRequest() Method

The Handler.handleRequest() method is called to intercept a SOAP message request before it is processed by the back-end component. Its signature is:

  public boolean handleRequest(MessageContext mc) 
          throws JAXRPCException,SOAPFaultException  {}

Implement this method to perform such tasks as decrypting data in the SOAP message before it is processed by the back-end component, and so on.

The MessageContext object abstracts the message context processed by the SOAP message handler. The MessageContext properties allow the handlers in a handler chain to share processing state.

Use the SOAPMessageContext sub-interface of MessageContext to get at or update the contents of the SOAP message request. The SOAP message request itself is stored in a javax.xml.soap.SOAPMessage object. For detailed information on this object, see Directly Manipulating the SOAP Request and Response Message Using SAAJ.

The SOAPMessageContext class defines two methods for processing the SOAP request:

  • SOAPMessageContext.getMessage()returns a javax.xml.soap.SOAPMessage object that contains the SOAP message request.

  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage)updates the SOAP message request after you have made changes to it.

After you code all the processing of the SOAP request, code one of the following scenarios:

  • Invoke the next handler on the handler request chain by returning true.

    The next handler on the request chain is specified as either the next <handler> subelement of the <handler-chain> element in the configuration file specified by the @HandlerChain annotation, or the next @SOAPMessageHandler in the array specified by the @SOAPMessageHandlers annotation. If there are no more handlers in the chain, the method either invokes the back-end component, passing it the final SOAP message request, or invokes the handleResponse() method of the last handler, depending on how you have configured your Web service.

  • Block processing of the handler request chain by returning false.

    Blocking the handler request chain processing implies that the back-end component does not get executed for this invoke of the Web service. You might want to do this if you have cached the results of certain invokes of the Web service, and the current invoke is on the list.

    Although the handler request chain does not continue processing, WebLogic Server does invoke the handler response chain, starting at the current handler. For example, assume that a handler chain consists of two handlers: handlerA and handlerB, where the handleRequest() method of handlerA is invoked before that of handlerB. If processing is blocked in handlerA (and thus the handleRequest() method of handlerB is not invoked), the handler response chain starts at handlerA and the handleRequest() method of handlerB is not invoked either.

  • Throw the javax.xml.rpc.soap.SOAPFaultException to indicate a SOAP fault.

    If the handleRequest() method throws a SOAPFaultException, WebLogic Server catches the exception, terminates further processing of the handler request chain, and invokes the handleFault() method of this handler.

  • Throw a JAXRPCException for any handler-specific runtime errors.

    If the handleRequest() method throws a JAXRPCException, WebLogic Server catches the exception, terminates further processing of the handler request chain, logs the exception to the WebLogic Server log file, and invokes the handleFault() method of this handler.

Implementing the Handler.handleResponse() Method

The Handler.handleResponse() method is called to intercept a SOAP message response after it has been processed by the back-end component, but before it is sent back to the client application that invoked the Web service. Its signature is:

  public boolean handleResponse(MessageContext mc) throws JAXRPCException {}

Implement this method to perform such tasks as encrypting data in the SOAP message before it is sent back to the client application, to further process returned values, and so on.

The MessageContext object abstracts the message context processed by the SOAP message handler. The MessageContext properties allow the handlers in a handler chain to share processing state.

Use the SOAPMessageContext sub-interface of MessageContext to get at or update the contents of the SOAP message response. The SOAP message response itself is stored in a javax.xml.soap.SOAPMessage object. See Directly Manipulating the SOAP Request and Response Message Using SAAJ.

The SOAPMessageContext class defines two methods for processing the SOAP response:

  • SOAPMessageContext.getMessage(): returns a javax.xml.soap.SOAPMessage object that contains the SOAP message response.

  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage): updates the SOAP message response after you have made changes to it.

After you code all the processing of the SOAP response, code one of the following scenarios:

  • Invoke the next handler on the handler response chain by returning true.

    The next response on the handler chain is specified as either the preceding <handler> subelement of the <handler-chain> element in the configuration file specified by the @HandlerChain annotation, or the preceding @SOAPMessageHandler in the array specified by the @SOAPMessageHandlers annotation. (Remember that responses on the handler chain execute in the reverse order that they are specified in the JWS file. See Designing the SOAP Message Handlers and Handler Chains for more information.)

    If there are no more handlers in the chain, the method sends the final SOAP message response to the client application that invoked the Web service.

  • Block processing of the handler response chain by returning false.

    Blocking the handler response chain processing implies that the remaining handlers on the response chain do not get executed for this invoke of the Web service and the current SOAP message is sent back to the client application.

  • Throw a JAXRPCException for any handler specific runtime errors.

    If the handleRequest() method throws a JAXRPCException, WebLogic Server catches the exception, terminates further processing of the handler request chain, logs the exception to the WebLogic Server logfile, and invokes the handleFault() method of this handler.

Implementing the Handler.handleFault() Method

The Handler.handleFault() method processes the SOAP faults based on the SOAP message processing model. Its signature is:

    public boolean handleFault(MessageContext mc) throws JAXRPCException  {}

Implement this method to handle processing of any SOAP faults generated by the handleResponse() and handleRequest() methods, as well as faults generated by the back-end component.

The MessageContext object abstracts the message context processed by the SOAP message handler. The MessageContext properties allow the handlers in a handler chain to share processing state.

Use the SOAPMessageContext sub-interface of MessageContext to get at or update the contents of the SOAP message. The SOAP message itself is stored in a javax.xml.soap.SOAPMessage object. See Directly Manipulating the SOAP Request and Response Message Using SAAJ.

The SOAPMessageContext class defines the following two methods for processing the SOAP message:

  • SOAPMessageContext.getMessage(): returns a javax.xml.soap.SOAPMessage object that contains the SOAP message.

  • SOAPMessageContext.setMessage(javax.xml.soap.SOAPMessage): updates the SOAP message after you have made changes to it.

After you code all the processing of the SOAP fault, do one of the following:

  • Invoke the handleFault() method on the next handler in the handler chain by returning true.

  • Block processing of the handler fault chain by returning false.

Directly Manipulating the SOAP Request and Response Message Using SAAJ

The javax.xml.soap.SOAPMessage abstract class is part of the SOAP With Attachments API for Java 1.1 (SAAJ) specification (see https://saaj.dev.java.net/). You use the class to manipulate request and response SOAP messages when creating SOAP message handlers. This section describes the basic structure of a SOAPMessage object and some of the methods you can use to view and update a SOAP message.

A SOAPMessage object consists of a SOAPPart object (which contains the actual SOAP XML document) and zero or more attachments.

Refer to the SAAJ Javadocs for the full description of the SOAPMessage class.

The SOAPPart Object

The SOAPPart object contains the XML SOAP document inside of a SOAPEnvelope object. You use this object to get the actual SOAP headers and body.

The following sample Java code shows how to retrieve the SOAP message from a MessageContext object, provided by the Handler class, and get at its parts:

SOAPMessage soapMessage =  messageContext.getMessage();
SOAPPart soapPart = soapMessage.getSOAPPart();
SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
SOAPBody soapBody = soapEnvelope.getBody();
SOAPHeader soapHeader = soapEnvelope.getHeader(); 

The AttachmentPart Object

The javax.xml.soap.AttachmentPart object contains the optional attachments to the SOAP message. Unlike the rest of a SOAP message, an attachment is not required to be in XML format and can therefore be anything from simple text to an image file.

Note:

If you are going to access a java.awt.Image attachment from your SOAP message handler, see Manipulating Image Attachments in a SOAP Message Handler for important information.

Use the following methods of the SOAPMessage class to manipulate the attachments:

  • countAttachments(): returns the number of attachments in this SOAP message.

  • getAttachments(): retrieves all the attachments (as AttachmentPart objects) into an Iterator object.

  • createAttachmentPart(): create an AttachmentPart object from another type of Object.

  • addAttachmentPart(): adds an AttachmentPart object, after it has been created, to the SOAPMessage.

Manipulating Image Attachments in a SOAP Message Handler

It is assumed in this section that you are creating a SOAP message handler that accesses a java.awt.Image attachment and that the Image has been sent from a client application that uses the client JAX-RPC stubs generated by the clientgen Ant task.

In the client code generated by the clientgen Ant task, a java.awt.Image attachment is sent to the invoked WebLogic Web service with a MIME type of text/xml rather than image/gif, and the image is serialized into a stream of integers that represents the image. In particular, the client code serializes the image using the following format:

  • int width

  • int height

  • int[] pixels

This means that, in your SOAP message handler that manipulates the received Image attachment, you must deserialize this stream of data to then re-create the original image.

Configuring Handlers in the JWS File

There are two standard annotations you can use in your JWS file to configure a handler chain for a Web service: @javax.jws.HandlerChain and @javax.jws.soap.SOAPMessageHandlers.

@javax.jws.HandlerChain

When you use the @javax.jws.HandlerChain annotation (also called @HandlerChain in this chapter for simplicity) you use the file attribute to specify an external file that contains the configuration of the handler chain you want to associate with the Web service. The configuration includes the list of handlers in the chain, the order in which they execute, the initialization parameters, and so on.

Use the @HandlerChain annotation, rather than the @SOAPMessageHandlers annotation, in your JWS file if one or more of the following conditions apply:

  • You want multiple Web services to share the same configuration.

  • Your handler chain includes handlers for multiple transports.

  • You want to be able to change the handler chain configuration for a Web service without recompiling the JWS file that implements it.

The following JWS file shows an example of using the @HandlerChain annotation; the relevant Java code is shown in bold:

package examples.webservices.soap_handlers.global_handler;

import java.io.Serializable;

import javax.jws.HandlerChain; 
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;

import weblogic.jws.WLHttpTransport;

@WebService(serviceName="HandlerChainService",
            name="HandlerChainPortType")

// Standard JWS annotation that specifies that the handler chain called 
// "SimpleChain", configured in the HandlerConfig.xml file, should fire 
// each time an operation of the Web Service is invoked. 

@HandlerChain(file="HandlerConfig.xml", name="SimpleChain") 

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
             use=SOAPBinding.Use.LITERAL,
             parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

@WLHttpTransport(contextPath="HandlerChain", serviceUri="HandlerChain",
                 portName="HandlerChainServicePort")

/**
 * This JWS file forms the basis of simple Java-class implemented WebLogic
 * Web Service with a single operation: sayHello.  The Web Service also
 * has a handler chain associated with it, as specified by the
 * @HandlerChain annotation.
 */

public class HandlerChainImpl  {

   public String sayHello(String input) {
     weblogic.utils.Debug.say( "in backend component. input:" +input );
     return "'" + input + "' to you too!";
   }
}

Before you use the @HandlerChain annotation, you must import it into your JWS file, as shown in the preceding example.

Use the file attribute of the @HandlerChain annotation to specify the name of the external file that contains configuration information for the handler chain. The value of this attribute is a URL, which may be relative or absolute. Relative URLs are relative to the location of the JWS file at the time you run the jwsc Ant task to compile the file.

Use the name attribute to specify the name of the handler chain in the configuration file that you want to associate with the Web service. The value of this attribute corresponds to the name attribute of the <handler-chain> element in the configuration file.

Note:

It is an error to specify more than one @HandlerChain annotation in a single JWS file. It is also an error to combine the @HandlerChain annotation with the @SOAPMessageHandlers annotation.

For details about creating the external configuration file, see Creating the Handler Chain Configuration File.

For additional detailed information about the standard JWS annotations discussed in this section, see the Web services Metadata for the Java Platform specification at http://www.jcp.org/en/jsr/detail?id=181.

@javax.jws.soap.SOAPMessageHandlers

Note:

This annotation has been deprecated as of the Web services Metadata for the Java Platform specification (JSR-181) at http://www.jcp.org/en/jsr/detail?id=181.

When you use the @javax.jws.soap.SOAPMessageHandlers (also called @SOAPMessageHandlers in this section for simplicity) annotation, you specify, within the JWS file itself, an array of SOAP message handlers (specified with the @SOAPMessageHandler annotation) that execute before and after the operations of a Web service. The @SOAPMessageHandler annotation includes attributes to specify the class name of the handler, the initialization parameters, list of SOAP headers processed by the handler, and so on. Because you specify the list of handlers within the JWS file itself, the configuration of the handler chain is embedded within the Web service.

Use the @SOAPMessageHandlers annotation if one or more of the following conditions apply:

  • You prefer to embed the configuration of the handler chain inside the Web service itself, rather than specify the configuration in an external file.

  • Your handler chain includes only SOAP handlers and none for any other transport.

  • You prefer to recompile the JWS file each time you change the handler chain configuration.

The following JWS file shows a simple example of using the @SOAPMessageHandlers annotation; the relevant Java code is shown in bold:

package examples.webservices.soap_handlers.simple;

import java.io.Serializable;

import javax.jws.soap.SOAPMessageHandlers; 
import javax.jws.soap.SOAPMessageHandler; 
import javax.jws.soap.SOAPBinding;
import javax.jws.WebService;
import javax.jws.WebMethod;

import weblogic.jws.WLHttpTransport;

@WebService(name="SimpleChainPortType",  
            serviceName="SimpleChainService")

// Standard JWS annotation that specifies a list of SOAP message handlers 
// that exeucte before and after an invocation of all operations in the 
// Web Serice. 

@SOAPMessageHandlers ( { 
        @SOAPMessageHandler ( 
          className="examples.webservices.soap_handlers.simple.ServerHandler1"), 
        @SOAPMessageHandler ( 
          className="examples.webservices.soap_handlers.simple.ServerHandler2") 
        } ) 

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
             use=SOAPBinding.Use.LITERAL,
             parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

@WLHttpTransport(contextPath="SimpleChain", serviceUri="SimpleChain",
                 portName="SimpleChainServicePort")

/**
 * This JWS file forms the basis of simple Java-class implemented WebLogic
 * Web Service with a single operation: sayHello.  The Web Service also
 * has a handler chain associated with it, as specified by the
 * @SOAPMessageHandler/s annotations.
 */

public class SimpleChainImpl  {

   // by default all public methods are exposed as operations

   public String sayHello(String input)  {
     weblogic.utils.Debug.say( "in backend component. input:" +input );
     return "'" + input + "' to you too!";
   }
}

Before you use the @SOAPMessageHandlers and @SOAPMessageHandler annotations, you must import them into your JWS file, as shown in the preceding example. Note that these annotations are in the javax.jws.soap package.

The order in which you list the handlers (using the @SOAPMessageHandler annotation) in the @SOAPMessageHandlers array specifies the order in which the handlers execute: in forward order before the operation, and in reverse order after the operation. The preceding example configures two handlers in the handler chain, whose class names are examples.webservices.soap_handlers.simple.ServerHandler1 and examples.webservices.soap_handlers.simple.ServerHandler2.

Use the initParams attribute of @SOAPMessageHandler to specify an array of initialization parameters expected by a particular handler. Use the @InitParam standard JWS annotation to specify the name/value pairs, as shown in the following example:

@SOAPMessageHandler(
  className = "examples.webservices.soap_handlers.simple.ServerHandler1",
  initParams = { @InitParam(name="logCategory", value="MyService")} 
)

The @SOAPMessageHandler annotation also includes the roles attribute for listing the SOAP roles implemented by the handler, and the headers attribute for listing the SOAP headers processed by the handler.

Note:

It is an error to combine the @SOAPMessageHandlers annotation with the @HandlerChain annotation.

For additional detailed information about the standard JWS annotations discussed in this section, see the Web services Metadata for the Java Platform specification http://www.jcp.org/en/jsr/detail?id=181.

Creating the Handler Chain Configuration File

If you decide to use the @HandlerChain annotation in your JWS file to associate a handler chain with a Web service, you must create an external configuration file that specifies the list of handlers in the handler chain, the order in which they execute, the initialization parameters, and so on.

Because this file is external to the JWS file, you can configure multiple Web services to use this single configuration file to standardize the handler configuration file for all Web services in your enterprise. Additionally, you can change the configuration of the handler chains without needing to recompile all your Web services. Finally, if you include handlers in your handler chain that use a non-SOAP transport, then you are required to use the @HandlerChain annotation rather than the @SOAPMessageHandler annotation.

The configuration file uses XML to list one or more handler chains, as shown in the following simple example:

<jwshc:handler-config xmlns:jwshc="http://www.bea.com/xml/ns/jws"
   xmlns:soap1="http://HandlerInfo.org/Server1"
   xmlns:soap2="http://HandlerInfo.org/Server2"
   xmlns="http://java.sun.com/xml/ns/j2ee" >
   <jwshc:handler-chain>
     <jwshc:handler-chain-name>SimpleChain</jwshc:handler-chain-name>
     <jwshc:handler>
       <handler-name>handler1</handler-name>
       <handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler1</handler-class>
     </jwshc:handler>
     <jwshc:handler>
       <handler-name>handler2</handler-name>
       <handler-class>examples.webservices.soap_handlers.global_handler.ServerHandler2</handler-class>
     </jwshc:handler>
   </jwshc:handler-chain>
</jwshc:handler-config>

In the example, the handler chain called SimpleChain contains two handlers: handler1 and handler2, implemented with the class names specified with the <handler-class> element. The two handlers execute in forward order before the relevant Web service operation executes, and in reverse order after the operation executes.

Use the <init-param>, <soap-role>, and <soap-header> child elements of the <handler> element to specify the handler initialization parameters, SOAP roles implemented by the handler, and SOAP headers processed by the handler, respectively.

For the XML Schema that defines the external configuration file, additional information about creating it, and additional examples, see the Web services Metadata for the Java Platform specification at http://www.jcp.org/en/jsr/detail?id=181.

Compiling and Rebuilding the Web Service

It is assumed in this section that you have a working build.xml Ant file that compiles and builds your Web service, and you want to update the build file to include handler chain. See "Developing WebLogic Web Services" in Getting Started With JAX-RPC Web Services for Oracle WebLogic Server for information on creating this build.xml file.

Follow these guidelines to update your development environment to include message handler compilation and building:

  • After you have updated the JWS file with either the @HandlerChain or @SOAPMessageHandlers annotation, you must rerun the jwsc Ant task to recompile the JWS file and generate a new Web service. This is true anytime you make a change to an annotation in the JWS file.

    If you used the @HandlerChain annotation in your JWS file, reran the jwsc Ant task to regenerate the Web service, and subsequently changed only the external configuration file, you do not need to rerun jwsc for the second change to take affect.

  • The jwsc Ant task compiles SOAP message handler Java files into handler classes (and then packages them into the generated application) if all the following conditions are true:

    • The handler classes are referenced in the @HandlerChain or @SOAPMessageHandler(s) annotations of the JWS file.

    • The Java files are located in the directory specified by the sourcepath attribute.

    • The classes are not currently in your CLASSPATH.

    If you want to compile the handler classes yourself, rather than let jwsc compile them automatically, ensure that the compiled classes are in your CLASSPATH before you run the jwsc Ant task.

  • You deploy and invoke a Web service that has a handler chain associated with it in the same way you deploy and invoke one that has no handler chain. The only difference is that when you invoke any operation of the Web service, the WebLogic Web services runtime executes the handlers in the handler chain both before and after the operation invoke.

Creating and Using Client-Side SOAP Message Handlers

The preceding sections describe how to create server-side SOAP message handlers that execute as part of the Web service running on WebLogic Server. You can also create client-side handlers that execute as part of the client application that invokes a Web service operation. In the case of a client-side handler, the handler executes twice:

  • Directly before the client application sends the SOAP request to the Web service

  • Directly after the client application receives the SOAP response from the Web service

You can configure client-side SOAP message handlers for both stand-alone clients and clients that run inside of WebLogic Server.

You create the actual Java client-side handler in the same way you create a server-side handler: write a Java class that extends the javax.xml.rpc.handler.GenericHandler abstract class. In many cases you can use the exact same handler class on both the Web service running on WebLogic Server and the client applications that invoke the Web service. For example, you can write a generic logging handler class that logs all sent and received SOAP messages, both for the server and for the client.

Similar to the server-side SOAP handler programming, you use an XML file to specify to the clientgen Ant task that you want to invoke client-side SOAP message handlers. However, the XML Schema of this XML file is slightly different, as described in the following procedure.

Using Client-Side SOAP Message Handlers: Main Steps

The following procedure describes the high-level steps to add client-side SOAP message handlers to the client application that invokes a Web service operation.

It is assumed that you have created the client application that invokes a deployed Web service, and that you want to update the client application by adding client-side SOAP message handlers and handler chains. It is also assumed that you have set up an Ant-based development environment and that you have a working build.xml file that includes a target for running the clientgen Ant task. For more information, see "Invoking a Web Service from a Stand-alone Client: Main Steps" in Getting Started With JAX-RPC Web Services for Oracle WebLogic Server.

  1. Design the client-side SOAP handlers and the handler chain which specifies the order in which they execute. This step is almost exactly the same as that of designing the server-side SOAP message handlers, except the perspective is from the client application, rather than a Web service.

    See Designing the SOAP Message Handlers and Handler Chains.

  2. For each handler in the handler chain, create a Java class that extends the javax.xml.rpc.handler.GenericHandler abstract class. This step is very similar to the corresponding server-side step, except that the handler executes in a chain in the client rather than the server.

    See Creating the GenericHandler Class for details about programming a handler class. See Example of a Client-Side Handler Class for an example.

  3. Create the client-side SOAP handler configuration file. This XML file describes the handlers in the handler chain, the order in which they execute, and any initialization parameters that should be sent.

    See Creating the Client-Side SOAP Handler Configuration File.

  4. Update the build.xml file that builds your client application, specifying to the clientgen Ant task the name of the SOAP handler configuration file. Also ensure that the build.xml file compiles the handler files into Java classes and makes them available to your client application.

    See Specifying the Client-Side SOAP Handler Configuration File to clientgen.

  5. Rebuild your client application by running the relevant task:

    prompt> ant build-client
    

When you next run the client application, the SOAP messaging handlers listed in the configuration file automatically execute before the SOAP request message is sent and after the response is received.

Note:

You do not have to update your actual client application to invoke the client-side SOAP message handlers; as long as you specify to the clientgen Ant task the handler configuration file, the generated JAX-RPC stubs automatically take care of executing the handlers in the correct sequence.

Example of a Client-Side Handler Class

The following example shows a simple SOAP message handler class that you can configure for a client application that invokes a Web service.

package examples.webservices.client_handler.client;

import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import javax.xml.rpc.handler.GenericHandler;
import javax.xml.rpc.handler.MessageContext;

public class ClientHandler1 extends GenericHandler {

  private QName[] headers;

  public void init(HandlerInfo hi) {
    System.out.println("in " + this.getClass() + " init()");
  }

  public boolean handleRequest(MessageContext context) {
    System.out.println("in " + this.getClass() + " handleRequest()");
    return true;
  }

  public boolean handleResponse(MessageContext context) {
    System.out.println("in " + this.getClass() + " handleResponse()");
    return true;
  }

  public boolean handleFault(MessageContext context) {
    System.out.println("in " + this.getClass() + " handleFault()");
    return true;
  }

  public QName[] getHeaders() {
    return headers;
  }
}

Creating the Client-Side SOAP Handler Configuration File

The client-side SOAP handler configuration file specifies the list of handlers in the handler chain, the order in which they execute, the initialization parameters, and so on. See XML Schema for the Client-Side Handler Configuration File for a full description of this file.

The configuration file uses XML to describe a single handler chain that contains one or more handlers, as shown in the following simple example:

<weblogic-wsee-clientHandlerChain
  xmlns="http://www.bea.com/ns/weblogic/90"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:j2ee="http://java.sun.com/xml/ns/j2ee">

        <handler>
          <j2ee:handler-name>clienthandler1</j2ee:handler-name>
          <j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler1</j2ee:handler-class>
          <j2ee:init-param>
            <j2ee:param-name>ClientParam1</j2ee:param-name>
            <j2ee:param-value>value1</j2ee:param-value>
          </j2ee:init-param>
        </handler>

        <handler>
          <j2ee:handler-name>clienthandler2</j2ee:handler-name>
          <j2ee:handler-class>examples.webservices.client_handler.client.ClientHandler2</j2ee:handler-class>
        </handler>

</weblogic-wsee-clientHandlerChain>

In the example, the handler chain contains two handlers: clienthandler1 and clienthandler2, implemented with the class names specified with the <j2ee:handler-class> element. The two handlers execute in forward order directly before the client application sends the SOAP request to the Web service, and then in reverse order directly after the client application receives the SOAP response from the Web service.

The example also shows how to use the <j2ee:init-param> element to specify one or more initialization parameters to a handler.

Use the <soap-role>, <soap-header>, and <port-name> child elements of the <handler> element to specify the SOAP roles implemented by the handler, the SOAP headers processed by the handler, and the port-name element in the WSDL with which the handler is associated with, respectively.

XML Schema for the Client-Side Handler Configuration File

The following XML Schema file defines the structure of the client-side SOAP handler configuration file:

<?xml version="1.0" encoding="UTF-8"?>

<schema
  targetNamespace="http://www.bea.com/ns/weblogic/90"
  xmlns:wls="http://www.bea.com/ns/weblogic/90"
  xmlns:j2ee="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="qualified"
  attributeFormDefault="unqualified"
  >
  <include schemaLocation="weblogic-j2ee.xsd"/>

  <element name="weblogic-wsee-clientHandlerChain"
           type="wls:weblogic-wsee-clientHandlerChainType">
       <xsd:key name="wsee-clienthandler-name-key">
            <xsd:annotation>
            <xsd:documentation>

            Defines the name of the handler. The name must be unique within the
            chain.

            </xsd:documentation>
            </xsd:annotation>
                <xsd:selector xpath="j2ee:handler"/>
                <xsd:field xpath="j2ee:handler-name"/>
       </xsd:key>
  </element>

  <complexType name="weblogic-wsee-clientHandlerChainType">
      <sequence>
        <xsd:element name="handler"
                     type="j2ee:service-ref_handlerType"
                     minOccurs="0" maxOccurs="unbounded">
        </xsd:element>
      </sequence>
  </complexType>
</schema>

A single configuration file specifies a single client-side handler chain. The root of the configuration file is <weblogic-wsee-clientHandlerChain>, and the file contains zero or more <handler> child elements, each of which describes a handler in the chain.

The structure of the <handler> element is described by the J2EE service-ref_handlerType complex type, specified in the J2EE 1.4 Web service client XML Schema http://java.sun.com/xml/ns/j2ee/j2ee_web_services_client_1_1.xsd.

Specifying the Client-Side SOAP Handler Configuration File to clientgen

Use the handlerChainFile attribute of the clientgen Ant task to specify the client-side SOAP handler configuration file, as shown in the following excerpt from a build.xml file:

    <clientgen
      wsdl="http://ariel:7001/handlers/ClientHandlerService?WSDL"
      destDir="${clientclass-dir}"
      handlerChainFile="ClientHandlerChain.xml"
      packageName="examples.webservices.client_handler.client"/>

The JAX-RPC stubs generated by clientgen automatically ensure that the handlers described by the configuration file execute in the correct order before and after the client application invokes the Web service operation.