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'.
Another walk-around is to add an interceptor and set the soapAction within the
handleRequest()
method that inbound receives theMessageContext
from which theSoapMessage
can be derived;after that you can easily set the soapAction invoking the
setSoapAction()
method.here is the code of the interceptor class:
and of course add the interceptor to the
WebTemplate
:I worked this out but never posted the answer. Here's what I ended up with that works well:
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:
And the
WebServiceTemplate
ignores this part. The above error means that yoursoapAction
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:
Where you can set up properly the header value. Worked for me too. Whole day of reading.