Как получить тело ответа 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 для заголовка, который вы выбрали для маршала.