Как получить тело ответа XML от клиента JAX-WS?

Здесь я прочитал несколько потоков о том, как получить XML-ответ от клиента JAX-WS. В моем случае клиент генерируется из WSDL через продукт Oracle JDeveloper и собирается вызвать конечную точку службы Document/Literal, которая была написана на.NET. То, что я хочу сделать, это получить ответ XML от вызова ОТ вызывающего клиента, а не из обработчика.

Самая близкая нить, которую я видел к этой проблеме, была: http://www.coderanch.com/t/453537/Web-Services/java/capture-SoapRequest-xml-SoapResponse-xml

Я не думаю, что хочу генерировать вызов Dispatch, потому что XML-схема конечной точки для пакета SOAP довольно сложна, и автоматический прокси-сервер делает этот вызов тривиальным. Разве есть какой-то другой способ заполнить сгенерированный компонент (ы) и затем вызвать некоторый метод, который просто производит 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 ответа

Если вы просто хотите увидеть запрос, вы можете использовать системное свойство

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

Если вы действительно хотите что- то сделать с запросом, то обработчик кажется естественным решением. Возможно, использовать контекст запроса для передачи значений в обработчик? На клиенте:

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

В обработчике:

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

К сожалению, единственный способ получить XML перед отправкой и без использования обработчиков сообщений - это маршалировать его самостоятельно (см. JAXB). Это даст вам представление данных в формате XML, однако оно может выглядеть не так, как сообщение, отправленное на WS. Различия могут возникнуть в том, как используются пространства имен, и т. Д., Но самое главное, вы не получите весь конверт SOAP, а только данные XML для заголовка, который вы выбрали для маршала.

Другие вопросы по тегам