I'm using Spring's WebServiceTemplate to consume a Soap service. Once in a while this Soap service responds with an invalid XML. I would like to intercept its parser and fix the invalid XML before it is parsed. How could I do that? Right now I'm calling:
wsTemplate.sendSourceAndReceiveToResult(new StreamSource(new StringInputStream(msg)),new StreamResult(stringWriter))
I suppose I have to call sendSourceAndReceive
and define my own SourceExtractor
but that seems like I'm meddling too much on the process when I actually wanted to do something simple.
This is the problem I want to fix:
An invalid XML character (Unicode: 0x1f) was found in the element content of the document.
SystemErr R at org.springframework.ws.soap.saaj.SaajSoapMessageFactory.createWebServiceMessage(SaajSoapMessageFactory.java :210)
That character is accepted in XML 1.1 but the document is described as XML 1.0:
<?xml version="1.0" encoding="utf-8"?>
So what I want is to replace that character for a tab or a space.
I was able to fix the message before it's parsed by decorating the webServiceTemplate's WebServiceMessageFactory as follows:
final WebServiceMessageFactory mfOriginal = myWebServiceTemplate.getMessageFactory();
WebServiceMessageFactory mfDecorator = new WebServiceMessageFactory() {
@Override
public WebServiceMessage createWebServiceMessage(final InputStream inputStream) throws InvalidXmlException, IOException {
InputStream decoratedIs = new InputStream() {
@Override
public int read() throws IOException {
int nextByte = inputStream.read();
// Replacing the invalid character with a tab. Touching nothing else.
if (nextByte == 0x1f) {
nextByte = 0x09;
}
return nextByte;
}
};
return mfOriginal.createWebServiceMessage(decoratedIs);
}
@Override
public WebServiceMessage createWebServiceMessage() {
return mfOriginal.createWebServiceMessage();
}
};
myServiceTemplate.setMessageFactory(mfDecorator);