I want to log raw soap post requests if there are any errors , I am using JAX-WS. Any help will be appreciated.
Is there an easy way (aka: not using a proxy) to get
In addition to Torsten's answer
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
Make sure that you set this before instantiating the WebServiceClient object (the one that extends Service)
Just thought I would mention this:
internal
in it and when not ?If you read the Metro Guide it will tell you to use:
on client:
com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
on server:
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
However: It seems to me that when JAX-WS RI library got included as standard with the JDK (this was with Java 6) then Sun had to rename the property name to include 'internal'. So if you are using JAX-WS RI as it comes bundled with the JDK, then you must be sure to add the internal
to the property name. Otherwise it will not work. In other words you need to use:
on client:
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
on server:
com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true
On the other hand if you are using a standalone version of JAX-WS RI (or of Metro as a whole) then I would guess you should use the property name without the internal
.
I'll be glad if someone has inside knowledge on this and can say if this is true or not.
The first thing you might want to try is using one, or both, of the following system properties:
Client:
com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
Server:
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
I think that what you need is an handler, see:
http://jax-ws.java.net/articles/handlers_introduction.html
With handler you can intercept web service call, and have access to all the SOAP message.
It is OK to go with system properties (here is Gradle DSL for test
task):
systemProperty "com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump", "true"
systemProperty "com.sun.xml.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.sun.xml.internal.ws.transport.http.HttpAdapter.dump", "true"
systemProperty "com.sun.xml.ws.transport.http.HttpAdapter.dumpTreshold", "99999"
systemProperty "com.sun.xml.internal.ws.transport.http.HttpAdapter.dumpTreshold", "99999"
but those settings are global and may have high volume to enable them on PROD... It is not fun to add filters to your logging framework bound to business logic if you want to reduce volume of XML logging.
Details on capturing req/rsp bodies in WS handlers are in my answer How can I pass data back from a SOAP handler to a webservice client?
Here is an important part:
public class MsgLogger implements SOAPHandler<SOAPMessageContext> {
public static String REQEST_BODY = "com.evil.request";
public static String RESPONSE_BODY = "com.evil.response";
@Override
public Set<QName> getHeaders() {
return null;
}
@Override
public boolean handleMessage(SOAPMessageContext context) {
SOAPMessage msg = context.getMessage();
Boolean beforeRequest = (Boolean) context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream(32_000);
context.getMessage().writeTo(baos);
String key = beforeRequest ? REQEST_BODY : RESPONSE_BODY;
context.put(key, baos.toString("UTF-8"));
context.setScope(key, MessageContext.Scope.APPLICATION);
} catch (SOAPException | IOException e) { }
return true;
}
@Override
public boolean handleFault(SOAPMessageContext context) {
return handleMessage(context);
}
@Override
public void close(MessageContext context) { }
}
To register handler and use preserved properties:
BindingProvider provider = (BindingProvider) port;
List<Handler> handlerChain = provider.getBinding().getHandlerChain();
handlerChain.add(new MsgLogger());
provider.getBinding().setHandlerChain(handlerChain);
Req req = ...;
Rsp rsp = port.serviceCall(req); // call WS Port
// Access saved message bodies:
Map<String, Object> responseContext = provider.getResponseContext();
String reqBody = (String) responseContext.get(MsgLogger.REQEST_BODY);
String rspBody = (String) responseContext.get(MsgLogger.RESPONSE_BODY);
With this solution (it is only the skeleton, proper error handling / edge cases is up to you) you decide to log later when you've got response.
This worked for me:
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true