Thursday, 5 June 2014

Logging in-bound and Out-bound SOAP messages in JAXWS WebServices

Logging in-bound and Out-bound SOAP messages in JAXWS WebServices

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;

Make sure in our JAX-WS Webservice we add handlerchain annotation.

@WebService
@HandlerChain(file = "handlerChain.xml")
@Stateless
public class MyService {
 private final Logger logger = MyServiceLoggingHandler.getLoggingHandler().getLogger();
 ...........
 }
 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Logging Handler for MyService.
 */
public class MyServiceLoggingHandler extends AbstractLoggingHandler {

 private static final MyServiceLoggingHandler loggingHandler = new MyServiceLoggingHandler();
 public static final Logger LOGGER = LoggerFactory.getLogger("MyService");

 @Override
 public Logger getLogger() {
  return LOGGER;
 }

 public static MyServiceLoggingHandler getLoggingHandler() {
  return loggingHandler;
 }
}

handlerChain.xml

<?xml version="1.0" encoding="UTF-8"?>
<handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
   <handler-chain>
      <handler>
         <handler-class>MyServiceLoggingHandler</handler-class>
      </handler>
   </handler-chain>
</handler-chains>


public abstract class AbstractLoggingHandler implements SOAPHandler<SOAPMessageContext> {

 private static final String INCOMING = "SoapMessage Incoming :";
 private static final String OUTGOING = "SoapMessage Outgoing :";
 private static final String ENCODING = "UTF-8";

 /**
  * Gets the logger for the logging handler.
  * @return the logger.
  */
 public abstract Logger getLogger();

 /**
  * Logs the in-bound and out-bound messages.
  * @param context the context.
  * @return always returns true.
  */
 @Override
 public boolean handleMessage(final SOAPMessageContext context) {
  return log(context);
 }

 /**
  * Logs the fault messages.
  * @param context the context.
  * @return always returns true.
  */
 @Override
 public boolean handleFault(final SOAPMessageContext context) {
  return log(context);
 }

 /**
  * Logs the message.
  * @param context the context.
  * @return always returns true.
  */
 private boolean log(final SOAPMessageContext context) {
  try {
         final SOAPMessage message = context.getMessage();
         final ByteArrayOutputStream stream = new ByteArrayOutputStream();
            message.writeTo(stream);
            final String xml = stream.toString(ENCODING);
            final boolean outboundProperty = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
            getLogger().info((outboundProperty ? OUTGOING : INCOMING) + xml);
        } catch (final Exception e) {
         getLogger().error("Error logging from SOAPMessageContext", e);
        }
  return true;
 }

 @Override
 public void close(final MessageContext context) {
  // No resources to close
 }

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

 /**
     * Handler method to log requests/response for third party calls.
     * @param clientBinding the client binding containing the existing handler chain.
     * @param abstractLoggingHandler the handler to add to the chain.
     * @return the clientBinding with the handler added.
     */
 public Binding configureLoggingHandler(final Binding clientBinding, final AbstractLoggingHandler abstractLoggingHandler) {
            @SuppressWarnings("rawtypes")
   final List<Handler> handlerList = clientBinding.getHandlerChain();
            handlerList.clear();
            handlerList.add(abstractLoggingHandler);
            clientBinding.setHandlerChain(handlerList);
            return clientBinding;
    }

}

1 comment: