3

I've found a read a number of threads on here about how to retrieve the XML response from a JAX-WS client. In my case, the client is generated from the WSDL via Oracle's JDeveloper product and is going to invoke a Document/Literal service endpoint that was written in .NET. What I want to do is obtain the XML response from the call FROM the calling client, not from inside a handler.

The closest thread that I saw to this issue was: http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml

I don't think I want to generate a Dispatch call because the endpoint's XML schema for the SOAP packet is rather complex, and the automatic proxy makes the call trivial. Unless there is some other way to populate the generated bean(s) and then invoke some method that simply produces the XML and I then make the call?

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

My thought was to store the response to the call in a ThreadLocal inside the handler and then read it after the call. Is that reasonable? So after the handler does the above code in the handleMessage and handleFault, the client calling code invokes this method:

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

It appears there may be another way after all. After reading jax-ws-handlers, I saw that the handler can introduce an Application scoped variable. I changed the handler to do this:

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

The client just reads it like this:

@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
4

2 回答 2

1

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

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

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

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

在处理程序中:

String value = (String) messageContext.get("KEY");
于 2013-05-20T15:15:45.380 回答
0

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

于 2013-05-21T07:01:09.530 回答