2009-02-06 20 views
58

Ho impostato un SOAP WebServiceProvider in JAX-WS, ma non riesco a capire come ottenere il codice XML non elaborato da un oggetto SOAPMessage (o qualsiasi nodo). Ecco un esempio del codice che ho in questo momento, e dove sto cercando di afferrare l'XML:Getting Raw XML da SOAPMessage in Java

@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? 
    } 
} 

C'è un modo semplice per ottenere il codice XML della richiesta originale? Se c'è un modo per ottenere l'XML non elaborato impostando un diverso tipo di Provider (come Source), sarei disposto a farlo anche io.

risposta

11

Si scopre che si può ottenere l'XML grezzo utilizzando Provider < Fonte>, in questo modo:

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

ho finito per non necessitano di questa soluzione, così non ho davvero provato questo codice me stesso - potrebbe aver bisogno di qualche ritocco per avere ragione. Ma so che questa è la strada giusta da percorrere per ottenere il codice XML grezzo da un servizio web.

(Non sono sicuro di come farlo funzionare se si deve assolutamente avere un oggetto SOAPMessage, ma poi di nuovo, se si gestirà comunque l'XML non elaborato, perché si utilizzerà un oggetto di livello superiore ?)

+0

Un 'StringWriter' è una buona alternativa alla ByteArrayOutputStream' +' 'StreamResult' combinazione, se si desidera l'XML come 'String' con la codifica corretta – artbristol

131

Si potrebbe provare in questo modo.

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

Questo è fantastico. – user85155

+3

Questo non richiede la codifica dei caratteri nell'account – artbristol

+0

Si consuma molta memoria con qualcosa come la costruzione di oggetti DOM o simili? O darà veramente la stringa grezza dalla risposta HTTP senza analizzare internamente l'xml? – Ruslan

4

Se è necessario formattare la stringa XML a XML, provare questo:

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

Se si dispone di un SOAPMessage o SOAPMessageContext, è possibile utilizzare un Transformer, convertendolo in un Source via 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()); 

Questo prenderà in considerazione la codifica, in modo che i "caratteri speciali" non vengano manomessi.

+0

Viene fornita memoria consumante? – lospejos

8

a scopo solo il debug, utilizzare uno codice di linea -

msg.writeTo(System.out);

+0

L'OP non sta necessariamente eseguendo il debug su System.out (che non è necessariamente facilmente accessibile per un server web) - potrebbe essere necessario inviare l'XML originale su un socket, memorizzarlo da qualche parte o calcolare le sue statistiche. – hexafraction

+1

solo raccontando un'opzione, nient'altro. grazie –

+0

Puoi facilmente scrivere in una conversione 'ByteArrayOutputStream' in' String' ... mi sembra facile – vikingsteve

0

se si dispone il codice del client, allora non vi resta che aggiungere le seguenti due righe per ottenere la richiesta XML/risposta. Qui _call è org.apache.axis.client.Call

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

Utilizzando trasformatore di fabbrica: -

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

questo funziona

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

Un'altra spiegazione invece di un dump del codice sarebbe buona. – Raidri

+0

Nessuna spiegazione necessaria. –