I'm currently going into a huge problem and any help would be highly appreciated.
First of all, the following is occuring in a J2EE environment and I know I shouldn't be managing a Thread myself, but unfortunately I can't change that nor use EJB. The environment is based on the Tomcat Web Container and Weld CDI manager.
My structure contains lots of RESTful services, Service layer and DAO layer implementations, and all of them are getting one another injected by using @Inject and it works fine. The issue comes when I need to get my Service layer injected into my Run method and I get
WELD-001303 No active contexts for scope type javax.enterprise.context.RequestScoped.
I already have a method to return the desired bean with its contextual, as the following code describes:
BeanManager manager = (BeanManager) jndiContext.lookup("java:/comp/BeanManager");
Bean<T> bean = (Bean<T>) manager.getBeans(beanClass).iterator().next();
CreationalContext<?> ctx = manager.createCreationalContext(bean);
return (T) manager.getReference(bean, beanClass, ctx);
But even I use this method I get the error. So, is there any way in which I could inject my beans inside a Thread created and managed by me?
Thank you.
Sorry, but nope - this just won't work.
CDI, as it is, does not support context propagation across threads. It is bound to one thread only. Having it otherwise would present a severe overhead due to synchronization.
As a proof of my thread-bound claim above, look at Weld source code, where there is
ThreadLocal<BeanStore>
used as a storage for beans in given context. The class I refer to in the link is a predecessor to context implementing classes. Also note that this is not Weld-only "problem", any CDI impl out there work on the same basis.You could activate given Context/Scope in a different thread but that means everything will be created anew and any state you had saved in your (for instance)
@ApplicationScoped
bean, will not propagate. Also, with some definitely not nice hacking, you might be able to access the bean store and make a copy to the other thread. That would give you a read-only access but I am not sure how to do that and if that's even worth the efforts.Last but not least, CDI allows you to implements you own context or even supplement your version of built-in contexts. That way you would be able to provide a full-blown version of context working across threads, but there are so many challenged to it, that I am not sure it's doable/reasonable.