Creating SOAP Message Handlers in 3 Simple Steps - Part 1
This tutorial takes a look at SOAP Message handlers and how easy it is to write handlers using JAX-WS 2.0. JAX-WS 2.0 allows both regular Java classes and stateless EJBs(Session beans) to be exposed as web services. The JAX-WS 2.0 is the core specification that defines the web services standard for Java EE 5 specification. JAX-WS 2.0 is an extension of the Java API for XML-RPC (JAX-RPC) 1.0.
SOAP message handlers are used to intercept the SOAP message as they make their way from the client to the end-point service and vice-versa. These handlers intercept the SOAP message for both the request and response of the Web Service. If you are familiar with EJB interceptors, handlers are similar to EJB interceptors and are defined in an XML file.
A few typical scenarios where you would be using SOAP Message handlers are: for encrypting and decrypting messages, to support logging, caching and in some cases auditing, and in rare cases to provide transaction management as well.
So much for the theory. Lets see the three basic steps to use a simple log handler to intercept and print our SOAP messages (request and response).
In this tutorial, we are going to expose an EJB 3 stateless session bean as a web service which is so simple and can be done by simply adding the @WebService annotation. So, here comes the source code for the interface as well as the implementation class which is self explanatory:
package com.ws;
import javax.ejb.Remote;
/**
*
* @author meerasubbarao
*/
@Remote
public interface HelloWebServiceRemote {
String sayHello(String name);
}
package com.ws;
import javax.ejb.Stateless;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
*
* @author meerasubbarao
*/
@WebService
@Stateless
public class HelloWebServiceBean implements HelloWebServiceRemote {
@WebMethod(operationName = "sayHello")
public String sayHello(@WebParam(name = "name") String name) {
return "Hello " + name;
}
}
You can package the two source files shown above into a jar, deploy to your application server, and test it as well. I am using GlassFish V2 and SoapUI to test my web services. So, shown below are the request and response from SoapUI:
Now that we know our web services work, lets start writing the message handler, which I said earlier is just 3 steps. So, what are these SOAP message handlers? They are simple Java classes that can easily modify SOAP messages; both request as well as response. These handlers have access to both the SOAP header as well as the body of the message.

