Skonfigurowałem SOAP WebServiceProvider w JAX-WS, ale mam problem ze znalezieniem surowego kodu XML z obiektu SOAPMessage (lub dowolnego Node). Oto przykład kodu, który mam teraz i gdzie próbuję pobrać 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?
}
}
Czy istnieje prosty sposób uzyskania kodu XML pierwotnego żądania? Jeśli istnieje sposób na uzyskanie surowego XML przez skonfigurowanie innego typu dostawcy (na przykład źródła), też bym to zrobił.
Jeśli masz
SOAPMessage
lubSOAPMessageContext
, możesz użyć aTransformer
, konwertując go naSource
viaDOMSource
: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());
To weźmie pod uwagę kodowanie, więc Twoje „znaki specjalne” nie zostaną zniekształcone.
źródło
Okazuje się, że surowy XML można pobrać za pomocą Provider <Source> w ten sposób:
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; } }
Skończyło się na tym, że nie potrzebowałem tego rozwiązania, więc tak naprawdę nie próbowałem sam tego kodu - może to wymagać pewnych poprawek, aby było dobrze. Ale wiem, że jest to właściwa ścieżka do uzyskania surowego XML z usługi sieciowej.
(Nie jestem pewien, jak to działa, jeśli absolutnie musisz mieć obiekt SOAPMessage, ale z drugiej strony, jeśli mimo wszystko masz zamiar obsługiwać surowy XML, dlaczego miałbyś używać obiektu wyższego poziomu?)
źródło
StringWriter
jest dobrą alternatywą dla kombinacjiByteArrayOutputStream
+StreamResult
, jeśli chcesz, aby XML byłString
z poprawnym kodowaniemtylko w celu debugowania użyj jednego wiersza kodu -
msg.writeTo(System.out);
źródło
ByteArrayOutputStream
konwersji naString
... wydaje mi się łatweJeśli potrzebujesz sformatować ciąg xml do xml, spróbuj tego:
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")));
źródło
Korzystanie z 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(); }
źródło
to działa
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();
źródło
jeśli masz kod klienta, wystarczy dodać następujące dwie linie, aby uzyskać żądanie / odpowiedź XML. Tutaj
_call
jestorg.apache.axis.client.Call
źródło
To dość stary wątek, ale ostatnio miałem podobny problem. Dzwoniłem do podrzędnej usługi mydła z usługi odpoczynku i musiałem zwrócić odpowiedź xml pochodzącą z serwera podrzędnego w takiej postaci, w jakiej jest.
W końcu dodałem moduł obsługi SoapMessageContext, aby uzyskać odpowiedź XML. Następnie wstrzyknąłem plik XML odpowiedzi do kontekstu serwletu jako atrybut.
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; } }
Następnie pobrałem ciąg odpowiedzi xml w warstwie usług.
ServletContext servletContext = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getServletContext(); String msg = (String) servletContext.getAttribute("responseXml");
Nie miałem jeszcze okazji go przetestować, ale to podejście musi być bezpieczne dla wątków, ponieważ używa kontekstu serwletu.
źródło