开发者

Tracing XML request/responses with JAX-WS when error occurs

I want to log raw soap post requests if there are any errors , I am using开发者_如何学JAVA JAX-WS. Any help will be appreciated.

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) only when exception occurs in response? I want to log raw SOAP reuest so that I can test it thorugh any webservice client at a later stage


Use

com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true

and

com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true

instead (note the "internal" in the package name), this did the trick for me.

Cheers, Torsten


Just thought I would mention this:

The question when to use the property name with the 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.


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.


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)


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


If you working with Jboss 6.1 and you want to print the logs for the JAX-WS generated classes request to the SOAP web service, open the file /home/oracle/jboss-eap-6.1/bin/standalone.sh note: please go where you have installed jboss

You will find something like this

JAVA_OPTS="$JAVA_OPTS -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"

Change it to the one shown below

JAVA_OPTS="$JAVA_OPTS -Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true -agentlib:jdwp=transport=dt_socket,address=$DEBUG_PORT,server=y,suspend=n"

Also make sure you enable debug

DEBUG_MODE=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.


This worked for me:

-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