You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@camel.apache.org by Jan Zankowski <ja...@gmail.com> on 2015/08/24 12:47:48 UTC

Is it safe to use ThreadLocal to implement route scope for dependency injection?

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

Re: Is it safe to use ThreadLocal to implement route scope for dependency injection?

Posted by Raul Kripalani <ra...@evosent.com>.
Typically what you would do is store the object you want to propagate in an
Exchange property, eg. just before a threads() DSL.

On the other side of the concurrency threshold, you would unwrap the object
back into its thread-bound structure from the Exchange property.

If you have a look at the feature/camel-hystrix branch, I'm implementing
something similar to propagate the HystrixRequestContext, which is
otherwise thread-bound.

Raúl.
On 27 Aug 2015 21:16, "Jan Zankowski" <ja...@gmail.com> wrote:

> 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 <rmannibucau@gmail.com
> >
> 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 <ja...@gmail.com>:
> >
> > > 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 <
> jan.zankowski@gmail.com
> > >
> > > 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
> > > >
> > >
> >
>

Re: Is it safe to use ThreadLocal to implement route scope for dependency injection?

Posted by Jan Zankowski <ja...@gmail.com>.
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 <rm...@gmail.com>
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 <ja...@gmail.com>:
>
> > 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 <jan.zankowski@gmail.com
> >
> > 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
> > >
> >
>

Re: Is it safe to use ThreadLocal to implement route scope for dependency injection?

Posted by Romain Manni-Bucau <rm...@gmail.com>.
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 <ja...@gmail.com>:

> 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 <ja...@gmail.com>
> 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
> >
>

Re: Is it safe to use ThreadLocal to implement route scope for dependency injection?

Posted by Jan Zankowski <ja...@gmail.com>.
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 <ja...@gmail.com>
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
>