开发者

Add SoapHeader to org.springframework.ws.WebServiceMessage

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>
 开发者_如何学Python   </credentials>
  </soap:Header>


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.


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


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).


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;

}
  


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>


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