Pergunta

Eu configurei um WebServiceProvider SOAP no JAX-WS, mas eu estou tendo dificuldade para descobrir como obter o XML cru de um SOAPMessage (ou qualquer Node) objeto. Aqui está um exemplo do código que eu tenho agora, e onde eu estou tentando agarrar o 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 uma maneira simples para obter o XML do pedido original? Se há uma maneira de obter o XML bruto através da criação de um tipo diferente de Provider (como o Source), eu estaria disposto a fazer isso também.

Foi útil?

Solução 3

Acontece que se pode obter o XML bruto usando o provedor , da seguinte maneira:

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

Eu acabei não necessitando esta solução, então eu não tentei realmente este código eu mesmo - que pode precisar de alguns ajustes para obter direito. Mas eu sei que este é o caminho certo para ir para baixo para obter o XML bruto de um serviço web.

(não tenho certeza de como fazer este trabalho se você absolutamente deve ter um objeto SOAPMessage, mas, novamente, se você estiver indo para lidar com o XML bruto de qualquer maneira, por que você iria usar um objeto de nível superior? )

Outras dicas

Você poderia tentar desta forma.

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

Se você tem um SOAPMessage ou SOAPMessageContext, você pode usar um Transformer, convertendo-a em um 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());

Isso levará a codificação em conta, para que seus "caracteres especiais" não vai ficar mutilado.

apenas para fins de depuração, use um código de linha -

msg.writeTo(System.out);

Se você precisa formatar a cadeia de caracteres XML para XML, tente o seguinte:

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

Usando Transformer fábrica: -

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

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

Se você tem o código do cliente, então você só precisa adicionar as duas linhas seguintes para obter a solicitação XML / resposta. Aqui _call é org.apache.axis.client.Call

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

É rosca belos antiga, mas recentemente tive um problema semelhante. Eu estava chamando um serviço de sabão a jusante, a partir de um serviço de descanso, e eu precisava retornar a resposta xml vindo do servidor downstream como é.

Então, eu acabei adicionando um manipulador SoapMessageContext para obter a resposta XML. Em seguida, injectado i o xml resposta em contexto servlet como um 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;
            }
        }

Então eu ter recuperado a cadeia de resposta XML na camada de serviço.

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

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

Não teve oportunidade de testá-lo ainda, mas esta abordagem deve ser thread-safe, uma vez que está usando o contexto servlet.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top