Exchange state gets OK in a Camel route even after a fault thrown in SwitchYard
Environment
- Red Hat JBoss Fuse Service Works (FSW)
- 6.0
Issue
- In a SwitchYard Camel route, the
Exchange
state can getOK
even though a fault has happened before. - We have two Camel routes. The second route calls some external web service, which returns a SOAP fault. When this is handed back over to the first route the content type and the state change in the
Exchange
. -
Look at the output. At some point it switches over to a fault, and shows the expected content type:
... State -> FAULT ... org.switchyard.bus.camel.fault .................: true ... org.switchyard.contentType ................: {urn:switchyard-quickstart:camel-soap-proxy:1.0}exceptionInfo ...
-
Then, later on in the chain you will see the following:
State -> OK ... org.switchyard.contentType ..........: {urn:switchyard-quickstart:camel-soap-proxy:1.0}reverseResponse ...
-
This is unexpected behaviour. The state and content type should not be lost. The reason for that is, that we registered some transformers in
switchyard.xml
based on the content type. If the content type
is 'response', but the actual message content is 'fault', the transformers are getting called with unexpected data and fail. Our expectation would be that we do not handle the fault, and it is propagated back through the chain, as we do not handle it. - Another interesting fact we noticed. This only happens with the
doTry
anddoCatch
blocks. If we remove them completely, we see the expected behaviour. Removing those blocks is not an option though, as it would mean that there is no handling for Java exceptions anymore. - Proposed two different solutions:
- Adding
handleFault=true
to the route -- This would mean that the fault message is handled in thedoCatch
block. We do not want this though. Instead we want the fault to be propagated. - Adding
handled
todoCatch
-- This does not apply, as this only works once thehandleFault=true
attribute is set.
- Adding
Resolution
Apply the roll-up patch FSW_6.0_1_2015 or later, or upgrade to Fuse 6.2.1 (when it is released).
Workaround
If applying the roll-up patch is temporarily impossible, then one workaround is to add a <log>
step right after the </doTry>
tag as follows:
<route>
...
<doTry>
...
<doCatch>
...
</doCatch>
</doTry>
<log message="..." /> <!-- Add here -->
...
</route>
Root Cause
This is a bug in Apache Camel:
- https://issues.apache.org/jira/browse/CAMEL-8476
- https://bugzilla.redhat.com/show_bug.cgi?id=1202701
This is actually a peculiarity of how try/catch works in Camel. The TryProcessor
has some logic where it iterates over each processor in the try/catch/finally blocks and on each iteration it sets the out
message as the in
message and clears the out
message reference. If the TryProcessor
is the final processor in a route, this results in the out
message being cleared when the route completes regardless of MEP. Unfortunately, the isFailed()
method on DefaultExchange
only looks at the out
message for a fault. SwitchYard checks whether an exchange is failed to see whether to mark the SwitchYard exchange state as FAULT
, so you can see where things go bad here.
With regard to the workaround, adding a processor after the try/catch block triggers code within Pipeline
to actually check if the MEP is in-out, and if it is, to copy the in message reference to the out
message reference. This results in isFailed()
returning the correct value.
This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.
Comments