Ich habe einen SOAP WebServiceProvider in JAX-WS eingerichtet, aber ich habe Probleme herauszufinden, wie das unformatierte XML von einem SOAPMessage-Objekt (oder einem beliebigen Knotenobjekt) abgerufen werden kann. Hier ist ein Beispiel des Codes, den ich gerade habe, und wo ich versuche, das XML abzurufen:
@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?
}
}
Gibt es eine einfache Möglichkeit, das XML der ursprünglichen Anforderung abzurufen? Wenn es eine Möglichkeit gibt, das unformatierte XML durch Einrichten eines anderen Anbietertyps (z. B. Quelle) zu erhalten, wäre ich auch dazu bereit.
Wenn Sie ein
SOAPMessage
oder habenSOAPMessageContext
, können Sie ein verwendenTransformer
, indem Sie es in einSource
Via konvertierenDOMSource
: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());
Dadurch wird die Codierung berücksichtigt, sodass Ihre "Sonderzeichen" nicht entstellt werden.
quelle
Es stellt sich heraus, dass man das unformatierte XML mithilfe von Provider <Quelle> auf folgende Weise erhalten kann:
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; } }
Ich brauchte diese Lösung letztendlich nicht, also habe ich diesen Code nicht selbst ausprobiert - es könnte einige Anpassungen erfordern, um richtig zu werden. Ich weiß jedoch, dass dies der richtige Weg ist, um das unformatierte XML von einem Webdienst abzurufen.
(Ich bin mir nicht sicher, wie ich das machen soll, wenn Sie unbedingt ein SOAPMessage-Objekt haben müssen, aber wenn Sie das rohe XML sowieso verarbeiten wollen, warum sollten Sie ein übergeordnetes Objekt verwenden?)
quelle
StringWriter
ist eine gute Alternative zurByteArrayOutputStream
+StreamResult
-Kombination, wenn Sie das XML alsString
mit der richtigen CodierungVerwenden Sie zum Debuggen nur einen Zeilencode -
msg.writeTo(System.out);
quelle
ByteArrayOutputStream
Konvertiten schreiben, umString
... scheint mir einfachWenn Sie die XML-Zeichenfolge in XML formatieren müssen, versuchen Sie Folgendes:
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")));
quelle
Verwenden von 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(); }
quelle
das funktioniert
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();
quelle
Wenn Sie den Client-Code haben, müssen Sie nur die folgenden zwei Zeilen hinzufügen, um die XML-Anforderung / Antwort zu erhalten. Hier
_call
istorg.apache.axis.client.Call
quelle
Es ist ein ziemlich alter Thread, aber kürzlich hatte ich ein ähnliches Problem. Ich habe einen Downstream-Seifendienst von einem Rest-Service aus aufgerufen und musste die XML-Antwort vom Downstream-Server unverändert zurückgeben.
Also habe ich einen SoapMessageContext-Handler hinzugefügt, um die XML-Antwort zu erhalten. Dann habe ich die Antwort-XML als Attribut in den Servlet-Kontext eingefügt.
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; } }
Dann habe ich die XML-Antwortzeichenfolge in der Service-Schicht abgerufen.
ServletContext servletContext = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext(); String msg = (String) servletContext.getAttribute("responseXml");
Ich hatte noch keine Gelegenheit, es zu testen, aber dieser Ansatz muss threadsicher sein, da er den Servlet-Kontext verwendet.
quelle