2012-04-17 83 views
9

我正在研究一些基于Web服务的应用程序,我对Apache CXF解组有一个疑问。在我们的项目中我们使用CXF 2.4.1版本。覆盖CXF错误处理

当一些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> 

所以,问题是:我怎么可以重写这个莫名其妙的错误处理,并在我的回应格式,而不是默认?

在此先感谢。

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

回答

6

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

*。 ValidationEventHandler为您提供抛出自己的异常而不是标准异常的可能性。但是你不能改变响应行为,你不能改变SOAP响应格式。

*。另一种改变错误处理的方法是创建你自己的拦截器。 CXF工作流程建立在拦截器链上。有4种类型的拦截器:inInterceptor,outInterceptor,inFaultInterceptor和outFaultInterceptor。使用一些聪明的黑客,你可以通过创建你自己的拦截器(将它添加到链中),并从链中删除标准拦截器(如果你知道它是类名)来改变工作流。所以你可以做任何你需要的事情。但是,就所有这些拦截器手动编组响应(xmlWriter.writeStartElement()等)而言,为每个流程阶段编写自己的拦截器可能是一个很大的挑战。这可能是一大堆真正的工作。

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

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

*。用所有参数设计你的wsdl文本可能不是很好解决方案:

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

b。你需要“重新发明轮子”进行验证。我的意思是说,你需要编写你自己的验证器,这可能是非常困难的一些复杂的规则。与此同时,XSD已经完成了所有这些验证并进行了良好的测试。

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

非常感谢@ericacm的回答。

+0

感谢您总结了您在这个问题上所做的研究。我现在正面临类似的挑战。 – Withheld 2013-10-02 19:18:14

1

您肯定可以生成比使用ValidationEventHandler的默认错误响应更好的错误响应,并抛出符合JAX-WS Fault规范的错误。但它只会让你有这么多的定制 - 将会有一些你无法控制的元素。例如,这里是从我的应用程序之一的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层更深入(例如使用拦截器)。

+0

感谢您的回答。我对此有一些评论。是的,ValidationEventHandler为您提供抛出自己的异常而不是标准异常的可能性。但如果你想完全重写响应消息,它不能帮你。但是,如果我们只接收到所有的字符串元素,那么我们所有生成的对象将包含所有这些字符串,然后我们需要'重新发明轮子'来转换和验证所有字符串。另一方面:我们的Web服务的消费者将如何理解对领域的要求?通过WSDL文件中的注释?所以,海事组织,字符串并不是很好的决定。 – 2012-04-19 10:45:30

+0

已更新的答案。 – sourcedelica 2012-04-20 01:16:08