【发布时间】:2011-07-18 01:17:15
【问题描述】:
如果有任何错误,我想记录原始的肥皂发布请求,我正在使用 JAX-WS。任何帮助将不胜感激。
是否有一种简单的方法(又名:不使用代理)仅在发生异常时才能访问使用 JAX-WS 参考实现(JDK 1.5 和更好的版本)发布的 Web 服务的原始请求/响应 XML作为回应?我想记录原始 SOAP reuest,以便以后可以通过任何 Web 服务客户端对其进行测试
【问题讨论】:
如果有任何错误,我想记录原始的肥皂发布请求,我正在使用 JAX-WS。任何帮助将不胜感激。
是否有一种简单的方法(又名:不使用代理)仅在发生异常时才能访问使用 JAX-WS 参考实现(JDK 1.5 和更好的版本)发布的 Web 服务的原始请求/响应 XML作为回应?我想记录原始 SOAP reuest,以便以后可以通过任何 Web 服务客户端对其进行测试
【问题讨论】:
可以使用系统属性(这里是 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);
有了这个解决方案(它只是一个框架,正确的错误处理/边缘情况由你决定)你决定稍后在你得到响应时记录。
【讨论】:
只是想我会提到这一点:
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。
如果有人对此有内幕消息并能说出这是否属实,我会很高兴。
【讨论】:
如果您使用 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
【讨论】:
这对我有用:
-Dcom.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
【讨论】:
使用
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
和
com.sun.xml.internal.ws.transport.http.HttpAdapter.dump=true
相反(注意包名称中的“内部”),这对我有用。
干杯, 托斯滕
【讨论】:
除了托尔斯滕的回答
com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.dump=true
确保在实例化 WebServiceClient 对象(扩展服务的对象)之前设置此设置
【讨论】:
我认为您需要的是一个处理程序,请参阅:
http://jax-ws.java.net/articles/handlers_introduction.html
使用处理程序,您可以拦截 Web 服务调用,并可以访问所有 SOAP 消息。
【讨论】:
您可能想尝试的第一件事是使用以下系统属性中的一个或两个:
客户:
com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump=true
服务器:
com.sun.xml.ws.transport.http.HttpAdapter.dump=true
【讨论】:
JAVA_OPTS?日志应该通过System.out 输出。