发生错误时使用JAX-WS跟踪XML请求/响应

use*_*837 24 java jax-ws

如果有任何错误,我想记录原始肥皂邮件请求,我正在使用JAX-WS.任何帮助将不胜感激.

只有在响应中发生异常时,是否有一种简单的方法(也就是说:不使用代理)来访问使用JAX-WS参考实现(JDK 1.5中包含的那个)更好的Web服务的原始请求/响应XML?我想记录原始的SOAP reuest,以便我可以在以后的任何webservice客户端测试它

小智 32

使用

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

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

相反(注意包名称中的"内部"),这对我来说很有用.

干杯,托斯滕


pet*_*erh 27

我想我会提到这个:

何时使用属性名称internal和何时使用属性名称的问题?

如果您阅读Metro指南,它会告诉您使用:

在客户端:

com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
Run Code Online (Sandbox Code Playgroud)

在服务器上:

com.sun.xml.ws.transport.http.HttpAdapter.dump=true
Run Code Online (Sandbox Code Playgroud)

但是:在我看来,当JAX-WS RI库作为标准包含在JDK中时(这是Java 6),Sun必须将属性名称重命名为包含"internal".因此,如果您使用JAX-WS RI,因为它与JDK捆绑在一起,那么您必须确保将其添加internal到属性名称.否则它将无法工作.换句话说,你需要使用:

在客户端:

com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
Run Code Online (Sandbox Code Playgroud)

在服务器上:

com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您使用的是独立版本的JAX-WS RI(或整个Metro),那么我猜你应该使用没有的属性名称internal.

如果有人对此有内在的知识并且可以说这是否属实,我会很高兴.


gav*_*koa 6

可以使用系统属性(这里是用于test任务的Gradle DSL ):

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"
Run Code Online (Sandbox Code Playgroud)

但是这些设置是全局的,并且可能有大量的内容可以在 PROD 上启用它们...如果您想减少 XML 日志记录的数量,那么向绑定到业务逻辑的日志记录框架添加过滤器并不有趣。

在 WS 处理程序中捕获 req/rsp 主体的详细信息在我的回答中如何将数据从 SOAP 处理程序传递回 Web 服务客户端?

这是一个重要的部分:

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) { }
}
Run Code Online (Sandbox Code Playgroud)

要注册处理程序并使用保留的属性:

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);
Run Code Online (Sandbox Code Playgroud)

使用此解决方案(这只是框架,正确的错误处理/边缘情况取决于您),您决定稍后在收到响应时记录。


ksc*_*eid 3

您可能想要尝试的第一件事是使用以下系统属性中的一个或两个:

客户:

com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
Run Code Online (Sandbox Code Playgroud)

服务器:

com.sun.xml.ws.transport.http.HttpAdapter.dump=true
Run Code Online (Sandbox Code Playgroud)