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

问题描述 投票:0回答:6
java web-services spring soap spring-ws
6个回答
43
投票

基本上,您需要在客户端中使用

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


15
投票

您可以执行以下操作:

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

5
投票

您需要将

WebServiceMessage
转换为
SoapMessage
,其中有一个
getSoapHeader()
方法可用于修改标题。反过来,
SoapHeader
有各种添加元素的方法,包括
getResult()
(可以用作
Transformer.transform()
操作的输出)。


5
投票
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;

}
  

0
投票

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

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>

-1
投票

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);
        
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.