web-dev-qa-db-fra.com

Obtenir du XML brut à partir de SOAPMessage en Java

J'ai configuré un SOAP WebServiceProvider dans JAX-WS, mais je ne parviens pas à comprendre comment obtenir le XML brut à partir d'un objet SOAPMessage (ou de n'importe quel nœud). Voici un exemple du code que j'ai en ce moment, et où j'essaie de récupérer le 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-t-il un moyen simple d’obtenir le code XML de la demande initiale? S'il existe un moyen d'obtenir le code XML brut en configurant un type de fournisseur différent (tel que Source), je serais prêt à le faire également.

67
Daniel Lew

Il s'avère que l'on peut obtenir le XML brut en utilisant Fournisseur <Source>, de la manière suivante:

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

En fin de compte, je n'ai plus besoin de cette solution. Je n'ai donc pas essayé ce code moi-même. Il faudra peut-être un peu de peaufinage pour réussir. Mais je sais que c’est le bon chemin à suivre pour obtenir le code XML brut d’un service Web.

(Je ne sais pas comment faire pour que cela fonctionne si vous devez absolument disposer d'un objet SOAPMessage, mais encore une fois, si vous allez gérer le XML brut de toute façon, pourquoi utiliseriez-vous un objet de niveau supérieur?)

11
Daniel Lew

Vous pouvez essayer de cette façon.

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

Si vous avez SOAPMessage ou SOAPMessageContext, vous pouvez utiliser un Transformer en le convertissant en Source via 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());

Cela tiendra compte de l’encodage afin que vos "caractères spéciaux" ne soient pas mutilés.

18
artbristol

Si vous avez besoin de formater la chaîne XML en XML, essayez ceci:

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
Hari

Utilisation de 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();
    }
4
Sireesh Yarlagadda

cela marche

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

C'est assez vieux fil mais récemment j'ai eu un problème similaire. J'appelais un service soap en aval, à partir d'un service de repos, et je devais renvoyer la réponse XML provenant du serveur en aval telle quelle.

Donc, j'ai fini par ajouter un gestionnaire SoapMessageContext pour obtenir la réponse XML. Ensuite, j’ai injecté la réponse XML dans un contexte de servlet en tant qu’attribut.

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

Ensuite, j'ai récupéré la chaîne de réponse XML dans la couche de service.

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

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

Nous n'avons pas encore eu l'occasion de le tester, mais cette approche doit être thread-safe car elle utilise le contexte de servlet.

0
Oguz Demir

si vous avez le code client, il vous suffit d'ajouter les deux lignes suivantes pour obtenir la requête/réponse XML. Ici _call est org.Apache.axis.client.Call

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