Right - I just found your code. The limitation you mention - async processors, threads(), multicast() - is exactly what the approach I describe is meant to overcome.
When a situation like that happens, i.e. a new thread takes over, it gets a copy of the original exchange, and an ExchangeCreateEvent is fired in it, allowing a listener to set the copy of exchange on the new thread's ThreadLocal. This should provide continuity of route scope. This is what the author of the code I point to claims, and it seems to work. My main question is: is this guaranteed to work? I.e., if adjacent components A and B on the same route are executed by different threads, can I always be sure that the new thread (or threads) executing B will each copy the exchange and fire ExchangeCreatedEvent before executing B? On Thu, Aug 27, 2015 at 8:19 PM, Romain Manni-Bucau <[email protected]> wrote: > this is what I used to implement an @ExchangeScoped but it has several > limitation, in particular when breaking the flow with .threads() or > .multicast(). All is explained on > http://camel.apache.org/threading-model.html . > > Using a camel interceptor would surely allow to pass the context through > the exchange and therefor avoid this ThreadLocal but this needs few more > setup and is less "magic". > > > Romain Manni-Bucau > @rmannibucau <https://twitter.com/rmannibucau> | Blog > <http://rmannibucau.wordpress.com> | Github < > https://github.com/rmannibucau> | > LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber > <http://www.tomitribe.com> > > 2015-08-27 20:13 GMT+02:00 Jan Zankowski <[email protected]>: > > > Just wanted to ping the thread in the hope someone will offer help.. I > > think the answer may also be useful to people in other situations who > > wonder how Camel works under the hood with regard to threads. Thanks! > > > > On Mon, Aug 24, 2015 at 12:47 PM, Jan Zankowski <[email protected] > > > > wrote: > > > > > Hi, > > > > > > My goal is to implement DB multitenancy in a Camel application using > > > Hibernate and Spring. For this, I need to implement the following > > Hibernate > > > interface, which gets called on each read/write to the DB. > > > > > > public interface CurrentTenantIdentifierResolver { > > > public String resolveCurrentTenantIdentifier(); > > > [...] > > > } > > > > > > Because the method doesn't take any parameters, it either needs to use > > (1) > > > some static context knowing which tenant the current route execution > > > belongs to, or (2) a dependency-injected manager holding such a > context. > > > > > > (1) points me to using ThreadLocal holding the current Exchange as it > > > travels down the route. The Exchange can have some custom field > > indicating > > > the tenant. > > > (2) requires using "route scope" - where each route execution gets its > > own > > > instance of context manager injected into > > CurrentTenantIdentifierResolver. > > > Implementing the route scope, however, seems to require the same as > (1) - > > > ThreadLocal referencing the Exchange. > > > > > > I found the following article (& Git repo) implementing "route scope" > > > exactly in this way: > > > https://blog.jyore.com/2015/01/spring-camel-route-bean-scoping/ It > > claims > > > to take advantage of the fact that if a new thread starts processing > the > > > Exchange as it travels down the route, for example after a > > > parallel-processing multicast, the new thread gets a copy of the > original > > > Exchange, and an ExchangeCreatedEvent is fired, allowing a listener to > > set > > > the ThreadLocal on the new thread. > > > > > > I was able to get this to work, though clearing of the ThreadLocal on > > > ExchangeCompletedEvent doesn't work as the author claims, because the > > event > > > is fired on a different thread (I checked). > > > > > > Such issues make me wonder if it's safe to use such a solution. > > > > > > I have the following questions in particular: > > > (a) Let's assume an Exchange E is travelling down a route with a > segment > > > ... -> A -> B -> ... If A and B are executed by different threads, is > it > > > guaranteed that the new thread (or threads) executing B will each copy > > the > > > exchange and fire ExchangeCreatedEvent before executing B? > > > (b) Why is ExchangeCompletedEvent sent by a different thread than the > one > > > executing L, the last endpoint on the route? Can I use some other hook > to > > > clear the ThreadLocal on the thread executing L, after L is executed? > > Maybe > > > a custom RoutePolicy, custom SynchronizationAdapter, or onCompletion()? > > > (c) Can Asynchronous Routing Engine or AsyncProcessors cause any > problems > > > in this setup? (If the answer to (a) is "yes", I'd assume they won't > > cause > > > problems.) > > > (d) Any other caveats? > > > > > > This thread is related: > > > > > > http://camel.465427.n5.nabble.com/Clearing-ThreadLocal-when-exchange-completes-td5729849.html > > > > > > Many thanks! > > > Jan > > > > > >
