如何从JAX-WS客户端获取XML响应主体?

时间:2013-05-20 15:01:47

标签: java xml jax-ws soaphandler

我在这里找到了一些关于如何从JAX-WS客户端检索XML响应的线程。在我的例子中,客户端是通过Oracle的JDeveloper产品从WSDL生成的,并将调用用.NET编写的Document / Literal服务端点。我想要做的是从调用客户端获取XML响应,而不是从处理程序内部获取。

我在这个问题上看到的最接近的主题是: http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml

我认为我不想生成Dispatch调用,因为端点的SOAP数据包的XML模式相当复杂,而自动代理使调用变得微不足道。除非有其他方法来填充生成的bean,然后调用一些简单生成XML的方法,然后我进行调用?

private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    SOAPMessage soapMessage = messageContext.getMessage();
    try {
        soapMessage.writeTo(baos);
        String responseXml = baos.toString();
        log.debug("Response: " + responseXml );
        PaymentGatewayXMLThreadLocal.set(responseXml);
    } catch (SOAPException e) {
        log.error("Unable to retrieve SOAP Response message.", e);
    } catch (IOException e) {
        log.error("Unable to retrieve SOAP Response message.", e);
    }
}

我的想法是在处理程序内的ThreadLocal中存储对调用的响应,然后在调用后读取它。这合理吗?因此,在处理程序在handleMessage和handleFault中执行上述代码之后,客户端调用代码将调用此方法:

@Override    
public String getSOAPResponseXML(Object clientstub) {
    String returnValue = PaymentGatewayXMLThreadLocal.get();
    return returnValue;
} // getSOAPResponseXML

看来可能还有另一种方式。阅读jax-ws-handlers后,我看到处理程序可以引入一个应用程序范围的变量。我改变了处理程序来执行此操作:

private void storeSOAPMessageXml(SOAPMessageContext messageContext) {
String xml = getSOAPMessageXml(messageContext);
// YourPayXMLThreadLocal.set(xml);
// put it into the messageContext as well, but change scope
// default of handler Scope, and client can't read it from responsecontext!
messageContext.put(SOAP_RESPONSE_XML, xml);
messageContext.setScope(SOAP_RESPONSE_XML, MessageContext.Scope.APPLICATION );
} // storeSOAPMessageXml

客户端只需读取它:

@Override    
public String getSOAPResponseXML(Object clientstub) {
    String returnValue = null;
    // works (assuming a threadlocal is ok)
    // returnValue = YourPayXMLThreadLocal.get();

    BindingProvider bindingProvider = (BindingProvider) clientstub;
    // Thought this would work, but it doesn't - it returns null.        
    // Map<String, Object> requestContext = bindingProvider.getRequestContext();
    // String returnValue = (String) requestContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);

    // this works!!
    Map<String, Object> responseContext = bindingProvider.getResponseContext();
    System.out.println("has key? " + responseContext.containsKey(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML));         
    returnValue = (String) responseContext.get(JaxWsClientResponseXmlHandler.SOAP_RESPONSE_XML);
    return returnValue;
} // getSOAPResponseXML

2 个答案:

答案 0 :(得分:0)

如果您只想查看请求,可以使用系统属性

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

如果你真的想一些请求,那么处理程序似乎是一个自然的解决方案。也许使用请求上下文将值传递给处理程序?在客户端:

((BindingProvider) port).getRequestContext().put("KEY", "VALUE");

在处理程序中:

String value = (String) messageContext.get("KEY");

答案 1 :(得分:0)

不幸的是,在发送XML之前获取XML并且不使用消息处理程序的唯一方法是自己编写它(参见JAXB)。这将为您提供数据的XML表示,但它可能与发送给WS的消息完全不同。使用命名空间的方式可能会出现差异等,但最重要的是,您不会获得整个SOAP信封,只会获得您选择编组的标头的XML数据。

相关问题