2010-10-28 22 views
11

Comment puis-je ajouter des en-têtes SOAP au client Spring Jax-WS?Comment ajouter des en-têtes SOAP au client Spring Jax-WS?

Plus précisément, j'ai un objet Jaxb que je voudrais ajouter à l'en-tête mais des exemples xml seraient appréciés. J'utilise JaxWsPortProxyFactoryBean de Spring décrit here. En outre, je génère mon client comme décrit here qui fonctionne moins les en-têtes que j'ai besoin d'ajouter.

Merci.

Répondre

6

J'essaie toujours de trouver une manière élégante d'ajouter des en-têtes, mais ce que je fais comme suggéré par d'autres est d'utiliser un Transformer sur le WebServiceMessageCallBack(). Voici un exemple de 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); 
     } 
} 
... 

Ce n'est pas vraiment élégant, étant donné que c'est le WS de Spring. Ce n'est pas intuitif.

14

Un peu plus élégant (encore un casting de classe est nécessaire):

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

Note: Cet exemple a été testicules avec Spring WS 2.1.4.

5

Après avoir piquer autour si trouvé une solution légèrement différente. J'utilise JAXB pour rassembler ma charge utile et les classes d'en-têtes possibles ont également été générées avec JAXB à partir du WSDL. Dans mon cas, je m'adresse à Microsoft Reporting Services et j'ai transmis un ExecutionID en tant qu'en-tête SOAP.

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

Fondamentalement, le WebServiceGatewaySupport connaît déjà le Marshaller pour convertir JAXB POJO. J'utilise celui-ci pour joindre mes propres classes d'en-tête au SoapHeader avec cette ligne:

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

dans mon WebServiceMessageCallback imbriqué.