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

Posted

技术标签:

【中文标题】发生错误时使用 JAX-WS 跟踪 XML 请求/响应【英文标题】:Tracing XML request/responses with JAX-WS when error occurs 【发布时间】:2011-07-18 01:17:15 【问题描述】:

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

是否有一种简单的方法(又名:不使用代理)仅在发生异常时才能访问使用 JAX-WS 参考实现(JDK 1.5 和更好的版本)发布的 Web 服务的原始请求/响应 XML作为回应?我想记录原始 SOAP reuest,以便以后可以通过任何 Web 服务客户端对其进行测试

【问题讨论】:

【参考方案1】:

可以使用系统属性(这里是 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"

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

在 WS 处理程序中捕获 req/rsp 主体的详细信息在我的回答 How can I pass data back from a SOAP handler to a webservice client?

这是一个重要的部分:

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)  

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

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);

有了这个解决方案(它只是一个框架,正确的错误处理/边缘情况由你决定)你决定稍后在你得到响应时记录。

【讨论】:

此答案基于 The Java API for XML-Based Web Services (JAX-WS) 2.3 规范,因此适用于任何 JAX WS 实现。【参考方案2】:

只是想我会提到这一点:

什么时候使用带有internal 的属性名称,什么时候不使用?

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

在客户端:

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

在服务器上:

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

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

在客户端:

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

在服务器上:

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

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

如果有人对此有内幕消息并能说出这是否属实,我会很高兴。

【讨论】:

【参考方案3】:

如果您使用 Jboss 6.1 并且想要将 JAX-WS 生成的类请求的日志打印到 SOAP Web 服务, 打开文件/home/oracle/jboss-eap-6.1/bin/standalone.sh 注意:请到你安装jboss的地方

你会发现这样的东西

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

改成如下图

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"

还要确保启用调试

DEBUG_MODE=true

【讨论】:

【参考方案4】:

这对我有用:

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

【讨论】:

【参考方案5】:

使用

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

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

相反(注意包名称中的“内部”),这对我有用。

干杯, 托斯滕

【讨论】:

更改了 catalina.sh 文件,包括“内部”但仍然看不到日志/catalina.yyyy-MM-dd.log 文件中的任何更改 .internal。当您使用 JRE 中包含的 JAX WS 版本时是必需的,而非“.internal”。当您明确使用 JAX WS 库时,使用版本 如何添加时间戳,特定请求到达服务器的时间以及服务器响应的时间?【参考方案6】:

除了托尔斯滕的回答

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

确保在实例化 WebServiceClient 对象(扩展服务的对象)之前设置此设置

【讨论】:

【参考方案7】:

我认为您需要的是一个处理程序,请参阅: http://jax-ws.java.net/articles/handlers_introduction.html 使用处理程序,您可以拦截 Web 服务调用,并可以访问所有 SOAP 消息。

【讨论】:

【参考方案8】:

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

客户:

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

服务器:

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

【讨论】:

我在我的tomcat服务器的catalina.properties文件中添加了以上属性,但是看不到任何更新的日志,请指教 在 JAVA_OPTS 上添加到我的 catalina.sh 但看不到任何更改 不要更改 catalina.properties。你如何设置JAVA_OPTS?日志应该通过System.out 输出。 以下是我的 catalina.sh 文件中的 JAVA_OPTS 行 JAVA_OPTS="-Dcom.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace = false -Djava.awt.headless=true -Dfile.encoding =UTF-8 -server -Xms512m -Xmx1024m -XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC -Dcom.sun.xml.ws.transport。 http.client.HttpTransportPipe.dump = true -Dcom.sun.xml.ws.transport.http.HttpAdapter.dump = true" ...logs/catalina.out 中没有显示任何内容?我想知道您使用的是什么 JDK 和 Tomcat 版本会很好......

以上是关于发生错误时使用 JAX-WS 跟踪 XML 请求/响应的主要内容,如果未能解决你的问题,请参考以下文章

没有 sun-jaxws.xml 的 Tomcat 上的 JAX-WS Web 服务

java使用POST发送soap报文请求webservice返回500错误解析

GDI+ 中发生一般性错误。 究竟是啥问题不是一般性的图片上传出错。

如何在 jax-ws 网络服务中解组 xml 文件

如何使用JAX-WS 2.0模拟soap响应?

签署 JAX-WS SOAP 请求