2012-04-17 115 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