Thursday, August 8, 2013

Logging SOAP Requests in WEF

Some of my projects make extensive use of the web service call builder and I often need to look at the outgoing SOAP requests when a problem crops up. This is easy by turning on logging in the advanced section of the builder, but doing this on every instance of the builder is tedious.


JAX-WS SOAP Handler
I stumbled on this article where Rob Flynn describes a technique to handle SOAP requests from a central point using the bowstreet.serviceCall.jaxwsHandler override. I used this approach to add some log4j logging statements, this way I don't have to go into each builder and tweak the input and redeploy, I can just change the log4j.properties. Unbelievably, a google search shows that there are no other references to this override - not even in IBM's documentation. I have to wonder how many other awesome WEF features lay undocumented (ask me about pageprocessors.properties).

public class SoapHandler extends BaseJaxWsHandler {

    static Logger logger = Logger.getLogger(SoapHandler.class);
    
    /* 
     * Populate the user's identity into the SOAP request.
     */
    public boolean handleOutboundMessage(SOAPMessageContext context) {
        // bail if logging not enabled  
        if (!logger.isInfoEnabled())
            return;
         logMessage(context);
        
        return true;
    }
    
    
    /**
     * Log the SOAP message.
     * @param context
     */
    private void logMessage(SOAPMessageContext context) {

        // bail if logging not enabled  
        if (!logger.isInfoEnabled())
            return;
        
        try {
            HashMap hm = (HashMap) context.get(com.ibm.websphere.webservices.Constants.REQUEST_TRANSPORT_PROPERTIES);
            Set keys = hm.keySet();
            
            logger.info(">> Start SOAP message log");
            logger.info("calling Model=" + getWebappAccess().getModelName());
            logger.info(this.getEndPointUrl(context));

            for (Object key : keys){
                logger.info("HTTP header -> " + key + "=" + hm.get(key));
            }
            
            logger.info(context.getMessage().getSOAPPart().getEnvelope());
            logger.info(">> End SOAP message log\n");
        } catch (SOAPException e) {
            // we're just logging, not sure we care that an exception is thrown
        }
    }


}

The parent class BaseJaxWsHandler can be found on Rob's entry mentioned above.