Kai Rommel created CXF-7650: ------------------------------- Summary: CXF WS-Provider returns http 200 although an error occurred Key: CXF-7650 URL: https://issues.apache.org/jira/browse/CXF-7650 Project: CXF Issue Type: Bug Components: Core Affects Versions: 3.2.2 Reporter: Kai Rommel Attachments: 0001-WS-Provider-handles-exception-in-fault-handling-and-.patch
Hi, I am faced with the issue, that a CXF WS-Provider returns a http 200, although an error within the WS-Provider occurred. ########################################### Error within the WS-Provider [ qtp1256350655-27] PhaseInterceptorChain DEBUG Invoking handleFault on interceptor org.apache.cxf.ws.policy.ServerPolicyOutFaultInterceptor@53236355 [ qtp1256350655-27] PhaseInterceptorChain WARN Application \{http://cxf.apache.org/hello_world_soap_http}GreeterService#\{http://cxf.apache.org/hello_world_soap_http}greetMe has thrown exception, unwinding now org.apache.cxf.interceptor.Fault: No configured signature username detected at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:237) at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.handleBinding(AsymmetricBindingHandler.java:117) at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessageInternal(PolicyBasedWSS4JOutInterceptor.java:185) at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:109) at org.apache.cxf.ws.security.wss4j.PolicyBasedWSS4JOutInterceptor$PolicyBasedWSS4JOutInterceptorInternal.handleMessage(PolicyBasedWSS4JOutInterceptor.java:96) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:112) at org.apache.cxf.phase.PhaseInterceptorChain.wrapExceptionAsFault(PhaseInterceptorChain.java:374) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:332) at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121) at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:267) at org.apache.cxf.transport.http_jetty.JettyHTTPDestination.doService(JettyHTTPDestination.java:247) at org.apache.cxf.transport.http_jetty.JettyHTTPHandler.handle(JettyHTTPHandler.java:79) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:190) at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253) at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:170) at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155) at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:141) at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:219) at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132) at org.eclipse.jetty.server.Server.handle(Server.java:530) at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:347) at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:256) at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279) at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102) at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:247) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.produce(EatWhatYouKill.java:140) at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131) at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:382) at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:708) at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:626) at java.lang.Thread.run(Thread.java:748) Caused by: org.apache.cxf.ws.policy.PolicyException: No configured signature username detected at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractCommonBindingHandler.unassertPolicy(AbstractCommonBindingHandler.java:92) at org.apache.cxf.ws.security.wss4j.policyhandlers.AbstractBindingBuilder.getSignatureBuilder(AbstractBindingBuilder.java:1863) at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignature(AsymmetricBindingHandler.java:721) at org.apache.cxf.ws.security.wss4j.policyhandlers.AsymmetricBindingHandler.doSignBeforeEncrypt(AsymmetricBindingHandler.java:193) ... 33 more [ qtp1256350655-27] AbstractHTTPDestination DEBUG Finished servicing http request on thread: Thread[qtp1256350655-27,5,main] ################################################## Response within the WS-Consumer [ main] Greeter INFO Inbound Message ---------------------------- ID: 1 Response-Code: 200 Encoding: ISO-8859-1 Content-Type: Headers: \{Date=[Wed, 10 Jan 2018 15:12:24 GMT], Server=[Jetty(9.4.8.v20171121)], transfer-encoding=[chunked]} -------------------------------------- [ main] PhaseInterceptorChain DEBUG Invoking handleMessage on interceptor org.apache.cxf.interceptor.AttachmentInInterceptor@2bb1d0aa As you can see, the http response code is 200 and no body is set. The expected response code is http 500. I attached a patch, which will fix following issues: 1st issue: Message Exchange Pattern (MEP) is request response. I setup a Camel Route with a CXF Endpoint as WS-Provider. I configured WSS (only signing) but NO signature user within the cxf endpoint. In case a error occurs within the Camel Route, above mentioned http 200 code will be returned to the WS-Consumer. Root cause is, that in class PhaseInterceptorChain.java following code snippet handles the exception of the Camel Route: } catch (RuntimeException ex) { if (!faultOccurred) { faultOccurred = true; wrapExceptionAsFault(message, ex); } state = State.ABORTED; } The method wrapExceptionAsFault handles the unwinding and calls faultObserver.onMessage(message); When now a second RuntimeException is thrown, e.g. in one of the OutInterceptors (in my case in the PolicyBasedWSS4JOutInterceptorInternal), this exception disturbs the fault handling and a http 200 without a payload is returned to the WS-Consumer. 2nd issue: MEP is oneway. I am configuring a Onewway WS-Provider within the Camel Route. Again with WSS (only signing) and I am not setting a signature user (is not necessary, as there is no response to sign). In addition I set the property org.apache.cxf.oneway.robust to true. With this setting errors of the Camel Route should be propagated back to the WS-Consumer. In my setup again a http 200 is returned to the WS_Consumer, although a error occurred in the Camel Route and the robust mode is activated. This is caused by the second exception in the fault handling because of the missing signature user within the configuration. I am not sure, whether the fault message should be signed in this case, but nevertheless the return code should be 500 and not 200. Your thoughts are welcome. Regarding my patch: My focus was to return at least a http 500, instead of 200. Therefore I had to modify the PhaseInterceptorChain.java and the fault observer implementation to detect, whether a second exception occurs in the fault handling. Another option would be to modify (in this case with WSS) the fault handling method implementation of the OutInterceptor PolicyBasedWSS4JOutInterceptorInternal. This method is called via the method wrapExceptionAsFault, when the unwinding is done. What is your opinion? Best regards Kai -- This message was sent by Atlassian JIRA (v7.6.3#76005)