我正在开发一些基于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>
所以问题是:如何以某种方式覆盖此错误处理并以我的格式回复,而不是默认?
提前致谢。
P.S。我试图查看一些ValidationEventHandler主体,但它在CXF 2.0及更高版本中以其他方式工作。
答案 0 :(得分:7)
好的,经过大量研究后我发现了一些CXF错误处理方法。
*。 ValidationEventHandler使您可以抛出自己的异常而不是标准异常。但是您无法更改响应行为,也无法更改SOAP响应格式。
*。另一种改变错误处理的方法是创建自己的拦截器。 CXF工作流程建立在拦截器链上。有4种类型的拦截器:inInterceptor,outInterceptor,inFaultInterceptor和outFaultInterceptor。
使用一些智能黑客,您可以通过创建自己的拦截器(将其添加到链)来更改工作流,并从链中删除标准拦截器(如果您知道它的类名)。所以你可以实际做任何你需要的事情。
但是就所有这些拦截器手动编组响应(xmlWriter.writeStartElement()等)而言,为每个流程阶段编写自己的拦截器可能是一个很大的挑战。这可能是真正的大量工作。
不幸的是,我还没有找到关于CXF拦截器的好参考。
另一件事 - 如果您需要返回常规响应而不是SOAPFaultException,您可能需要其他信息,例如:返回此响应的实际服务,请求中传递的服务参数等。我没有在拦截器中的可访问参数中找到此信息。并且,当然,通过这样做,您欺骗客户端代码将返回OK而不是真正的异常。
*。用所有参数设计你的wsdl作为文本可能是非常不好的解决方案:
一个。如果wsdl中没有数据类型和验证规则,那么您的服务的使用者可能会非常困惑。
湾你需要'重新发明轮子'进行验证。我的意思是你需要编写自己的验证器代码,这些验证器在一些复杂的规则下可能非常困难。与此同时,XSD已经实施了所有这些验证并进行了良好的测试。
最后关于我的情况:我们与需求管理器进行了讨论,并决定允许CXF在请求中违反XML模式要求时抛出自己的标准异常。这是一个很好的解决方案,因为现在我们正在使用XSD验证的所有功能,不要把时间浪费在复杂和无用的工作上。
非常感谢@ericacm的回答。
答案 1 :(得分:1)
您当然可以使用ValidationEventHandler
生成比默认值更好的错误响应,并抛出符合JAX-WS Fault规范的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>
的所有内容都是自定义的。
如果您需要对响应进行更详细的控制,那么您应该将字段类型从numeric更改为string,然后在代码中进行验证,而不是让unmarshaller捕获错误。
是的,我同意,强迫它成为一个字符串会很糟糕,但如果响应必须与上面所说的完全相同,那么如果不深入研究CXF而不是JAX-WS层(例如使用拦截器。)
答案 2 :(得分:0)