Red Hat Training

A Red Hat training course is available for Red Hat Fuse

43.5. Handling Messages in a SOAP Handler

Overview

Normal message processing is handled by the handleMessage() method.
The handleMessage() method receives a SOAPMessageContext object that provides access to the message body as a SOAPMessage object and the SOAP headers associated with the message. In addition, the context provides access to any properties stored in the message context.
The handleMessage() method returns either true or false depending on how message processing is to continue. It can also throw an exception.

Working with the message body

You can get the SOAP message using the SOAP message context's getMessage() method. It returns the message as a live SOAPMessage object. Any changes to the message in the handler are automatically reflected in the message stored in the context.
If you wish to replace the existing message with a new one, you can use the context's setMessage() method. The setMessage() method takes a SOAPMessage object.

Getting the SOAP headers

You can access the SOAP message's headers using the SOAPMessage object's getHeader() method. This will return the SOAP header as a SOAPHeader object that you will need to inspect to find the header elements you wish to process.
The SOAP message context provides a getHeaders() method, shown in Example 43.10, “The SOAPMessageContext.getHeaders() Method”, that will return an array containing JAXB objects for the specified SOAP headers.

Example 43.10. The SOAPMessageContext.getHeaders() Method

Ojbect[] getHeaders(QName header,
                    JAXBContext context,
                    boolean allRoles);
You specify the headers using the QName of their element. You can further limit the headers that are returned by setting the allRoles parameter to false. That instructs the runtime to only return the SOAP headers that are applicable to the active SOAP roles.
If no headers are found, the method returns an empty array.
For more information about instantiating a JAXBContext object see Chapter 39, Using A JAXBContext Object.

Working with context properties

The SOAP message context passed into a logical handler is an instance of the application's message context and can access all of the properties stored in it. Handlers have access to properties at both the APPLICATION scope and the Handler scope.
Like the application's message context, the SOAP message context is a subclass of Java Map. To access the properties stored in the context, you use the get() method and put() method inherited from the Map interface.
By default, any properties you set in the context from inside a logical handler will be assigned a scope of HANDLER. If you want the application code to be able to access the property you need to use the context's setScope() method to explicitly set the property's scope to APPLICATION.
For more information on working with properties in the message context see Section 42.1, “Understanding Contexts”.

Determining the direction of the message

It is often important to know the direction a message is passing through the handler chain. For example, you would want to add headers to an outgoing message and strip headers from an incoming message.
The direction of the message is stored in the message context's outbound message property. You retrieve the outbound message property from the message context using the MessageContext.MESSAGE_OUTBOUND_PROPERTY key as shown in Example 43.11, “Getting the Message's Direction from the SOAP Message Context”.

Example 43.11. Getting the Message's Direction from the SOAP Message Context

Boolean outbound;
outbound = (Boolean)smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
The property is stored as a Boolean object. You can use the object's booleanValue() method to determine the property's value. If the property is set to true, the message is outbound. If the property is set to false the message is inbound.

Determining the return value

How the handleMessage() method completes its message processing has a direct impact on how message processing proceeds. It can complete by doing one of the following actions:
  1. return true—Returning true signals to the Apache CXF runtime that message processing should continue normally. The next handler, if any, has its handleMessage() invoked.
  2. return false—Returning false signals to the Apache CXF runtime that normal message processing is to stop. How the runtime proceeds depends on the message exchange pattern in use for the current message.
    For request-response message exchanges the following happens:
    1. The direction of message processing is reversed.
      For example, if a request is being processed by a service provider, the message will stop progressing toward the service's implementation object. It will instead be sent back towards the binding for return to the consumer that originated the request.
    2. Any message handlers that reside along the handler chain in the new processing direction have their handleMessage() method invoked in the order in which they reside in the chain.
    3. When the message reaches the end of the handler chain it is dispatched.
    For one-way message exchanges the following happens:
    1. Message processing stops.
    2. All previously invoked message handlers have their close() method invoked.
    3. The message is dispatched.
  3. throw a ProtocolException exception—Throwing a ProtocolException exception, or a subclass of this exception, signals the Apache CXF runtime that fault message processing is to start. How the runtime proceeds depends on the message exchange pattern in use for the current message.
    For request-response message exchanges the following happens:
    1. If the handler has not already created a fault message, the runtime wraps the message in a fault message.
    2. The direction of message processing is reversed.
      For example, if a request is being processed by a service provider, the message will stop progressing toward the service's implementation object. It will be sent back towards the binding for return to the consumer that originated the request.
    3. Any message handlers that reside along the handler chain in the new processing direction have their handleFault() method invoked in the order in which they reside in the chain.
    4. When the fault message reaches the end of the handler chain it is dispatched.
    For one-way message exchanges the following happens:
    1. If the handler has not already created a fault message, the runtime wraps the message in a fault message.
    2. Message processing stops.
    3. All previously invoked message handlers have their close() method invoked.
    4. The fault message is dispatched.
  4. throw any other runtime exception—Throwing a runtime exception other than a ProtocolException exception signals the Apache CXF runtime that message processing is to stop. All previously invoked message handlers have the close() method invoked and the exception is dispatched. If the message is part of a request-response message exchange the exception is dispatched so that it is returned to the consumer that originated the request.

Example

Example 43.12, “Handling a Message in a SOAP Handler” shows a handleMessage() implementation that prints the SOAP message to the screen.

Example 43.12. Handling a Message in a SOAP Handler

public boolean handleMessage(SOAPMessageContext smc)
{
  PrintStream out;

  Boolean outbound = (Boolean)smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY); 1

  if (outbound.booleanValue()) 2
  {
    out.println("\nOutbound message:");
  }
  else
  {
    out.println("\nInbound message:");
  }

  SOAPMessage message = smc.getMessage(); 3

  message.writeTo(out); 4
  out.println();

  return true;
}
The code in Example 43.12 does the following:
1
Retrieves the outbound property from the message context.
2
Tests the messages direction and prints the appropriate message.
3
Retrieves the SOAP message from the context.
4
Prints the message to the console.