The Spring-WS client does not define the SOAPAction header

advertisements

I'm sending a SOAP request and the server is complaining that the SOAPAction header is empty. I think I'm setting it right, but obviously I'm not. Wireshark shows it's not set.

@Test
public void testLogin() throws Exception {
    StringBuffer loginXml = new StringBuffer();
    loginXml.append("<soapenv:Envelope xmlns:soapenv=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:ns=\"http://example.com/xyz/2010/08\">");
    loginXml.append("  <soapenv:Header>");
    loginXml.append("    <ns:loginOperationDetails>");
    loginXml.append("    </ns:loginOperationDetails>");
    loginXml.append("  </soapenv:Header>");
    loginXml.append("  <soapenv:Body>");
    loginXml.append("    <ns:LogIn>");
    loginXml.append("      <ns:logInInfo>");
    loginXml.append("        <ns:CustomerAccountId>customer1</ns:CustomerAccountId>");
    loginXml.append("        <ns:Username>JDoe</ns:Username>");
    loginXml.append("        <ns:Password>abc123</ns:Password>");
    loginXml.append("      </ns:logInInfo>");
    loginXml.append("    </ns:LogIn>");
    loginXml.append("  </soapenv:Body>");
    loginXml.append("</soapenv:Envelope>");

    WebServiceTemplate webServiceTemplate = new WebServiceTemplate();
    MessageFactory msgFactory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);
    SaajSoapMessageFactory newSoapMessageFactory = new SaajSoapMessageFactory(msgFactory);
    webServiceTemplate.setMessageFactory(newSoapMessageFactory);

    String uri = "http://xyz.example.com/xyz_1.0/membership.svc/ws";
    webServiceTemplate.setDefaultUri(uri);

    StreamSource source = new StreamSource(new StringReader(loginXml.toString()));
    StreamResult result = new StreamResult(System.out);

    boolean resultReturned = false;
    try {
        resultReturned = webServiceTemplate.sendSourceAndReceiveToResult(source,
            new SoapActionCallback("http://example.com/xyz/2010/08/MembershipService/LogIn"),
            result);
    }
    catch (SoapFaultClientException sfe) {
        logger.error("SoapFaultClientException resultReturned: " + resultReturned, sfe);
        fail();
    }
}

The error I'm getting back from the server says:

500 Internal Server Error
The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://example.com/xyz/2010/08/MembershipService/LogIn'.


A complete answer goes as follow.

While you are using WebServiceTemplate as a class to communicate with the Webservice, I do not understand why but it does not properly fill the HTTP Header.

Some WSDL have a part saying:

<soap:operation
            soapAction="SOMELINK"
            style="document" />

And the WebServiceTemplate ignores this part. The above error means that your soapAction parameter in the header is empty. And it should be not. Check with Wireshark. I did - using some Chrome Soap client and Spring. The second one has an invalid header.


To fix this you need to follow Section 6.2.4 in here: http://docs.spring.io/spring-ws/sites/2.0/reference/html/client.html

What it says is basically add the header part on your own, with WebServiceMessageCallback interface. You can read more in the reference.

Basically it ends up like this:

 webServiceTemplate.marshalSendAndReceive(o, new WebServiceMessageCallback() {

    public void doWithMessage(WebServiceMessage message) {
        ((SoapMessage)message).setSoapAction("http://tempuri.org/Action");
    }
});

Where you can set up properly the header value. Worked for me too. Whole day of reading.