How to add SOAP Headers to Spring Jax-WS Client?

后端 未结 4 1431
南方客
南方客 2021-02-02 16:10

How can I add SOAP Headers to Spring Jax-WS Client?

Specifically, I have a Jaxb object I would like to add to the header but xml examples would be appreciated.

相关标签:
4条回答
  • 2021-02-02 16:37

    I'm still trying to find an elegant way to add headers, but what I do as suggested by others is to use a Transformer on the WebServiceMessageCallBack(). Here's an example 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);
           }
    }
    ...
    

    It's not really elegant, considering this is Spring's WS. It's not intuitive.

    0 讨论(0)
  • 2021-02-02 16:42

    After some poking around if found a slightly different solution. I'm using JAXB for marshalling my payload and the possible header classes have also been generated with JAXB from the WSDL. In my case I am addressing Microsoft Reporting Services and have pass on an ExecutionID as SOAP header.

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

    Basically the WebServiceGatewaySupport already knows the Marshaller to convert JAXB Pojos. I'm using this one to attach my own header classes to the SoapHeader with this line:

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

    in my nested WebServiceMessageCallback.

    0 讨论(0)
  • 2021-02-02 16:50

    A little bit more elegant (still a class cast is required):

    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: This example has been testes with Spring WS 2.1.4.

    0 讨论(0)
  • 2021-02-02 16:56

    This is an alternative solution:

    public class YourServiceClient extends WebServiceGatewaySupport {
    
        // custom header inner class
        private final class CustomHeader implements WebServiceMessageCallback {
    
            private String soapAction;
            private long yourHeaderParameter1;
            private long yourHeaderParameter2;
    
    
            public CustomHeader(String soapAction, long yourHeaderParameter1, long yourHeaderParameter2) {
                super();
                if (!StringUtils.hasText(soapAction)) {
                    soapAction = "\"\"";
                }
                this.soapAction = soapAction;
                this.yourHeaderParameter1 = yourHeaderParameter1;
                this.yourHeaderParameter2 = yourHeaderParameter2;
            }
    
            @Override
            public void doWithMessage(WebServiceMessage message) {
                try {
                    // get the header from the SOAP message
                    SoapHeader soapHeader = ((SoapMessage) message).getSoapHeader();
    
                    // create the header element
                    ObjectFactory factory = new ObjectFactory();
                    YourGeneratedHeaderEntity header = new YourGeneratedHeaderEntity();
                    header.setyourHeaderParameter1(yourHeaderParameter1);
                    header.setyourHeaderParameter2(yourHeaderParameter2);
    
                    JAXBElement<YourGeneratedHeaderEntity> headers = factory.createYourGeneratedHeaderEntity(header);
    
                    // create a marshaller
                    JAXBContext context = JAXBContext.newInstance(YourGeneratedHeaderEntity.class);
                    Marshaller marshaller = context.createMarshaller();
    
                    // set action
                    Assert.isInstanceOf(SoapMessage.class, message);
                    SoapMessage soapMessage = (SoapMessage) message;
                    soapMessage.setSoapAction(soapAction);
    
                    // marshal the headers into the specified result
                    marshaller.marshal(headers, soapHeader.getResult());
    
    
                } catch (Exception e) {
                    logger.error(e.getLocalizedMessage());
                }
    
            }
        }
    
        public YourEntityResponse getYourService(long yourHeaderParameter1, long yourHeaderParameter2) {
            GetYourService request = new GetYourService();
    
            YourEntityResponse response = (YourEntityResponse) getWebServiceTemplate()
                    .marshalSendAndReceive(request, new CustomHeader("https://your.service.asmx?WSDL", yourHeaderParameter1, yourHeaderParameter2));
    
            return response;
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题