LibraryLink ToToggle FramesPrintFeedback

Handling Messages in a Logical Handler

Normal message processing is handled by the handleMessage() method.

The handleMessage() method receives a LogicalMessageContext object that provides access to the message body and 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.

The LogicalMessageContext object passed into logical message handlers allows access to the message body using the context's getMessage() method. The getMessage() method, shown in Example 21.2, returns the message payload as a LogicalMessage object.


Once you have the LogicalMessage object, you can use it to manipulate the message body. The LogicalMessage interface, shown in Example 21.3, has getters and setters for working with the actual message body.


[Important]Important

The contents of the message payload are determined by the type of binding in use. The SOAP binding only allows access to the SOAP body of the message. The XML binding allows access to the entire message body.

One pair of getters and setters of the logical message work with the message payload as a javax.xml.transform.dom.DOMSource object.

The getPayload() method that has no parameters returns the message payload as a DOMSource object. The returned object is the actual message payload. Any changes made to the returned object change the message body immediately.

You can replace the body of the message with a DOMSource object using the setPayload() method that takes the single Source object.

The other pair of getters and setters allow you to work with the message payload as a JAXB object. They use a JAXBContext object to transform the message payload into JAXB objects.

To use the JAXB objects you do the following:

The logical 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 logical 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 message context from inside a logical handler are 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 Understanding Contexts.

It is often important to know the direction a message is passing through the handler chain. For example, you would want to retrieve a security token from incoming requests and attach a security token to an outgoing response.

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 21.6.


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.

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 FUSE Services Framework runtime that message processing should continue normally. The next handler, if any, has its handleMessage() invoked.

  2. Return false—Returning false signals to the FUSE Services Framework runtime that normal message processing must 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:

    For one-way message exchanges the following happens:

  3. Throw a ProtocolException exception—Throwing a ProtocolException exception, or a subclass of this exception, signals the FUSE Services Framework runtime that fault message processing is beginning. How the runtime proceeds depends on the message exchange pattern in use for the current message.

    For request-response message exchanges the following happens:

    For one-way message exchanges the following happens:

  4. Throw any other runtime exception—Throwing a runtime exception other than a ProtocolException exception signals the FUSE Services Framework 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 21.7 shows an implementation of handleMessage() message for a logical message handler that is used by a service consumer. It processes requests before they are sent to the service provider.

Example 21.7. Logical Message Handler Message Processing

public class SmallNumberHandler implements LogicalHandler<LogicalMessageContext>
{
    public final boolean handleMessage(LogicalMessageContext messageContext)
    {
        try
        {
            boolean outbound = (Boolean)messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

            if (outbound) 1
            {
                LogicalMessage msg = messageContext.getMessage(); 2

                JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class);
                Object payload = msg.getPayload(jaxbContext); 3
                if (payload instanceof JAXBElement)
                {
                    payload = ((JAXBElement)payload).getValue();
                }

                if (payload instanceof AddNumbers) 4
                {
                    AddNumbers req = (AddNumbers)payload;

                    int a = req.getArg0();
                    int b = req.getArg1();
                    int answer = a + b;

                    if (answer < 20) 5
                    {
                      AddNumbersResponse resp = new AddNumbersResponse(); 6
                      resp.setReturn(answer);
                      msg.setPayload(new ObjectFactory().createAddNumbersResponse(resp),
                                                      jaxbContext);

                      return false; 7
                    }
                }
                else
                {
                   throw new WebServiceException("Bad Request"); 8
                }
            }
            return true; 9
        }
        catch (JAXBException ex) 10
        {
            throw new ProtocolException(ex);
        }
    }
...
}

The code in Example 21.7 does the following:

1

Checks if the message is an outbound request.

If the message is an outbound request, the handler does additional message processing.

2

Gets the LogicalMessage representation of the message payload from the message context.

3

Gets the actual message payload as a JAXB object.

4

Checks to make sure the request is of the correct type.

If it is, the handler continues processing the message.

5

Checks the value of the sum.

If it is less than the threshold of 20 then it builds a response and returns it to the client.

6

Builds the response.

7

Returns false to stop message processing and return the response to the client.

8

Throws a runtime exception if the message is not of the correct type.

This exception is returned to the client.

9

Returns true if the message is an inbound response or the sum does not meet the threshold.

Message processing continues normally.

10

Throws a ProtocolException if a JAXB marshalling error is encountered.

The exception is passed back to the client after it is processed by the handleFault() method of the handlers between the current handler and the client.