developer tip

Java의 SOAPMessage에서 원시 XML 가져 오기

copycodes 2020. 10. 28. 08:12
반응형

Java의 SOAPMessage에서 원시 XML 가져 오기


JAX-WS에서 SOAP WebServiceProvider를 설정했지만 SOAPMessage (또는 모든 노드) 개체에서 원시 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을 얻는 방법이 있다면 저도 그렇게 할 것입니다.


이런 식으로 시도 할 수 있습니다.

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

당신이있는 경우 SOAPMessage또는 SOAPMessageContext, 당신은을 사용할 수 있습니다 TransformerA를 변환하여, 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());

이것은 인코딩을 고려하므로 "특수 문자"가 엉망이되지 않습니다.


다음과 같이 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;
    }
}

이 솔루션이 필요하지 않게되었으므로 실제로이 코드를 직접 시도하지 않았습니다. 제대로하려면 약간의 조정이 필요할 수 있습니다. 그러나 이것이 웹 서비스에서 원시 XML을 가져 오는 올바른 경로라는 것을 알고 있습니다.

(SOAPMessage 객체가 반드시 있어야하는 경우 어떻게 작동하는지 모르겠지만, 어쨌든 원시 XML을 처리하려는 경우 왜 더 높은 수준의 객체를 사용합니까?)


디버깅 목적으로 한 줄 코드를 사용하십시오.

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

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

이것은 작동한다

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

It is pretty old thread but recently i had a similar issue. I was calling a downstream soap service, from a rest service, and I needed to return the xml response coming from the downstream server as is.

So, i ended up adding a SoapMessageContext handler to get the XML response. Then i injected the response xml into servlet context as an attribute.

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

Then I have retrieved the xml response string in the service layer.

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

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

Didn't have chance to test it yet but this approach must be thread safe since it is using the servlet context.

참고URL : https://stackoverflow.com/questions/522395/getting-raw-xml-from-soapmessage-in-java

반응형