Получение Raw XML из SOAPMessage в Java
Я установил SOAP WebServiceProvider в JAX-WS, но мне трудно понять, как получить необработанный XML из объекта SOAPMessage (или любого Node). Вот образец кода, который у меня есть сейчас, и где я пытаюсь захватить XML:
@WebServiceProvider(wsdlLocation="SoapService.wsdl")
@ServiceMode(value=Service.Mode.MESSAGE)
public class SoapProvider implements Provider<SOAPMessage>
{
public SOAPMessage invoke(SOAPMessage msg)
{
// How do I get the raw XML here?
}
}
Есть ли простой способ получить XML исходного запроса? Если есть способ получить необработанный XML, настроив другой тип провайдера (например, Source), я тоже захочу сделать это.
Ответы
Ответ 1
Оказывается, можно получить исходный XML, используя Provider <Source> следующим образом:
import java.io.ByteArrayOutputStream;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.Provider;
import javax.xml.ws.Service;
import javax.xml.ws.ServiceMode;
import javax.xml.ws.WebServiceProvider;
@ServiceMode(value=Service.Mode.PAYLOAD)
@WebServiceProvider()
public class SoapProvider implements Provider<Source>
{
public Source invoke(Source msg)
{
StreamResult sr = new StreamResult();
ByteArrayOutputStream out = new ByteArrayOutputStream();
sr.setOutputStream(out);
try {
Transformer trans = TransformerFactory.newInstance().newTransformer();
trans.transform(msg, sr);
// Use out to your heart desire.
}
catch (TransformerException e) {
e.printStackTrace();
}
return msg;
}
}
Мне не нужно это решение, поэтому я на самом деле не пробовал этот код сам - для его исправления может потребоваться некоторая настройка. Но я знаю, что это правильный путь, чтобы спуститься, чтобы получить необработанный XML из веб-службы.
(Я не уверен, как сделать эту работу, если у вас обязательно должен быть объект SOAPMessage, но опять же, если вы собираетесь обрабатывать необработанный XML в любом случае, зачем использовать объект более высокого уровня? )
Ответ 2
Вы можете попробовать таким образом.
SOAPMessage msg = messageContext.getMessage();
ByteArrayOutputStream out = new ByteArrayOutputStream();
msg.writeTo(out);
String strMsg = new String(out.toByteArray());
Ответ 3
Если у вас есть SOAPMessage
или SOAPMessageContext
, вы можете использовать Transformer
, переведя его в Source
через DOMSource
:
final SOAPMessage message = messageContext.getMessage();
final StringWriter sw = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(
new DOMSource(message.getSOAPPart()),
new StreamResult(sw));
} catch (TransformerException e) {
throw new RuntimeException(e);
}
// Now you have the XML as a String:
System.out.println(sw.toString());
Это учитывает кодировку, поэтому ваши "специальные символы" не будут искажены.
Ответ 4
только для цели отладки, используйте один код строки -
msg.writeTo(System.out);
Ответ 5
Если вам нужно форматировать строку xml в xml, попробуйте следующее:
String xmlStr = "your-xml-string";
Source xmlInput = new StreamSource(new StringReader(xmlStr));
Transformer transformer = TransformerFactory.newInstance().newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
transformer.transform(xmlInput,
new StreamResult(new FileOutputStream("response.xml")));
Ответ 6
Использование Transformer Factory: -
public static String printSoapMessage(final SOAPMessage soapMessage) throws TransformerFactoryConfigurationError,
TransformerConfigurationException, SOAPException, TransformerException
{
final TransformerFactory transformerFactory = TransformerFactory.newInstance();
final Transformer transformer = transformerFactory.newTransformer();
// Format it
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2");
final Source soapContent = soapMessage.getSOAPPart().getContent();
final ByteArrayOutputStream streamOut = new ByteArrayOutputStream();
final StreamResult result = new StreamResult(streamOut);
transformer.transform(soapContent, result);
return streamOut.toString();
}
Ответ 7
это работает
final StringWriter sw = new StringWriter();
try {
TransformerFactory.newInstance().newTransformer().transform(
new DOMSource(soapResponse.getSOAPPart()),
new StreamResult(sw));
} catch (TransformerException e) {
throw new RuntimeException(e);
}
System.out.println(sw.toString());
return sw.toString();
Ответ 8
если у вас есть код клиента, вам просто нужно добавить следующие две строки, чтобы получить запрос/ответ XML. Здесь _call
есть org.apache.axis.client.Call
String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString();
String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString();
Ответ 9
Это довольно старая тема, но недавно у меня была похожая проблема. Я звонил в нисходящую службу мыла из службы отдыха, и мне нужно было вернуть ответ xml, исходящий от нижестоящего сервера, как есть.
Итак, я добавил обработчик SoapMessageContext, чтобы получить XML-ответ. Затем я вставил ответ XML в контекст сервлета в качестве атрибута.
public boolean handleMessage(SOAPMessageContext context) {
// Get xml response
try {
ServletContext servletContext =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();
SOAPMessage msg = context.getMessage();
ByteArrayOutputStream out = new ByteArrayOutputStream();
msg.writeTo(out);
String strMsg = new String(out.toByteArray());
servletContext.setAttribute("responseXml", strMsg);
return true;
} catch (Exception e) {
return false;
}
}
Затем я получил строку ответа xml в слое сервиса.
ServletContext servletContext =
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();
String msg = (String) servletContext.getAttribute("responseXml");
У него еще не было возможности протестировать его, но этот подход должен быть потокобезопасным, поскольку он использует контекст сервлета.