11

我正在开发一些基于 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>

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

提前致谢。

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

4

3 回答 3

10

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

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

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

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

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

不幸的是,我还没有找到关于 CXF 拦截器的好的参考资料。

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

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

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

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

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

非常感谢@ericacm 的回答。

于 2012-04-19T12:06:36.273 回答
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>

你不能对<soap:Fault>, <faultcode> and <faultstring>元素做任何事情。但一切都是<ValidationFault>习惯</ValidationFault>

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

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

于 2012-04-17T22:19:35.103 回答
0

另一种选择是使用CXF 变换功能

<entry key="Fault" value="ResponseState=..."/>

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

于 2018-04-04T10:06:47.360 回答