2010-10-28 9 views
11

Wie kann ich dem Spring Jax-WS Client SOAP-Header hinzufügen?So fügen Sie SOAP-Header zum Spring Jax-WS-Client hinzu?

Konkret habe ich ein Jaxb-Objekt, das ich gerne zur Kopfzeile hinzufügen möchte, aber xml-Beispiele wären willkommen.

Ich verwende Spring JaxWsPortProxyFactoryBean beschrieben here. Außerdem erstelle ich meinen Client wie beschrieben here, der weniger die Header arbeitet, die ich hinzufügen muss.

Vielen Dank.

Antwort

6

Ich versuche immer noch, eine elegante Möglichkeit zu finden, Header hinzuzufügen, aber was ich mache, wie von anderen vorgeschlagen, ist die Verwendung eines Transformers in der WebServiceMessageCallBack(). Hier ist ein Beispiel-Code:

JAXBElement<GetDeletedResponse> result = (JAXBElement<GetDeletedResponse>) webServiceTemplate.marshalSendAndReceive(request, new WebServiceMessageCallback() { 
public void doWithMessage(WebServiceMessage webServiceMessage) { 
    try { 
     SoapMessage soapMessage = (SoapMessage) webServiceMessage; 
     soapMessage.setSoapAction("getDeleted"); 

     SoapHeader header = soapMessage.getSoapHeader(); 
     StringSource headerSource = new StringSource("<account>\n" + 
           "<username>"+"johnsmith"+"</username>\n" + 
           "<password>"+"1234"+"</password>\n" + 
           "</account>"); 
     Transformer transformer = TransformerFactory.newInstance().newTransformer(); 
     transformer.transform(headerSource, header.getResult()); 

     } catch (Exception e) { 
     new RuntimeException(e); 
     } 
} 
... 

Es ist nicht wirklich elegant, wenn man bedenkt das WS Spring ist. Es ist nicht intuitiv.

14

Ein wenig eleganter (noch eine Klasse Besetzung erforderlich):

public void doWithMessage(WebServiceMessage message) { 
    try { 
     SOAPMessage soapMessage = ((SaajSoapMessage)message).getSaajMessage(); 
     SOAPHeader header = soapMessage.getSOAPHeader(); 
     SOAPHeaderElement security = header.addHeaderElement(new QName("http://schemas.xmlsoap.org/ws/2003/06/secext", "Security", "wsse")); 
     SOAPElement usernameToken = security.addChildElement("UsernameToken", "wsse"); 
     SOAPElement username = usernameToken.addChildElement("Username", "wsse"); 
     SOAPElement password = usernameToken.addChildElement("Password", "wsse"); 

     username.setTextContent(someUsername); 
     password.setTextContent(somePassword); 
    } catch (Exception e) { 
     //... handle appropriately 
    } 
} 

Hinweis: Dieses Beispiel hat Hoden wurden mit Frühling WS 2.1.4.

5

Nach etwas stochern, wenn eine etwas andere Lösung gefunden. Ich verwende JAXB zum Marshalling meiner Payload und die möglichen Header-Klassen wurden auch mit JAXB aus der WSDL generiert. In meinem Fall adressiere ich Microsoft Reporting Services und habe eine ExecutionID als SOAP-Header übergeben.

public class ReportExecution2005Client extends WebServiceGatewaySupport { 

    private static final String SET_EXECUTION_PARAMETERS_ACTION = "http://schemas.microsoft.com/sqlserver/2005/06/30/reporting/reportingservices/SetExecutionParameters"; 

    private final class SoapActionExecutionIdCallback implements WebServiceMessageCallback { 

     private final String soapAction; 
     private final String executionId; 

     public SoapActionExecutionIdCallback(String soapAction, String executionId) { 
      super(); 
      this.soapAction = soapAction; 
      this.executionId = executionId; 
     } 

     @Override 
     public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException { 
      SoapMessage soapMessage = (SoapMessage) message; 
      soapMessage.setSoapAction(soapAction); 
      ExecutionHeader executionHeader = new ExecutionHeader(); 
      executionHeader.setExecutionID(executionId); 
      getMarshaller().marshal(executionHeader, soapMessage.getSoapHeader().getResult()); 
     } 
    } 

    public void setExecutionParameters(String executionId){ 
     SetExecutionParameters request = new SetExecutionParameters(); 
     request.setParameters(new ArrayOfParameterValue()); 

     SetExecutionParametersResponse response = (SetExecutionParametersResponse) getWebServiceTemplate().marshalSendAndReceive(request, 
       new SoapActionExecutionIdCallback(
         SET_EXECUTION_PARAMETERS_ACTION, 
         executionId)); 
    } 
} 

Grundsätzlich ist der WebServiceGatewaySupport kennt bereits die Marshaller JAXB Pojos zu konvertieren. Ich verwende diese eine meine eigenen Header-Klassen an die Soapheader mit dieser Linie befestigen:

getMarshaller().marshal(executionHeader, soapMessage.getSoapHeader().getResult()); 

in meinem verschachtelten WebServiceMessageCallback.