簡體   English   中英

如何處理Out Fault Interceptors中的運行時異常,Apache CXF

[英]How to handle Runtime Exception in Out Fault Interceptors, Apache CXF

我們使用的是最新版本的Apache CXF 3.1.6 ,我在代碼中發現了一個有趣的情況。

假設我們有一個名為InterceptorA的攔截InterceptorA ,在我們的例子中我們希望它觸發正常輸出和錯誤輸出,所以我們在兩者中都注冊了它:

  • OutInterceptors
  • OutFaultInterceptors

InterceptorA調用一個拋出RuntimeException的服務時,樂趣就開始了。

  1. 如果在常規攔截器鏈中發生這種情況, InterceptorA將被調用兩次! 因為拋出RuntimeException時。 我們輸入故障鏈,再次呼叫InterceptorA ,然后再次呼叫該服務......

  2. 我們不可避免地在故障鏈中得到一個RuntimeException 現在,由於我不理解的原因,CXF返回HTTP 200空消息

所以...

對於雙重調用問題,我正在考慮Message一個簡單標志,說明之前是否調用了InterceptorA 如果沒有,我們可以做常規。 但問題仍然存在,當我們在故障鏈中並且發生RuntimeException時。

為什么結果200 OK? 為什么身體是空的?

為了使問題完整,我提供了這種情況的日志。 我加快了這個過程。 首先我們可以看到Fault: Service error ,這是我在服務中強制執行的RuntimeException 我們進入out故障鏈然后我拋出RuntimeException: Interceptor error 接下來我要觀察的是SoapUI中的空響應。

16-06-22 19:12:36 [W] [LogUtils.java:449] Application {http://domain.com/service/}EEMediationServiceImplService#{http://domain.com/service/}transfer has thrown exception, unwinding now
org.apache.cxf.interceptor.Fault: Service error
    at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:162) ~[cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.createFault(AbstractJAXWSMethodInvoker.java:267) ~[cxf-rt-frontend-jaxws-3.1.6.jar:3.1.6]
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:128) ~[cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.jaxws.AbstractJAXWSMethodInvoker.invoke(AbstractJAXWSMethodInvoker.java:232) ~[cxf-rt-frontend-jaxws-3.1.6.jar:3.1.6]
    at org.apache.cxf.jaxws.JAXWSMethodInvoker.invoke(JAXWSMethodInvoker.java:85) ~[cxf-rt-frontend-jaxws-3.1.6.jar:3.1.6]
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:74) ~[cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:59) ~[cxf-core-3.1.6.jar:3.1.6]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_91]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_91]
    at org.apache.cxf.interceptor.ServiceInvokerInterceptor$2.run(ServiceInvokerInterceptor.java:126) ~[cxf-core-3.1.6.jar:3.1.6]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_91]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_91]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
Caused by: java.lang.RuntimeException: Service error
    at pl.ds.eemediation.service.INServiceStub.transfer(INServiceStub.java:64) ~[classes/:na]
    at pl.ds.eemediation.service.EEMediationServiceImpl.transfer(EEMediationServiceImpl.java:102) ~[classes/:na]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_91]
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_91]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_91]
    at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_91]
    at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.jaxws.JAXWSMethodInvoker.performInvocation(JAXWSMethodInvoker.java:66) ~[cxf-rt-frontend-jaxws-3.1.6.jar:3.1.6]
    at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-core-3.1.6.jar:3.1.6]
    ... 10 common frames omitted
