views:

884

answers:

5

Is there an easy way (aka: not using a proxy) to get access to the raw request/response XML for a webservice published with JAX-WS reference implementation (the one included in JDK 1.5 and better) ? Being able to do that via code is what I need to do. Just having it logged to a file by clever logging configurations would be nice but enough.

I know that other more complex and complete frameworks exist that might do that, but I would like to keep it as simple as possible and axis, cxf, etc all add considerable overhead that I want to avoid.

Thanks!

A: 

You could try to put a ServletFilter in front of the webservice and inspect request and response going to / returned from the service.

Although you specifically did not ask for a proxy, sometimes I find tcptrace is enough to see what goes on on a connection. It's a simple tool, no install, it does show the data streams and can write to file too.

rsp
A: 

One way to do is not using your code but use network packet sniffers like Etheral or WireShark which can capture the HTTP packet with the XML message as payload to it and you can keep logging them to a file or so.

But more sophisticated approach is to write your own message handlers. You can have a look at it here.

Shamik
A: 

You need to implement a javax.xml.ws.handler.LogicalHandler, this handler then needs to be referenced in a handler configuration file, which in turn is referenced by an @HandlerChain annotation in your service endpoint (interface or implementation). You can then either output the message via system.out or a logger in your processMessage implementation.

See

http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/twbs_jaxwshandler.html

http://java.sun.com/mailers/techtips/enterprise/2006/TechTips_June06.html

stjohnroe
A: 

Here is the solution in raw code (put together thanks to stjohnroe and Shamik):

Endpoint ep = Endpoint.publish("http://my.server.com/mywebservice/", new WebserviceImpl());
ep.getBinding().getHandlerChain().add(new SOAPLoggingHandler());

Where SOAPLoggingHandler is (ripped from linked examples):

package com.myfirm.util.logging.ws;

import java.io.PrintStream;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;
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;

/*
 * This simple SOAPHandler will output the contents of incoming
 * and outgoing messages.
 */
public class SOAPLoggingHandler implements SOAPHandler<SOAPMessageContext> {

    // change this to redirect output if desired
    private static PrintStream out = System.out;

    public Set<QName> getHeaders() {
        return null;
    }

    public boolean handleMessage(SOAPMessageContext smc) {
        logToSystemOut(smc);
        return true;
    }

    public boolean handleFault(SOAPMessageContext smc) {
        logToSystemOut(smc);
        return true;
    }

    // nothing to clean up
    public void close(MessageContext messageContext) {
    }

    /*
     * Check the MESSAGE_OUTBOUND_PROPERTY in the context
     * to see if this is an outgoing or incoming message.
     * Write a brief message to the print stream and
     * output the message. The writeTo() method can throw
     * SOAPException or IOException
     */
    private void logToSystemOut(SOAPMessageContext smc) {
        Boolean outboundProperty = (Boolean)
            smc.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);

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

        SOAPMessage message = smc.getMessage();
        try {
            message.writeTo(out);
            out.println("");   // just to add a newline
        } catch (Exception e) {
            out.println("Exception in handler: " + e);
        }
    }
}
Antonio
+1  A: 

There are various ways of doing this programmatically, as described in the other answers, but they're quite invasive mechanisms. However, if you know that you're using the JAX-WS RI (aka "Metro"), then you can do this at the configuration level. See here for instructions on how to do this. No need to mess about with your application.

skaffman
Metro = JAX-WS RI + WSIT (i.e. JAX-WS RI != Metro)
Pascal Thivent
@Pascal: I stand corrected :)
skaffman