发生错误时使用 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错误解析