He configurado un SOAP WebServiceProvider en JAX-WS, pero tengo problemas para averiguar cómo obtener el XML sin formato de un objeto SOAPMessage (o cualquier nodo). Aquí hay una muestra del código que tengo ahora, y donde estoy tratando de obtener el 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?
}
}
¿Existe una forma sencilla de obtener el XML de la solicitud original? Si hay una forma de obtener el XML sin procesar configurando un tipo diferente de proveedor (como Fuente), también estaría dispuesto a hacerlo.
Si tiene una
SOAPMessage
oSOAPMessageContext
, puede usar unaTransformer
, convirtiéndola en unaSource
víaDOMSource
: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());
Esto tendrá en cuenta la codificación, por lo que sus "caracteres especiales" no se estropearán.
fuente
Resulta que uno puede obtener el XML sin formato utilizando Provider <Source>, de esta manera:
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's desire. } catch (TransformerException e) { e.printStackTrace(); } return msg; } }
Terminé sin necesitar esta solución, por lo que en realidad no he probado este código; es posible que necesite algunos ajustes para hacerlo bien. Pero sé que este es el camino correcto para obtener el XML sin formato de un servicio web.
(No estoy seguro de cómo hacer que esto funcione si absolutamente debe tener un objeto SOAPMessage, pero, de nuevo, si va a manejar el XML sin formato de todos modos, ¿por qué usaría un objeto de nivel superior?)
fuente
StringWriter
es una buena alternativa alByteArrayOutputStream
+StreamResult
combinación, si desea que el XML comoString
con la codificación correctasolo para fines de depuración, use un código de línea:
msg.writeTo(System.out);
fuente
ByteArrayOutputStream
convertido aString
... me parece fácilSi necesita formatear la cadena xml a xml, intente esto:
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")));
fuente
Usando 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(); }
fuente
esto funciona
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();
fuente
si tiene el código de cliente, solo necesita agregar las siguientes dos líneas para obtener la solicitud / respuesta XML. Aqui
_call
estaorg.apache.axis.client.Call
fuente
Es un hilo bastante antiguo, pero recientemente tuve un problema similar. Estaba llamando a un servicio de jabón en sentido descendente, desde un servicio de descanso, y necesitaba devolver la respuesta xml procedente del servidor en sentido descendente como está.
Entonces, terminé agregando un controlador SoapMessageContext para obtener la respuesta XML. Luego inyecté la respuesta xml en el contexto del servlet como un atributo.
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; } }
Luego recuperé la cadena de respuesta xml en la capa de servicio.
ServletContext servletContext = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext(); String msg = (String) servletContext.getAttribute("responseXml");
Todavía no tuve la oportunidad de probarlo, pero este enfoque debe ser seguro para subprocesos, ya que utiliza el contexto del servlet.
fuente