16-06-22 19:12:36 [W] [LogUtils.java:449] Application {http://domain.com/service/}EEMediationServiceImplService#{http://domain.com/service/}transfer has thrown exception, unwinding now
java.lang.RuntimeException: Interceptor error
    at pl.ds.eemediation.antifraud.interceptors.AntifraudInterceptor.handleMessage(AntifraudInterceptor.java:45) ~[classes/:na]
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) [cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:112) [cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.phase.PhaseInterceptorChain.wrapExceptionAsFault(PhaseInterceptorChain.java:366) [cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:324) [cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) [cxf-core-3.1.6.jar:3.1.6]
    at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:254) [cxf-rt-transports-http-3.1.6.jar:3.1.6]
    at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:234) [cxf-rt-transports-http-jetty-3.1.6.jar:3.1.6]
    at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:70) [cxf-rt-transports-http-jetty-3.1.6.jar:3.1.6]
    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1129) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1065) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:215) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:97) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.Server.handle(Server.java:499) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:311) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:257) [jetty-server-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.io.AbstractConnection$2.run(AbstractConnection.java:544) [jetty-io-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:635) [jetty-util-9.2.15.v20160210.jar:9.2.15.v20160210]
    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:555) [jetty-util-9.2.15.v20160210.jar:9.2.15.v20160210]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=ResponseInfo{HTTP/1.1 200 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@1cb2eb9d] generate: NEED_HEADER (null,[p=0,l=0,c=0,r=0],false)@START
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=ResponseInfo{HTTP/1.1 200 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@1cb2eb9d] generate: FLUSH ([p=0,l=117,c=8192,r=117],[p=0,l=0,c=0,r=0],false)@COMMITTED
16-06-22 19:12:36 [D] [WriteFlusher.java:295] write: WriteFlusher@40c8dabd{IDLE} [HeapByteBuffer@e0d40e5[p=0,l=117,c=8192,r=117]={<<<HTTP/1.1 200 OK\r\n....v20160210)\r\n\r\n>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}]
16-06-22 19:12:36 [D] [WriteFlusher.java:118] update WriteFlusher@40c8dabd{WRITING}:IDLE-->WRITING
16-06-22 19:12:36 [D] [ChannelEndPoint.java:188] flushed 117 SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,W,6543/200000,HttpConnection}{io=0,kio=0,kro=1}
16-06-22 19:12:36 [D] [WriteFlusher.java:118] update WriteFlusher@40c8dabd{IDLE}:WRITING-->IDLE
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=ResponseInfo{HTTP/1.1 200 null,-1,false},cb=org.eclipse.jetty.server.HttpChannel$CommitCallback@1cb2eb9d] generate: DONE ([p=117,l=117,c=8192,r=0],[p=0,l=0,c=0,r=0],false)@COMMITTED
16-06-22 19:12:36 [D] [Server.java:502] RESPONSE /eemediation-ws/EEMediationServicePort  200 handled=true
16-06-22 19:12:36 [D] [HttpChannelState.java:289] HttpChannelState@da912da{s=DISPATCHED i=true a=null} unhandle DISPATCHED
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=null,cb=Blocker@3b2f9996{null}] generate: CONTINUE (null,[p=0,l=0,c=0,r=0],true)@COMPLETING
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=null,cb=Blocker@3b2f9996{null}] generate: NEED_CHUNK (null,[p=0,l=0,c=0,r=0],true)@COMPLETING
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=null,cb=Blocker@3b2f9996{null}] generate: FLUSH (null,[p=0,l=0,c=0,r=0],true)@COMPLETING
16-06-22 19:12:36 [D] [WriteFlusher.java:295] write: WriteFlusher@40c8dabd{IDLE} [HeapByteBuffer@44cb4d4a[p=0,l=5,c=1024,r=5]={<<<0\r\n\r\n>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}]
16-06-22 19:12:36 [D] [WriteFlusher.java:118] update WriteFlusher@40c8dabd{WRITING}:IDLE-->WRITING
16-06-22 19:12:36 [D] [ChannelEndPoint.java:188] flushed 5 SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,W,3/200000,HttpConnection}{io=0,kio=0,kro=1}
16-06-22 19:12:36 [D] [WriteFlusher.java:118] update WriteFlusher@40c8dabd{IDLE}:WRITING-->IDLE
16-06-22 19:12:36 [D] [HttpConnection.java:657] org.eclipse.jetty.server.HttpConnection$SendCallback@5b033b51[PROCESSING][i=null,cb=Blocker@3b2f9996{null}] generate: DONE (null,[p=0,l=0,c=0,r=0],true)@END
16-06-22 19:12:36 [D] [HttpConnection.java:373] unconsumed input HttpConnection@3359b3ac[FILLING,SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,1/200000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=CONTENT,877 of 877},g=HttpGenerator{s=END},c=HttpChannelOverHttp@38d29a84{r=1,c=true,a=COMPLETED,uri=/eemediation-ws/EEMediationServicePort}]
16-06-22 19:12:36 [D] [HttpParser.java:1232] parseNext s=CONTENT HeapByteBuffer@9b849ba[p=1229,l=1229,c=8192,r=0]={POST /eemediation...apenv:Envelope><<<>>>\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
16-06-22 19:12:36 [D] [HttpParser.java:1587] CONTENT --> END
16-06-22 19:12:36 [D] [HttpChannel.java:705] HttpChannelOverHttp@38d29a84{r=1,c=true,a=COMPLETED,uri=/eemediation-ws/EEMediationServicePort} messageComplete
16-06-22 19:12:36 [D] [HttpInput.java:272] HttpInputOverHTTP@4b5e5f5a EOF
16-06-22 19:12:36 [D] [ChannelEndPoint.java:142] filled 0 SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,2/200000,HttpConnection}{io=0,kio=0,kro=1}
16-06-22 19:12:36 [D] [HttpConnection.java:322] HttpConnection@3359b3ac[FILLING,SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,3/200000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=END,877 of 877},g=HttpGenerator{s=END},c=HttpChannelOverHttp@38d29a84{r=1,c=true,a=COMPLETED,uri=/eemediation-ws/EEMediationServicePort}] filled 0
16-06-22 19:12:36 [D] [HttpInput.java:151] HttpInputOverHTTP@4b5e5f5a eof EOF
16-06-22 19:12:36 [D] [HttpParser.java:1563] reset HttpParser{s=END,877 of 877}
16-06-22 19:12:36 [D] [HttpParser.java:1587] END --> START
16-06-22 19:12:36 [D] [HttpChannel.java:448] HttpChannelOverHttp@38d29a84{r=1,c=false,a=IDLE,uri=} handle exit, result COMPLETE
16-06-22 19:12:36 [D] [ChannelEndPoint.java:142] filled 0 SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,6/200000,HttpConnection}{io=0,kio=0,kro=1}
16-06-22 19:12:36 [D] [ChannelEndPoint.java:142] filled 0 SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,6/200000,HttpConnection}{io=0,kio=0,kro=1}
16-06-22 19:12:36 [D] [HttpParser.java:1232] parseNext s=START HeapByteBuffer@e0d40e5[p=0,l=0,c=8192,r=0]={<<<>>>HTTP/1.1 200 OK\r\n...\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00}
16-06-22 19:12:36 [D] [AbstractConnection.java:128] fillInterested HttpConnection@3359b3ac[FILLING,SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,7/200000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@38d29a84{r=1,c=false,a=IDLE,uri=}]
16-06-22 19:12:36 [D] [AbstractConnection.java:275] FILLING-->FILLING_FILL_INTERESTED HttpConnection@3359b3ac[FILLING_FILL_INTERESTED,SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,7/200000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@38d29a84{r=1,c=false,a=IDLE,uri=}]
16-06-22 19:12:36 [D] [AbstractConnection.java:275] FILLING_FILL_INTERESTED-->FILL_INTERESTED HttpConnection@3359b3ac[FILL_INTERESTED,SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,-,-,8/200000,HttpConnection}{io=0,kio=0,kro=1}][p=HttpParser{s=START,0 of -1},g=HttpGenerator{s=START},c=HttpChannelOverHttp@38d29a84{r=1,c=false,a=IDLE,uri=}]
16-06-22 19:12:36 [D] [SelectChannelEndPoint.java:136] Local interests updating 0 -> 1 for SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,R,-,0/200000,HttpConnection}{io=1,kio=0,kro=1}
16-06-22 19:12:36 [D] [SelectorManager.java:480] Queued change org.eclipse.jetty.io.SelectChannelEndPoint$1@3cfd9e43
16-06-22 19:12:36 [D] [SelectorManager.java:602] Selector loop woken up from select, 0/1 selected
16-06-22 19:12:36 [D] [SelectorManager.java:525] Running change org.eclipse.jetty.io.SelectChannelEndPoint$1@3cfd9e43
16-06-22 19:12:36 [D] [SelectChannelEndPoint.java:160] Key interests updated 0 -> 1 on SelectChannelEndPoint@7f7a6aa3{/127.0.0.1:58021<->18085,Open,in,out,R,-,2/200000,HttpConnection}{io=1,kio=1,kro=1}
16-06-22 19:12:36 [D] [SelectorManager.java:599] Selector loop waiting on select

