将 SoapHeader 添加到 org.springframework.ws.WebServiceMessage

发布于 2024-08-21 17:36:52 字数 344 浏览 4 评论 0原文

如何将对象添加到 org.springframework.ws.WebServiceMessage 的肥皂头中

这是我希望最终得到的结构:

 <soap:Header>
    <credentials xmlns="http://example.com/auth">
      <username>username</username>
      <password>password</password>
    </credentials>
  </soap:Header>

How can I add an object into the soap header of a org.springframework.ws.WebServiceMessage

This is the structure I'm looking to end up with:

 <soap:Header>
    <credentials xmlns="http://example.com/auth">
      <username>username</username>
      <password>password</password>
    </credentials>
  </soap:Header>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

佞臣 2024-08-28 17:36:52

基本上,您需要使用 WebServiceMessageCallback 在您的客户端中,用于在消息创建之后、发送之前修改消息。 @skaffman 已经非常准确地描述了其余的代码,因此整个内容可能如下所示:

public void marshalWithSoapActionHeader(MyObject o) {

    webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback() {

        public void doWithMessage(WebServiceMessage message) {
            try {
                SoapMessage soapMessage = (SoapMessage)message;
                SoapHeader header = soapMessage.getSoapHeader();
                StringSource headerSource = new StringSource("<credentials xmlns=\"http://example.com/auth\">\n +
                        <username>"+username+"</username>\n +
                        <password>"+password"+</password>\n +
                        </credentials>");
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.transform(headerSource, header.getResult());
            } catch (Exception e) {
                // exception handling
            }
        }
    });
}

就我个人而言,我发现 Spring-WS 很难满足这样的基本需求,他们应该修复 SWS-479

Basically, you need to use a WebServiceMessageCallback in your client to modify the message after its creation but before it is sent. To rest of the code has been described pretty accurately by @skaffman so the whole stuff might look like this:

public void marshalWithSoapActionHeader(MyObject o) {

    webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback() {

        public void doWithMessage(WebServiceMessage message) {
            try {
                SoapMessage soapMessage = (SoapMessage)message;
                SoapHeader header = soapMessage.getSoapHeader();
                StringSource headerSource = new StringSource("<credentials xmlns=\"http://example.com/auth\">\n +
                        <username>"+username+"</username>\n +
                        <password>"+password"+</password>\n +
                        </credentials>");
                Transformer transformer = TransformerFactory.newInstance().newTransformer();
                transformer.transform(headerSource, header.getResult());
            } catch (Exception e) {
                // exception handling
            }
        }
    });
}

Personally, I find that Spring-WS sucks hard for such a basic need, they should fix SWS-479.

惟欲睡 2024-08-28 17:36:52

您可以执行以下操作:

public class SoapRequestHeaderModifier implements WebServiceMessageCallback {
 private final String userName = "user";
 private final String passWd = "passwd";

 @Override
 public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
  if (message instanceof SaajSoapMessage) {
   SaajSoapMessage soapMessage = (SaajSoapMessage) message;
   MimeHeaders mimeHeader = soapMessage.getSaajMessage().getMimeHeaders();
   mimeHeader.setHeader("Authorization", getB64Auth(userName, passWd));
  }
 }

 private String getB64Auth(String login, String pass) {
  String source = login + ":" + pass;
  String retunVal = "Basic " + Base64.getUrlEncoder().encodeToString(source.getBytes());
  return retunVal;
 }
}

然后

Object response = getWebServiceTemplate().marshalSendAndReceive(request, new SoapRequestHeaderModifier());

You can do as below:

public class SoapRequestHeaderModifier implements WebServiceMessageCallback {
 private final String userName = "user";
 private final String passWd = "passwd";

 @Override
 public void doWithMessage(WebServiceMessage message) throws IOException, TransformerException {
  if (message instanceof SaajSoapMessage) {
   SaajSoapMessage soapMessage = (SaajSoapMessage) message;
   MimeHeaders mimeHeader = soapMessage.getSaajMessage().getMimeHeaders();
   mimeHeader.setHeader("Authorization", getB64Auth(userName, passWd));
  }
 }

 private String getB64Auth(String login, String pass) {
  String source = login + ":" + pass;
  String retunVal = "Basic " + Base64.getUrlEncoder().encodeToString(source.getBytes());
  return retunVal;
 }
}

Then

Object response = getWebServiceTemplate().marshalSendAndReceive(request, new SoapRequestHeaderModifier());
A君 2024-08-28 17:36:52

您需要将 WebServiceMessage 转换为 SoapMessage,它具有可用于修改标头的 getSoapHeader() 方法。反过来,SoapHeader 有各种添加元素的方法,包括 getResult()(可以用作 Transformer.transform() 的输出) > 操作)。

You need to cast the WebServiceMessage to SoapMessage, which has a getSoapHeader() method you can use to modify the header. In turn, SoapHeader has various methods for adding elements, including getResult() (which can be used as the output of a Transformer.transform() operation).

碍人泪离人颜 2024-08-28 17:36:52
I tried many options and finally below one worked for me if you have to send soap header with authentication(Provided authentication object created by wsimport) and also need to set soapaction.

public Response callWebService(String url, Object request)

{
    Response res = null;
    log.info("The request object is " + request.toString());

    try {
        
        

        res = (Response) getWebServiceTemplate().marshalSendAndReceive(url, request,new WebServiceMessageCallback() {
                 @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();
                      Authentication auth =
                          factory.createAuthentication();
                      auth.setUser("****");
                      auth.setPassword("******");
                     ((SoapMessage) message).setSoapAction(
                                "soapAction");

                      JAXBElement<Authentication> headers =
                          factory.createAuthentication(auth);

                      // create a marshaller
                      JAXBContext context = JAXBContext.newInstance(Authentication.class);
                      Marshaller marshaller = context.createMarshaller();

                      // marshal the headers into the specified result
                      marshaller.marshal(headers, soapHeader.getResult());
                      
                    } catch (Exception e) {
                      log.error("error during marshalling of the SOAP headers", e);
                    }
                  }
                });

        
    } catch (Exception e) {
        e.printStackTrace();
    }
    return res;

}
  
I tried many options and finally below one worked for me if you have to send soap header with authentication(Provided authentication object created by wsimport) and also need to set soapaction.

public Response callWebService(String url, Object request)

{
    Response res = null;
    log.info("The request object is " + request.toString());

    try {
        
        

        res = (Response) getWebServiceTemplate().marshalSendAndReceive(url, request,new WebServiceMessageCallback() {
                 @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();
                      Authentication auth =
                          factory.createAuthentication();
                      auth.setUser("****");
                      auth.setPassword("******");
                     ((SoapMessage) message).setSoapAction(
                                "soapAction");

                      JAXBElement<Authentication> headers =
                          factory.createAuthentication(auth);

                      // create a marshaller
                      JAXBContext context = JAXBContext.newInstance(Authentication.class);
                      Marshaller marshaller = context.createMarshaller();

                      // marshal the headers into the specified result
                      marshaller.marshal(headers, soapHeader.getResult());
                      
                    } catch (Exception e) {
                      log.error("error during marshalling of the SOAP headers", e);
                    }
                  }
                });

        
    } catch (Exception e) {
        e.printStackTrace();
    }
    return res;

}
  
戈亓 2024-08-28 17:36:52

您也可以通过创建子元素的键值映射来实现:

final Map<String, String> elements = new HashMap<>();
elements.put("username", "username");
elements.put("password", "password");

在soap标头中设置子元素的命名空间和前缀:

final String LOCAL_NAME = "credentials";
final String PREFIX = "";
final String NAMESPACE = "http://example.com/auth";

然后,您可以调用WebServiceTemplate的方法 marshalSendAndReceive ,您可以在其中重写 WebServiceMessageCallback 的方法 doWithMessage 如下:

Object response = getWebServiceTemplate().marshalSendAndReceive(request, (message) -> {
    if (message instanceof SaajSoapMessage) {
        SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
        SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        if (Objects.nonNull(elements)) {
            try {
                SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
                SOAPHeader soapHeader = soapEnvelope.getHeader();
                Name headerElementName = soapEnvelope.createName(
                        LOCAL_NAME,
                        PREFIX,
                        NAMESPACE
                );
                SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);

                elements.forEach((key, value) -> {
                    try {
                        SOAPElement element = soapHeaderElement.addChildElement(key, PREFIX);
                        element.addTextNode(value);
                    } catch (SOAPException e) {
                        // error handling
                    }
                });

                soapMessage.saveChanges();
            } catch (SOAPException e) {
                // error handling
            }
        }
    }
});

上述步骤导致:

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Header>
      <credentials xmlns="http://example.com/auth">
         <password>password</password>
         <username>username</username>
      </credentials>
   </env:Header>
   <env:Body>
      <!--  your payload -->
   </env:Body>
</env:Envelope>

You can achieve it by creating key-value map of child elements as well:

final Map<String, String> elements = new HashMap<>();
elements.put("username", "username");
elements.put("password", "password");

Set up namespace and prefix of your child element within the soap header:

final String LOCAL_NAME = "credentials";
final String PREFIX = "";
final String NAMESPACE = "http://example.com/auth";

Then, you can invoke WebServiceTemplate's method marshalSendAndReceive where you override WebServiceMessageCallback's method doWithMessage as follows:

Object response = getWebServiceTemplate().marshalSendAndReceive(request, (message) -> {
    if (message instanceof SaajSoapMessage) {
        SaajSoapMessage saajSoapMessage = (SaajSoapMessage) message;
        SOAPMessage soapMessage = saajSoapMessage.getSaajMessage();
        SOAPPart soapPart = soapMessage.getSOAPPart();

        if (Objects.nonNull(elements)) {
            try {
                SOAPEnvelope soapEnvelope = soapPart.getEnvelope();
                SOAPHeader soapHeader = soapEnvelope.getHeader();
                Name headerElementName = soapEnvelope.createName(
                        LOCAL_NAME,
                        PREFIX,
                        NAMESPACE
                );
                SOAPHeaderElement soapHeaderElement = soapHeader.addHeaderElement(headerElementName);

                elements.forEach((key, value) -> {
                    try {
                        SOAPElement element = soapHeaderElement.addChildElement(key, PREFIX);
                        element.addTextNode(value);
                    } catch (SOAPException e) {
                        // error handling
                    }
                });

                soapMessage.saveChanges();
            } catch (SOAPException e) {
                // error handling
            }
        }
    }
});

The above steps result in:

<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
   <env:Header>
      <credentials xmlns="http://example.com/auth">
         <password>password</password>
         <username>username</username>
      </credentials>
   </env:Header>
   <env:Body>
      <!--  your payload -->
   </env:Body>
</env:Envelope>
神经大条 2024-08-28 17:36:52

Response response = (Response)getWebServiceTemplate() .marshalSendAndReceive(request, new HeaderModifier());

创建类 HeaderModifier 并重写 doWithMessage

public class HeaderModifier implements WebServiceMessageCallback {

     private static PrintStream out = System.out;
     
    @Override
    public void doWithMessage(WebServiceMessage message) throws IOException {
          SaajSoapMessage soapMessage = (SaajSoapMessage) message;

                SoapEnvelope soapEnvelope = soapMessage.getEnvelope();
                SoapHeader soapHeader = soapEnvelope.getHeader();
                
                //Initialize QName for Action and To 
                QName action = new QName("{uri}","Action","{actionname}");
                QName to = new QName("{uri}","To","{actionname}");
                
                
                soapHeader.addNamespaceDeclaration("{actionname}", "{uri}");
                
            
                SoapHeaderElement soapHeaderElementAction = soapHeader.addHeaderElement(action);
                SoapHeaderElement soapHeaderElementTo =  soapHeader.addHeaderElement(to);
                
                
            
                soapHeaderElementAction.setText("{text inside the tags}");
                
            
                soapHeaderElementTo.setText("{text inside the tags}");
                
            
                soapMessage.setSoapAction("{add soap action uri}");
                
            
                soapMessage.writeTo(out);
        
    }
}

Response response = (Response)getWebServiceTemplate() .marshalSendAndReceive(request, new HeaderModifier());

Create class HeaderModifier and override doWithMessage

public class HeaderModifier implements WebServiceMessageCallback {

     private static PrintStream out = System.out;
     
    @Override
    public void doWithMessage(WebServiceMessage message) throws IOException {
          SaajSoapMessage soapMessage = (SaajSoapMessage) message;

                SoapEnvelope soapEnvelope = soapMessage.getEnvelope();
                SoapHeader soapHeader = soapEnvelope.getHeader();
                
                //Initialize QName for Action and To 
                QName action = new QName("{uri}","Action","{actionname}");
                QName to = new QName("{uri}","To","{actionname}");
                
                
                soapHeader.addNamespaceDeclaration("{actionname}", "{uri}");
                
            
                SoapHeaderElement soapHeaderElementAction = soapHeader.addHeaderElement(action);
                SoapHeaderElement soapHeaderElementTo =  soapHeader.addHeaderElement(to);
                
                
            
                soapHeaderElementAction.setText("{text inside the tags}");
                
            
                soapHeaderElementTo.setText("{text inside the tags}");
                
            
                soapMessage.setSoapAction("{add soap action uri}");
                
            
                soapMessage.writeTo(out);
        
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文