【问题标题】:How to add SOAP Headers to Spring Jax-WS Client?如何将 SOAP 标头添加到 Spring Jax-WS 客户端?
【发布时间】:2011-05-02 01:23:10
【问题描述】:

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

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

我正在使用 here 描述的 Spring 的 JaxWsPortProxyFactoryBean。另外,我正在生成我的客户端,如here 所述,它的工作量更少我需要添加的标题。

谢谢。

【问题讨论】:

    标签: java spring jax-ws soapheader


    【解决方案1】:

    这是另一种解决方案:

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

    【讨论】:

      【解决方案2】:

      经过一番摸索,如果找到了一个稍微不同的解决方案。我正在使用 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));
          }
      }
      

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

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

      在我的嵌套 WebServiceMessageCallback 中。

      【讨论】:

        【解决方案3】:

        更优雅一点(仍然需要类转换):

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

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

        【讨论】:

          【解决方案4】:

          我仍在尝试找到一种添加标头的优雅方法,但我按照其他人的建议做的是在 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);
                 }
          }
          ...
          

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

          【讨论】:

            猜你喜欢
            • 2011-01-20
            • 1970-01-01
            • 2013-09-24
            • 1970-01-01
            • 2010-10-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多