java 如何将 SOAP 标头添加到 Spring Jax-WS 客户端?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4046075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:32:06  来源:igfitidea点击:

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

javaspringjax-wssoapheader

提问by Brandon

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

如何将 SOAP 标头添加到 Spring Jax-WS 客户端?

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

具体来说,我有一个 Jaxb 对象,我想添加到标题中,但不胜感激 xml 示例。

I am using Spring's JaxWsPortProxyFactoryBean described here. Also, I am generating my client as described herewhich is working less the headers I need to add.

我正在使用此处描述的 Spring 的 JaxWsPortProxyFactoryBean 。此外,我正在按照此处所述生成我的客户端,这减少了我需要添加的标题。

Thank you.

谢谢你。

回答by user3078523

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.

注意:此示例已使用 Spring WS 2.1.4 进行测试。

回答by chris

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:

我仍在尝试找到一种优雅的方式来添加标题,但我按照其他人的建议做的是在 WebServiceMessageCallBack() 上使用 Transformer。这是一个示例代码:

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.

考虑到这是 Spring 的 WS,它并不是很优雅。这不直观。

回答by Wildsau

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.

如果找到了稍微不同的解决方案,则经过一番摸索。我正在使用 JAXB 来编组我的有效负载,并且还使用来自 WSDL 的 JAXB 生成了可能的头类。就我而言,我正在处理 Microsoft Reporting Services,并将 ExecutionID 作为 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));
    }
}

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:

基本上 WebServiceGatewaySupport 已经知道 Marshaller 来转换 JAXB Pojos。我正在使用此行将我自己的头类附加到 SoapHeader 中:

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

in my nested WebServiceMessageCallback.

在我嵌套的 WebServiceMessageCallback 中。

回答by lidox

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

}