JAX-WS: Capturing SOAP messages at the client side



One of the usual steps involved in the debugging of Web Services applications is to inspect the request and response SOAP messages. An easy way to do this is to use a proxy that sits between the client and the server. tcpmon, the TCP connection monitoring tool is the one that I use.

However, in certain situations, you may want to capture and log the SOAP message within the client process itself. Recently I had to deal with such a requirement for JAX-WS 2.0 and it turned out that it was quite easy to do this using the Handler framework. I added a logging handler to capture the request and response messages. The code snippet is given below.


import javax.xml.ws.BindingProvider;
import javax.xml.ws.Binding;
....
TestServicePortType proxy = new TestService().getTestServicePort();
BindingProvider bp = (BindingProvider) proxy;
bp.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, urlStr);
Binding binding = bp.getBinding();

// Add the logging handler
List handlerList = binding.getHandlerChain();
if (handlerList == null)
   handlerList = new ArrayList();
LoggingHandler loggingHandler = new LoggingHandler(...);
handlerList.add(loggingHandler);
binding.setHandlerChain(handlerList);

....

// Invoking a method will activate the handler.
proxy.someMethod(...);

....

// Remove the logging handler if done with it.
List handlerList = binding.getHandlerChain();
if (handlerList != null && loggingHandler != null)
   handlerList.remove(loggingHandler);


public class LoggingHandler implements SOAPHandler<SOAPMessageContext> {

// Initialize OtputStream (fos) etc. ...

public boolean handleMessage (SOAPMessageContext c) {
   SOAPMessage msg = c.getMessage();

   boolean request = ((Boolean) c.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();

   try {
      if (request) { // This is a request message.
         // Write the message to the output stream
         msg.writeTo (fos);
      }
      else { // This is the response message
         msg.writeTo (fos);
      }
   }
   catch (Exception e) { ... }
   return true;
}

public boolean handleFault (SOAPMessageContext c) {
   SOAPMessage msg = c.getMessage();
   try {
      msg.writeTo (fos);
   }
   catch (Exception e) {...}
   return true;
}

public void close (MessageContext c) {
   ...
}

public Set getHeaders() {
   // Not required for logging
   return null;
}
}



There is another implementation specific way of doing this - using the _setTransportFactory method. The handler approach is the more preferable option since it does not have any implementation dependencies.
Comments:

Post a Comment:
Comments are closed for this entry.
About

binu

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today