-
1. Re: ExchangeInterceptor As Global Exception Handling
kcbabo Nov 18, 2013 8:19 AM (in response to pzl_mz)Can your provide a small app+test which reproduces this behavior? Looking at how this is handled:
I can see a window where the ExchangeInterceptor can be called twice on the fault path if an exception is thrown after the PROVIDER after() method has been called. It's not immediately apparent to me how this can happen when an Exception is reported twice though. In that scenario, the first call to after() would be a normal message and the second call would be a fault/exception.
For now, you can make sure you only process once by adding a context property to the exchange in your ExchangeInterceptor that indicates the exception was handled. Check for that property in your interceptor code to guard against processing twice. The fix in the runtime to close the window I mentioned above will look similar.
-
3. Re: ExchangeInterceptor As Global Exception Handling
pzl_mz Nov 18, 2013 11:43 AM (in response to kcbabo)I posted an example which should illustrate the behavior. But I don't think that my problem is related to the bug. I just wondered why CamelService gets intercepted in after() even though an exception occurred before in TestService and the the Invoker was set to inOnly.
I tried your suggestion but without success:
public void after(String target, Exchange exchange) throws HandlerException {
Object content = exchange.getMessage().getContent();
if (content instanceof HandlerException) {
if (exchange.getContext().getProperty("error_processed", Scope.EXCHANGE) == null) {
exchange.getContext().setProperty("error_processed", true, Scope.EXCHANGE);
// should happen only once, but still happens twice, why?
}
}
}
-
4. Re: ExchangeInterceptor As Global Exception Handling
igarashitm Dec 2, 2013 6:28 PM (in response to pzl_mz)I'm sorry for taking longer to respond, I just walked through the scenario your application shows. This is correct behavior since this application has 2 SwitchYard exchanges in its entire route. One is for invoking "CamelService" and the other is for invoking "TestService" from the Camel route. The ExchangeInterceptor is being invoked for each SwitchYard exchange. It also happens in the fault route since the SwitchYard processor chain triggers the interceptors on the catch path.
hth,
Tomo
-
5. Re: ExchangeInterceptor As Global Exception Handling
pzl_mz Dec 3, 2013 9:27 AM (in response to igarashitm)Thanks for your feedback. I understand why the interceptor gets called twice but why does the workaround in reply 3) not work?
-
6. Re: ExchangeInterceptor As Global Exception Handling
igarashitm Dec 5, 2013 6:23 PM (in response to pzl_mz)That workaround doesn't work for multiple exchanges - since the context property is exchange scoped, it doesn't survive over the exchange.
2 workarounds come to my mind:
- Cache the root cause of HandlerException in the ThreadLocal field of the ExchangeInterceptor and handle only if the incoming exception is different from cached one. Note that you would need to peel the HandlerException and extract the root cause so you can make sure those are the same Exception.
- If the application always have a single front service and it invokes other services, you may be able to limit the situation of ExchangeInterceptor being fired to that front service with checking provider/consumer name. Those name can be retrieved by exchange.getProvider().getName().
hth
Tomo
-
7. Re: ExchangeInterceptor As Global Exception Handling
pzl_mz Dec 16, 2013 9:12 AM (in response to igarashitm)Thanks for your answer!
Workaround 2) in my case does not work since there's not enough information available in the exchange properties of the front service. So the workaround 1) and 2) combined might work.
Workaround 1) is used to set the HandlerException in ThreadLocal
Workaround 2) is used to remove HandlerException from ThreadLocal
There's still the question why neither exchange.setProperty Scope.EXCHANGE nor exchange.setProperty Scope.MESSAGE work for exchange pattern inOnly in case of an exception.
-
8. Re: ExchangeInterceptor As Global Exception Handling
kcbabo Dec 17, 2013 9:50 PM (in response to pzl_mz)A property scoped at EXCHANGE is available for the life of that exchange, but it does not propagate across multiple exchanges. Going off Tomo's evaluation earlier, it sounds like there are actually two exchanges created (e1, e2) when the app is invoked. If your interceptor sets the property in one exchange (e2) at EXCHANGE scope when the exception is encountered, then it will be present on that exchange for it's lifetime. It will not, however, be present on the other exchange (e1) when your interceptor fires on that.