I'm writing a SOAP client against a server that's producing a Fault that is not up-to-spec. Specifically, the lang
attribute is missing in the Text
element in the Fault Reason (spec). I'm using Spring WS 2.4.0. Is there a way to intercept the response and inject the attribute before it gets parsed into a SaajSoapMessage
? I tried creating a ClientInterceptor, but the xml has already been parsed by the time it hits the interceptor. Would I need to create my own MessageFactory?
Asked
Active
Viewed 1,073 times
0

end-user
- 2,845
- 6
- 30
- 56
1 Answers
1
I've solved this with help from this answer and this answer.
When I instantiated my WebServiceGatewaySupport
, I added a ClientInterceptor
where I configured the handleFault()
method:
@Override
public boolean handleFault(MessageContext messageContext) throws WebServiceClientException {
LOGGER.debug("intercepted a fault.");
TransformerFactory transformerFactory = TransformerFactory.newInstance();
WebServiceMessage response = messageContext.getResponse();
Source source = response.getPayloadSource();
StreamResult streamResult = new StreamResult(new StringWriter());
try {
Transformer displayTransformer = transformerFactory.newTransformer();
displayTransformer.transform(source, streamResult);
LOGGER.debug("\t>> initial response\n" + streamResult.getWriter().toString());
StreamSource xslSource = new StreamSource(new File(
FaultInterceptor.class.getResource("/SoapFaultFix.xsl").getFile()
));
Transformer modifyingTransformer = transformerFactory.newTransformer(xslSource);
modifyingTransformer.transform(source, response.getPayloadResult());
} catch (TransformerException e) {
e.printStackTrace();
}
return true;
}
This simply takes the source xml and runs it through an xsl transformation. It's important to begin with an identity transformation so you don't lose content. I then added the attribute and value, then dropped in the existing value. My SoapFaultFix.xsl
looked like this:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
>
<xsl:template match="/ | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//soapenv:Fault/soapenv:Reason/soapenv:Text">
<soapenv:Text>
<xsl:attribute name="xml:lang">en</xsl:attribute>
<xsl:value-of select="."/>
</soapenv:Text>
</xsl:template>
</xsl:stylesheet>
I liked this approach because I found drilling into the DOM was arduous with pure Java, and I could easily expand the xsl to make other changes.