Step 1. Implement the SOAPHandler interface.
package com.ws;
import java.io.IOException;
import java.util.Collections;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
/**
*
* @author meerasubbarao
*/
public class LogMessageHandler implements SOAPHandler<SOAPMessageContext> {
public boolean handleMessage(SOAPMessageContext messageContext) {
return true;
}
public Set<QName> getHeaders() {
return Collections.EMPTY_SET;
}
public boolean handleFault(SOAPMessageContext messageContext) {
return true;
}
public void close(MessageContext context) {
}
}
The handleMessage method is invoked for both incoming as well as outgoing messages. Lets add a new method called log() and invoke this method from the handleMessage method. Shown below are both the methods:
private void log(SOAPMessageContext messageContext) {
SOAPMessage msg = messageContext.getMessage(); //Line 1
try {
msg.writeTo(System.out); //Line 3
} catch (SOAPException ex) {
Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(LogMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
In line 1, we are retrieving the SOAPMessage from the message context. Line 3 will print the incoming and outgoing messages in our GlassFish console.
Invoke this method from within the handleMessage as shown:
public boolean handleMessage(SOAPMessageContext messageContext) {
log(messageContext);
return true;
}
Step 2: Create the XML file for the Handler Chain.
Create this XML file in the same package as the web service with the name LogMessage_handler.xml.
<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
<handler-chain>
<handler>
<handler-name>com.ws.LogMessageHandler</handler-name>
<handler-class>com.ws.LogMessageHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
So, let me explain about the various elements used above:
1. handler-chains is the root element that will contain a list of all handler chains that are defined for the Web Service.
2. The handler-chain child element of the handler-chains element lists all the handlers in the handler chain.
3. Within the handler-chain element is defined the handler, each handler element must in turn specify the name and also the fully qualified name of the Java class that implements the handler. If you have more than one handler, specify each one of them within the handler-chain element.
Step 3: Invoking the Handler
The @HandlerChain annotation is used to define a set of handlers that are invoked in response to a SOAP message. So, within our HelloWebServiceBean implementaion, you need to make a simple change to invoke the Log Handler as shown below:
package com.ws;
import javax.ejb.Stateless;
import javax.jws.HandlerChain;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
/**
*
* @author meerasubbarao
*/
@WebService
@Stateless
@HandlerChain(file = "LogMessage_handler.xml") // Line 1
public class HelloWebServiceBean implements HelloWebServiceRemote {
@WebMethod(operationName = "sayHello")
public String sayHello(@WebParam(name = "name") String name) {
return "Hello " + name;
}
}
Now, that we have added the annotation, recompile, package and deploy the application.
Lets invoke the web services and see if it works, if it did, we should be able to see the request and response logged in our GlassFish console window, right?
So, here comes the output:
**RemoteBusinessJndiName: com.ws.CustomerManagerRemote; remoteBusIntf: com.ws.CustomerManagerRemote
LDR5010: All ejb(s) of [EJBWebServices] loaded successfully!
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ws="http://ws.com/"><soapenv:Header/><soapenv:Body><ws:sayHello>
<name>Javalobby</name>
</ws:sayHello></soapenv:Body></soapenv:Envelope>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"><S:Body><ns2:sayHelloResponse xmlns:ns2="http://ws.com/"><return>Hello Javalobby</return></ns2:sayHelloResponse></S:Body></S:Envelope>
In this article, we saw how simple and easy it was to use SOAP Handlers to intercept request and response of SOAP messages. We implemented the SOAPHandler interface, wrote minimal XML to define the handler chain, and finally one simple annotation to the web service. We also were able to test these web service using SoapUI.
In Part 2 of this series, we will see how to actually parse the SOAP Headers, and also use multiple handlers.

August 29th, 2008 at 1:29 am
Hi there, This was a excellent example. Try it and it work. thanks heap. When will you guys be showing part 2 parse with soap headers.
August 29th, 2008 at 6:25 am
It will be posted soon.
September 10th, 2008 at 3:09 am
Hi Meera,
thank you so much for this neat and useful post.
I’m looking forward for the second part of your tutorial.
Do you think it would be a good idea using a Soap Handler to implement the authentication for a webservice (parsing the authentication parameters in the Soap header)?
September 10th, 2008 at 9:57 am
That’s one of the reasons why handlers are used.
October 6th, 2008 at 10:35 am
Hi Meera,
I have a question for you.
I used a SOAPHandler to implement the server-side authentication in a web service. I would like the client to receive a custom checked exception that is defined in the wsdl (the same thrown by the webservice methods), but I’m not able to generate it from the handleMessage method, since it can throw only unchecked exceptions (ProtocolException and RuntimeException). Since it’s the first time I’m using this technology I’m not sure which is the best practice in this case. I would really appreciate your advice.
Thanks in advance
November 20th, 2008 at 8:46 am
Dunia,
Don’t know if you had an answer to your question, but I was looking for a good pattern to throw an applicative exception from within my SOAP handler. This is what I did. Hope this helps!
Marwan
private SOAPFaultException createSOAPFaultException(String aFaultString, AutoClientCodeEnum aFaultCode) {
try {
SOAPFault fault = SOAPFactory.newInstance().createFault();
fault.setFaultString(aFaultCode.getErrorCode());
fault.setFaultCode(new QName(SOAPConstants.URI_NS_SOAP_ENVELOPE, “Server”));
LTPException ltpException = new LTPException();
ltpException.setErrorMessage(aFaultString);
ltpException.setErrorCode(aFaultCode.getErrorCode());
Detail detail = fault.addDetail();
Marshaller marshaller = sContext.createMarshaller();
marshaller.marshal(ltpException, detail);
return new SOAPFaultException(fault);
} catch (Exception e) {
throw new RuntimeException(”Error creating SOAP Fault message, faultString: ” + aFaultString);
}
}