【问题标题】:Override CXF error handling覆盖 CXF 错误处理
【发布时间】:2012-04-29 00:00:23
【问题描述】:

我正在开发一些基于 Web 服务的应用程序,并且我有一个关于 Apache CXF 解组的问题。在我们的项目中,我们使用 CXF 2.4.1 版本。

当某些 SOAP 请求不正确(例如,某些字段是文本而不是数字)时,CXF 会抛出标准 SOAPFaultException 并且 SOAP 响应是使用标准字段构建的,例如:

<soap:Fault>
    <faultcode>soap:Client</faultcode>
    <faultstring>Unmarshalling Error: some field missing</faultstring>
</soap:Fault>

项目要求说万一出现任何故障系统需要以其他格式响应,例如:

<soap:body>
    <ResponseState>
        <ErrorCode>2732</ErrorCode>
        <ErrorMessage>Unmarshalling Error: some field missing</ErrorMessage>
        <ErrorDetails> some details </ErrorDetails>
        <some other fields>
        ...
    </ResponseState>
</soap:body>

所以问题是:我怎样才能以某种方式覆盖这个错误处理并以我的格式而不是默认格式响应?

提前致谢。

附:我试图研究一些 ValidationEventHandler 主体,但它在 CXF 2.0 及更高版本中以其他方式工作。

【问题讨论】:

    标签: java soap cxf


    【解决方案1】:

    您当然可以使用ValidationEventHandler 并抛出一个符合 JAX-WS 故障规范的故障来生成比默认更好的错误响应。但它只允许您进行如此多的自定义 - 会有一些您无法控制的元素。例如,这是来自我的一个应用程序的 ValidationEventHandler 响应:

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
       <soap:Body>
          <soap:Fault>
             <faultcode>soap:Client</faultcode>
             <faultstring>Errors in request</faultstring>
             <detail>
                <ns2:ValidationFault xmlns:ns2="http://notification.ws.foo.com/">
                   <errors>
                      <error>
                         <inputElement>topicId</inputElement>
                         <errorMessage>java.lang.NumberFormatException: For input string: "" [line:6]</errorMessage>
                      </error>
                   </errors>
                </ns2:ValidationFault>
             </detail>
          </soap:Fault>
       </soap:Body>
    </soap:Envelope>
    

    您无法对&lt;soap:Fault&gt;, &lt;faultcode&gt; and &lt;faultstring&gt; 元素执行任何操作。但是从 &lt;ValidationFault&gt;&lt;/ValidationFault&gt; 的所有内容都是自定义的。

    如果您需要对响应进行更详细的控制,则应将字段类型从数字更改为字符串,然后在代码中进行验证,而不是让解组器捕获错误。

    是的,我同意,强制它是一个字符串会很糟糕,但如果响应必须完全符合您在上面指定的内容,那么如果不深入 CXF 而不是 JAX-WS 层(例如使用拦截器)。

    【讨论】:

    • 感谢您的回答。我有一些关于它的cmets。是的,ValidationEventHandler 让您可以抛出自己的异常而不是标准异常。但是,如果您想完全重写响应消息,它无济于事。但是如果我们只接收所有字符串元素,那么我们生成的所有对象都将包含所有这些字符串,然后我们需要“重新发明轮子”来转换和验证所有这些字符串。另一方面:我们的 Web 服务的消费者将如何理解字段的要求?通过 WSDL 文件中的 cmets?所以,IMO,字符串并不是一个很好的决定。
    【解决方案2】:

    好的,经过大量研究,我找到了一些 CXF 错误处理的方法。

    *。 ValidationEventHandler 使您可以抛出自己的异常而不是标准异常。但是您无法更改响应行为,也无法更改 SOAP 响应格式。

    *。另一种改变错误处理的方法是创建自己的拦截器。 CXF 工作流建立在拦截器链上。有 4 种类型的拦截器:inInterceptor、outInterceptor、inFaultInterceptor 和 outFaultInterceptor。

    使用一些巧妙的技巧,您可以通过创建自己的拦截器(将其添加到链中)来更改工作流程,并从链中删除标准拦截器(如果您知道它的类名)。所以你实际上可以做任何你需要的事情。

    但就所有这些拦截器手动编组响应(xmlWriter.writeStartElement() 等)而言,为每个流程阶段编写自己的拦截器可能是一个巨大的挑战。这可能是一大堆工作。

    很遗憾,我没有找到关于 CXF 拦截器的好的参考资料。

    另一件事 - 如果您需要返回常规响应而不是 SOAPFaultException,您可能需要其他信息,例如:返回此响应的实际服务、请求中传递的服务参数等。我没有在拦截器的可访问参数中找到此信息。而且,当然,这样做你欺骗了将返回 OK 而不是真正异常的客户端代码。

    *。将所有参数作为文本设计您的 wsdl 可能不是很好的解决方案:

    一个。如果 wsdl 中没有数据类型和验证规则,您的服务的使用者可能会感到非常困惑。

    b.您需要“重新发明轮子”进行验证。我的意思是您需要编写自己的验证器,这对于一些复杂的规则可能非常困难。同时,XSD 已实施所有这些验证并经过良好测试。

    最后是关于我的情况:我们与需求经理讨论过,并决定在请求中违反 XML 模式要求时允许 CXF 抛出它自己的标准异常。这是一个很好的解决方案,因为现在我们正在使用 XSD 验证的所有功能,并且不会将我们的时间浪费在复杂和无用的工作上。

    非常感谢@ericacm 的回答。

    【讨论】:

    • 感谢您总结您在此问题上所做的研究。我现在面临着类似的挑战。
    【解决方案3】:

    另一种选择是使用CXF Transform 功能

    &lt;entry key="Fault" value="ResponseState=..."/&gt;

    这会将来自服务器的原始故障映射到任何其他故障,以便您的客户端可以接受。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多