有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

发生错误时使用JAXWS跟踪XML请求/响应

我想记录原始soap post请求,如果有任何错误,我将使用JAX-WS。任何帮助都将不胜感激

只有在响应中发生异常时,才有一种简单的方法(aka:不使用代理)来访问使用JAX-WS参考实现(JDK1.5和更好版本中包含的)发布的Web服务的原始请求/响应XML吗?我想记录原始SOAP reuest,以便在以后的阶段可以通过任何Web服务客户端对其进行测试


共 (6) 个答案

  1. # 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"
    

    但这些设置是全局性的,可能会有很大的容量,以便在生产中使用。。。如果想要减少XML日志记录的数量,那么在绑定到业务逻辑的日志框架中添加过滤器并不是件有趣的事

    有关在WS-Handler中捕获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);
    

    有了这个解决方案(它只是一个框架,正确的错误处理/边缘情况取决于您),您可以在收到响应后决定登录

  2. # 2 楼答案

    除了托尔斯滕的回答

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

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

  3. # 3 楼答案

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

    客户:

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

    服务器:

    com.sun.xml.ws.transport.http.HttpAdapter.dump=true
    
  4. # 4 楼答案

    如果您使用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
    
  5. # 5 楼答案

    使用

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

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

    相反(注意包名中的“internal”),这为我带来了好处

    干杯, 托尔斯滕

  6. # 6 楼答案

    我只是想提一下:

    问题是什么时候使用带有internal的属性名,什么时候不使用

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

    在客户端:

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

    在服务器上:

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

    然而:在我看来,当JAX-WSRI库作为JDK的标准包含(这是Java6的标准)时,Sun不得不将属性名称重命名为包含“internal”。因此,如果您使用的是与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作为一个整体),那么我猜您应该使用属性名,而不使用^{

    如果有人知道这件事,并且能说出这是真是假,我会很高兴的