Pregunta

He creado un WebServiceProvider SOAP en JAX-WS, pero estoy teniendo problemas para averiguar cómo obtener el código XML sin procesar desde un SOAPMessage (o cualquier nodo) objeto. He aquí un ejemplo del código que tengo en este momento, y donde yo estoy tratando de agarrar 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?
    }
}

¿Hay una forma sencilla de obtener el código XML de la solicitud original? Si hay una manera de obtener el código XML sin procesar mediante el establecimiento de un tipo diferente de proveedor (como fuente), que estaría dispuesto a hacer eso, también.

¿Fue útil?

Solución 3

Resulta que uno puede obtener el código XML sin procesar mediante el uso de Proveedor , 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;
    }
}

he terminado no necesitar esta solución, así que en realidad no lo he probado este código a mí mismo - que podría necesitar algunos ajustes para hacerlo bien. Pero sé que este es el camino correcto a seguir para obtener el código XML sin procesar de un servicio web.

(no estoy seguro de cómo hacer este trabajo si es absolutamente necesario tener un objeto SOAPMessage, pero de nuevo, si usted va a estar manejando el XML sin procesar de todos modos, ¿para qué usar un objeto de nivel superior? )

Otros consejos

Usted podría tratar de esta manera.

SOAPMessage msg = messageContext.getMessage();
ByteArrayOutputStream out = new ByteArrayOutputStream();
msg.writeTo(out);
String strMsg = new String(out.toByteArray());

Si usted tiene un SOAPMessage o SOAPMessageContext, se puede utilizar un Transformer, mediante la conversión a un Source través 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());

Esto tomará la codificación en cuenta, por lo que sus "caracteres especiales" no conseguirán destrozado.

sólo por propósitos de depuración, utilice el código de una sola línea -

msg.writeTo(System.out);

Si necesita formatear la cadena XML a XML, intente lo siguiente:

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

El uso de fábrica de transformadores: -

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

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

si tiene el código de cliente a continuación, sólo tiene que añadir las dos líneas siguientes para obtener la solicitud XML / respuesta. Aquí se _call org.apache.axis.client.Call

String request = _call.getMessageContext().getRequestMessage().getSOAPPartAsString();
String response = _call.getMessageContext().getResponseMessage().getSOAPPartAsString();

Es bastante viejo hilo, pero recientemente he tenido un problema similar. Estaba llamando un servicio de jabón aguas abajo, desde un servicio de descanso, y que tenía que devolver la respuesta XML procedente del servidor indirecto como es.

Así, terminé la adición de un controlador SoapMessageContext para obtener la respuesta XML. Entonces i inyecta el xml respuesta en contexto 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;
            }
        }

A continuación, he recuperado la cadena de respuesta XML en la capa de servicio.

ServletContext servletContext =
                ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext();

        String msg = (String) servletContext.getAttribute("responseXml");

No tuvo oportunidad de probarlo todavía, pero este enfoque debe ser hilo de seguridad, ya que está utilizando el contexto de servlet.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top