Thursday, March 21, 2013

JAXWS Handler : Example for logging request / response SOAP packets

There are times when we want to see the request / response SOAP packets in our system console or log files. Instead of going for TCP monitor or other similiar tools, I though of writing a handler. The code below is quite popular and can be found in many other posts too.

Adding this handler is simple. Just pass the binding object of your Web Service client port into the static addToPort(...) method in this class.
package handler;

import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.Binding;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

public class SOAPRequestResponseSpitter implements SOAPHandler<SOAPMessageContext> {

 @Override
 public boolean handleMessage(SOAPMessageContext context) {
  logToSystemOut(context);
  return true;
 }

 @Override
 public boolean handleFault(SOAPMessageContext context) {
  logToSystemOut(context);
  return true;
 }

 private void logToSystemOut(SOAPMessageContext smc) {
  Boolean outboundProperty = (Boolean) smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

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

  SOAPMessage message = smc.getMessage();
  try {
       ByteArrayOutputStream baos = new ByteArrayOutputStream();
       message.writeTo(baos);
       System.out.println(baos.toString());
  } catch (Exception e) {
   System.out.println("Exception in handler: " + e);
  }
 }

 @Override
 public void close(MessageContext context) {
 }

 @Override
 public Set<QName> getHeaders() {
  return Collections.emptySet();
 }

 @SuppressWarnings("rawtypes")
 /**
  * This static method adds the handler to the provided port's binding object. 
  * 
  * @param binding - The binding object can be fetched by <code>((BindingProvider) port).getBinding()</code>
  */
 public static void addToPort(Binding binding) {
  List<Handler> handlerChain = binding.getHandlerChain();
  handlerChain.add(new SOAPRequestResponseSpitter());

  /*
   * Check List<Handler> javax.xml.ws.Binding.getHandlerChain() javadocs.
   * It states: Gets a copy of the handler chain for a protocol binding
   * instance. If the returned chain is modified a call to setHandlerChain
   * is required to configure the binding instance with the new chain.
   */
  binding.setHandlerChain(handlerChain);
 }
}


To inject this handler into the port using Spring, please refer to my other post JAXWS Handler injection using Spring

The handler gives you much control on how you want to log the packets. If you don't want to write a handler and just want to see the packets without making any changes to the application, you can use the below mentioned JVM argument in your server startup script and all the web service related tcp communication will be printed on the console.
  -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true

No comments:

Post a Comment