我可以使用JAX-RS和JAX-WS重現您的問題。 似乎從CXF攔截器拋出的異常會逃避JAX-RS / JAX-WS流並且未正確處理。 請參閱我的響應, 將CXF攔截器的異常傳播到異常映射器 ,以獲取客戶端類似的情況。

interceptor.handleMessage的RuntimeException生成一個Fault,響應代碼為:

  • 200,如果您的服務方法最初返回200.正文連接結果和SoapFault
  • 500,如果您的服務方法最初返回其他錯誤代碼。 身體有一個SoapFault

interceptor.handleFault的RuntimeException生成一個Fault,響應代碼為: - 如果您的服務方法最初返回200,則為200.無效的Body。 收到SoapFault但XML無效 - 如果您的服務方法最初返回其他錯誤代碼,則為200。 空身

為什么結果200 OK?

它只能是一個bug。 對於SOAP 1.2,W3C規范指定狀態代碼為400或500,具體取決於故障類型。 見表20, 網址http://www.w3.org/TR/soap12-part2/#tabresstatereccodes

為什么身體是空的?

在所有情況下,身體都不是空的。 在某些情況下,CXF 3.1.6返回SOAP錯誤,真正奇怪的是,如果服務回答200,請將正確答案與soap fault連接!

看一看我所做的真實反應

ID: 1
Response-Code: 200
Encoding: UTF-8
Content-Type: text/xml;charset=UTF-8
Headers: {Content-Length=[199], content-type=[text/xml;charset=UTF-8], Date=[Fri, 01 Jul 2016 06:12:40 GMT], Server=[Apache-Coyote/1.1]}
Payload: <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns2:testWSResponse xmlns:ns2="http://test/"><return>name123</return></ns2:testWSResponse></soap:Body></soap:Envelope>

對攔截器的雙重調用是有道理的。

1) OutInterceptor1.handleMessage() - > RuntimeException

2) OutInterceptor1.handleFault() - >調用因為handleMessage生成了一個Fault 檢查攔截器的javadoc

void handleFault(T message)

調用已成功調用handleMessage的所有攔截器(按相反順序),當鏈的正常執行因某種原因而中止時。

3) OutFaultInterceptor2.handleMessage()調用,因為OutInterceptor1生成了一個Fault。

4) OutFaultInterceptor2.handleFault()調用,因為OutFaultInterceptor2.handleMessage()生成了一個Fault

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM