我正在针对产生不符合规范的错误的服务器编写一个 SOAP 客户端。 具体而言,故障原因(规范(的Text
元素中缺少 lang
属性。 我正在使用Spring WS 2.4.0。 有没有办法在将响应解析为SaajSoapMessage
之前拦截响应并注入属性? 我尝试创建一个客户端拦截器,但是当它命中拦截器时,xml已经被解析了。 我是否需要创建自己的消息工厂?
我已经在这个答案和这个答案的帮助下解决了这个问题。
当我实例化我的WebServiceGatewaySupport
时,我添加了一个ClientInterceptor
,用于配置 handleFault()
方法:
@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 responsen" + 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;
}
这仅获取源 xml 并通过 xsl 转换运行它。 请务必从标识转换开始,以免丢失内容。 然后,我添加了属性和值,然后删除了现有值。 我的SoapFaultFix.xsl
看起来像这样:
<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>
我喜欢这种方法,因为我发现使用纯 Java 钻研 DOM 很困难,而且我可以轻松地扩展 xsl 以进行其他更改。