web-dev-qa-db-ja.com

JavaでSOAPMessageから生のXMLを取得する

JAX-WSでSOAP WebServiceProviderを設定しましたが、SOAPMessage(または任意のNode)オブジェクトから未加工のXMLを取得する方法を見つけるのに問題があります。以下にサンプルを示します。私が今持っているコード、そして私が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を取得する方法があれば、私も喜んでそれを行います。

70
Daniel Lew

次のように、Provider <Source>を使用して生のXMLを取得できることがわかります。

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

私は結局この解決策を必要としないことになったので、実際にこのコードを自分で試したことはありません。しかし、これがWebサービスから生のXMLを取得するための正しい道であることは知っています。

(SOAPMessageオブジェクトが絶対に必要な場合、これをどのように機能させるかわかりませんが、とにかく生のXMLを処理するつもりなら、なぜより高いレベルのオブジェクトを使用するのですか?)

11
Daniel Lew

この方法で試すことができます。

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

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

これによりエンコードが考慮されるため、「特殊文字」が破損することはありません。

18
artbristol

デバッグのためだけに、1行のコードを使用します-

msg.writeTo(System.out);

11

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

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

これは動作します

 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

それはかなり古いスレッドですが、最近、同様の問題が発生しました。レストサービスからダウンストリームSOAPサービスを呼び出していたので、ダウンストリームサーバーからの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");

まだテストする機会はありませんでしたが、このアプローチはサーブレットコンテキストを使用しているため、スレッドセーフでなければなりません。

0
Oguz Demir

クライアントコードがある場合は、次の2行を追加するだけでXML要求/応答を取得できます。ここに _callorg.Apache.axis.client.Call

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