Need to see SOAP messages for client talking to external web service - how to? (Eclipse/Netbeans/IDEA ok)

StackOverflow https://stackoverflow.com/questions/2221488

Question

I have a situation where I have to write a client in Java against a very picky external web service (over https) and I can talk to the web service through the Web Services Explorer in Eclipse Java EE.

Unfortunately I cannot get the client to ask properly so I'd really like to see the SOAP messages going back and forth. Being new to web services this is a bit of a jungle. I am very familiar with Eclipse, and have spent some time with Netbeans and IntelliJ.

I'd really, really prefer using the Metro stack as it allows this to run on a stock Java 6, and deployment size matters. Is there a simple way to make Metro log what it does, or make it talk through the TCP/IP monitors in Eclipse and Netbeans? The Metro documentation seems to be primarily targeted at the web service author and not the client, so I might easily have missed it.

Any suggestions for a setup saying "Here is the WSDL - generate me a client where I can see the traffic"?

Was it helpful?

Solution 3

It was helpful to turn on logging with

-Dcom.sun.xml.ws.assembler.client=true

in the Eclipse launch configuration.

OTHER TIPS

Just put a proxy or a tcp monitor "in the middle" and you will see the message.

I've been using tcpmon for a similar task.

Here is another way to observe SOAP messages:

Supposing generated client classes looks like:

// generated service class
public class MyWebServiceClient extends javax.xml.ws.Service {
    // ...
    private final QName portName = "...";
    // ...
    public RetrieveMyObjects getRetrieveMyObjects() {
        return super.getPort(portName, RetrieveMyObject.class);
    }
    // ...
}

// generated port interface
// annotations here
public interface RetrieveMyObjects {

    // annotations here
    List<MyObject> getAll();

}

Now, upon executing following code:

MyWebServiceClient wsClient = new MyWebServiceClient("wsdl/location/url/here.wsdl");
RetrieveMyObjectsPort retrieveMyObjectsPort = wsClient.getRetrieveMyObjects();

wsClient should return instance which is both instance of RetrieveMyObjects & javax.xml.ws.BindingProvider interfaces. It is not stated anywhere on the surface of JAX-WS, but it seems that a lot of code is based on that fact. One can re-assure him\herself by executing something like:

if(!(retrieveMyObjectsPort instanceof javax.xml.ws.BindingProvider)) {
    throw new RuntimeException("retrieveMyObjectsPort is not instance of " + BindingProvider.class + ". Redirect following as well as authentication is not possible");
}

Now, when we are sure that retrieveMyObjectsPort is instance of javax.xml.ws.BindingProvider we can enable SOAPMessage logging by invoking following method on each desired web service port interface:

/**
 * Enables logging of send and received SOAP messages on the specified {@link BindingProvider}s
 */
private static void enableSoapMessageLogging(final Logger logger, final BindingProvider... bindingProviders) {
    for(final BindingProvider bindingProvider : bindingProviders) {
        final List<Handler> handlerChain = bindingProvider.getBinding().getHandlerChain();
        handlerChain.add(new SOAPHandler<SOAPMessageContext>() {
            @Override
            public boolean handleMessage(final SOAPMessageContext context) {
                try {
                    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    context.getMessage().writeTo(baos);
                    logger.trace(new String(baos.toByteArray()));
                } catch(final Exception e) {
                    logger.error("", e);
                }
                return true;
            }

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

            @Override
            public void close(final MessageContext context) {
            }

            @Override
            public Set<QName> getHeaders() {
                return null;
            }
        });
        bindingProvider.getBinding().setHandlerChain(handlerChain);
    }
}

// and somewhere at the beginning of application ...
enableSoapMessageLogging(logger, (BindingProvider) retrieveMyObjectsPort);

Hope this helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top