4

I have a problem with spring + hibernate multitenancy when working with @Async: the current tenant can not be resolved, because it is stored in a ThreadLocal which is not inherited to the thread (provided by some TaskExecutor). Any experience in this field?

Thanks in advance! Erwin

bgraves
  • 788
  • 1
  • 11
  • 23
  • Answering my own question: I solved my problem by adding a field `tenant` to the principal (userAccount). The principal is accessible when delegating the security context with `SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);` or by using some of Springs `DelegatingSecurityContext*` - voilà. Of course this can only work if triggering the async method requires a logged in user. – bgraves May 13 '19 at 17:48

1 Answers1

1

I just saw your question. I'm facing the exact same issue and I came up with the following solution, which probably it's not the best but at the moment it's enough for my tasks.

I have taken the idea here How to enable request scope in async task executor and I have slightly modified it because it wasn't working correctly for my needs.

What I did was:

  1. create a TenantAwareThreadPoolExecutor like the link above;
  2. create TenantAwareCallable (it will have a private String tenantName instead of the RequestAttributes (take it in the way you already do)).
  3. Create a singleton component which will store the current tenant which you got from the request.
  4. Save and clear into this component the tenant you need to use in the call() method of the callable.
  5. Now you must change your CurrentTenantIdentifierResolver to get the tenant from that singleton (after having checked the request, otherwise other requests will use the same tenant as that one).

Please note: this will work ONLY if you execute the tasks one after another in a queue style. If you execute some concurrently this approach will not work.

Any ideas for improvements will be accepted.

Community
  • 1
  • 1
Emanuele
  • 131
  • 2
  • 6