开发者

How do I test a Spring-WS webservice that Requires soapHeaders?

开发者 https://www.devze.com 2023-04-01 21:44 出处:网络
I have a spring-ws (2.0.2) service I have implemented that requires some custom elements in the soap header.I am trying to use Spring\'s MockWebServiceClient to ge开发者_StackOverflownerate a valid re

I have a spring-ws (2.0.2) service I have implemented that requires some custom elements in the soap header. I am trying to use Spring's MockWebServiceClient to ge开发者_StackOverflownerate a valid request to test the dispatcher, marshallers, etc.

The problem I am getting is that the MockWebSerivce only seems to support the Soap Body (the payload).

How can I access the soap request being generated to get the right headers into it?

If there is a better library for doing this other than Spring's MockWebServiceClient, that would be fine too.

Related Links: http://forum.springsource.org/showthread.php?101708-MockWebServiceClient-amp-WS-Security

Add SoapHeader to org.springframework.ws.WebServiceMessage


I had the similar problem when I wanted to test spring web service with Security, I ended up using the Spring Interceptors to modify the header before they reach end point, I enabled the interceptors only for testing.

Create an interceptor, I implemented the SmartEndpointInterceptor, You can use the other interceptors if you choose

public class ModifySoapHeaderInterceptor implements
    SmartEndpointInterceptor 
{
  //WSConstants.WSSE_NS;
   private static final String DEFAULT_SECURITY_URL = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
    private static final String SECURITY_TAG = "Security";
    private static final String SECURITY_PREFIX = "wsse";
    private static final String USER_NAME_TOKEN = "UsernameToken";

    @Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
        throws Exception 
{
      SaajSoapMessage saajSoapMessage(SaajSoapMessage)messageContext.getRequest());
      SOAPHeader soapHeader = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope().getHeader();

       //you can modify header's as you choose
       Name headerElement = saajSoapMessage.getSaajMessage().getSOAPPart()
            .getEnvelope()
            .createName(SECURITY_TAG, SECURITY_PREFIX, DEFAULT_SECURITY_URL);
       SOAPHeaderElement soapHeaderElement = soapHeader
            .addHeaderElement(headerElement);
    SOAPElement usernameToken = soapHeaderElement.addChildElement(
            USER_NAME_TOKEN, SECURITY_PREFIX);

    SOAPElement userNameElement = usernameToken.addChildElement("Username",
            SECURITY_PREFIX);
    userNameElement.addTextNode("userid");//you can inject via spring

    SOAPElement passwordElement = usernameToken.addChildElement("Password",
            SECURITY_PREFIX);
    passwordElement.addTextNode("password");
       return true;
    }
}

Configure this interceptor in spring context

  <sws:interceptors>
     <bean class="prasanna.ws.security.wss4j.ModifySoapHeaderInterceptor"/>
  </sws:interceptors>

This will add the necessary security headers to the message before it reaches the end point, You can still use MockWebServiceClient to test your web service.


As you noted, the MockWebServiceClient sendRequest() method only sets up the SOAP body with the payload given it. It does not touch the SOAP header.

To set up the SOAP header as well you can create a class that implements the RequestCreator interface and sets the SOAP header. Pass an instance of this class to the sendRequest() method.

For example:

class SoapActionCreator implements RequestCreator {

    private final Source payload;

    public SoapActionCreator(Source payload) {
        this.payload = payload;
    }

    @Override
    public WebServiceMessage createRequest(WebServiceMessageFactory webServiceMessageFactory)
            throws IOException {
        WebServiceMessage webServiceMessage =
                new PayloadMessageCreator(payload).createMessage(webServiceMessageFactory);

        SoapMessage soapMessage = (SoapMessage) webServiceMessage;
        SoapHeader header = soapMessage.getSoapHeader();
        // Add an Action element to the SOAP header
        StringSource headerSource = new StringSource(
                "<wsa:Action xmlns:wsa=\"http://www.w3.org/2005/08/addressing\">https://example.com/foo/bar</wsa:Action>");
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.transform(headerSource, header.getResult());

        return webServiceMessage;
    }

}

Then use SoapActionCreator like this:

    SoapActionCreator soapActionCreator = new SoapActionCreator(requestPayload);
    mockClient.sendRequest(soapActionCreator).
            andExpect(payload(responsePayload));

where requestPayload is the SOAP request body and responsePayload is the entire SOAP response (header and body).


I did find the smock library which does what I really wanted: just takes a text file with the whole request in it.

http://code.google.com/p/smock/wiki/SpringWs

It supports the same request and response matchers as the spring provided stuff. It also keeps my tests very self contained. (Rather than a whole new class that would only be used in my test cases.)

0

精彩评论

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

关注公众号