处理一个畸形的肥皂故障

时间:2017-04-05 14:34:34

标签: java spring web-services soap

我正在针对服务器编写SOAP客户端,该服务器产生的错误不符合规范。具体而言,错误原因(spec)中的lang元素中缺少Text属性。我正在使用Spring WS 2.4.0。有没有办法拦截响应并在将属性解析为SaajSoapMessage之前注入该属性?我尝试创建一个ClientInterceptor,但是当它到达拦截器时,xml已经被解析了。我需要创建自己的MessageFactory吗?

1 个答案:

答案 0 :(得分:1)

我在this answerthis answer的帮助下解决了这个问题。

当我实例化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 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;
}

这只需要获取源xml并通过xsl转换运行它。从identity transformation开始非常重要,这样您就不会丢失内容。然后我添加了属性和值,然后放入现有值。我的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以进行其他更改。