Получение необработанного XML из SOAPMessage в Java

StackOverflow https://stackoverflow.com/questions/522395

  •  22-08-2019
  •  | 
  •  

Вопрос

Я настроил SOAP WebServiceProvider в JAX-WS, но не могу понять, как получить необработанный XML из объекта SOAPMessage (или любого узла).Вот пример кода, который у меня есть сейчас, и где я пытаюсь получить 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, настроив другой тип поставщика (например, источник), я бы тоже это сделал.

Это было полезно?

Решение 3

Оказывается, можно получить необработанный 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's desire.
        }
        catch (TransformerException e) {
            e.printStackTrace();
        }    

        return msg;
    }
}

В конечном итоге мне не понадобилось это решение, поэтому я сам не пробовал этот код — возможно, для его правильной настройки может потребоваться некоторая настройка.Но я знаю, что это правильный путь, чтобы получить необработанный XML из веб-сервиса.

(Я не уверен, как заставить это работать, если вам абсолютно необходим объект SOAPMessage, но опять же, если вы все равно собираетесь обрабатывать необработанный XML, зачем вам использовать объект более высокого уровня?)

Другие советы

Вы можете попробовать таким образом.

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

Если у тебя есть 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());

При этом будет учтена кодировка, поэтому ваши «специальные символы» не будут искажены.

только для целей отладки используйте однострочный код -

msg.writeTo(System.out);

Если вам нужно отформатировать строку 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")));

Использование Трансформаторной фабрики: -

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

это работает

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

если у вас есть клиентский код, вам просто нужно добавить следующие две строки, чтобы получить запрос/ответ XML.Здесь _call является org.apache.axis.client.Call

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

Это довольно старая тема, но недавно у меня возникла похожая проблема.Я вызывал нижестоящую мыльную службу из службы отдыха, и мне нужно было вернуть 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");

У меня еще не было возможности протестировать его, но этот подход должен быть потокобезопасным, поскольку он использует контекст сервлета.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top