Search for software conversations

Is it possible to get a CDI conversation instance programmatically, only knowing that the current thread is the one used to handle the CDI request associated with the wanted conversation? And if possible, how?

In particular, I want to do the following:

 @ConversationScoped public class UnitOfWork {...} public class Client { @Inject transient UnitOfWork uof; ... } public class Room { @Inject transient UnitOfWork uof; ... } 

but using a software mechanism to initialize uof instance uof instead of using the @Inject annotation (because Client and Room are objects and they do not support injection).
I already tried to introduce UnitOfWork using the BeanManager obtained by the following static method:

 public static <B> B getManagedBean(Class<B> type, Annotation... qualifiers) { try { BeanManager beanManager = InitialContext.doLookup("java:comp/BeanManager"); Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers); Bean<B> bean = (Bean<B>) beanManager.resolve(beans); CreationalContext<B> cc = beanManager.createCreationalContext(bean); return bean.create(cc); } catch (NamingException e) { throw new RuntimeException("", e); } } 

but the problem is that the beans specified using the above method are new (each call gives a new instance), and I need Client and Room share the same instance with the UnitOfWork talk UnitOfWork .

+4
source share
2 answers

The answer was very close, but I did not pay attention to it. Yes, you can get an instance of the bean class of any bean contained in any of the active contexts (associated with the current thread) using BeanManager. This method does the job:

 public static <B> B getContextualBeanInstance(Class<B> type, Annotation... qualifiers) { try { BeanManager beanManager = InitialContext.doLookup("java:comp/BeanManager"); Set<Bean<?>> beans = beanManager.getBeans(type, qualifiers); Bean<?> bean = beanManager.resolve(beans); CreationalContext<?> cc = beanManager.createCreationalContext(bean); return (B) beanManager.getReference(bean, type, cc); } catch (NamingException e) { throw new RuntimeException("", e); } } 

The only difference from the method that I mentioned in the question column is that instead of Bean#create(..) , BeanManager#getReference(..) .

If you want to support parameterized bean types, change the type parameter type from Class<B> to type .

If the bean is dependent on @Dependent, you should take care to destroy the bean class instance to avoid memory leaks. Here I will explain how to do it.

+1
source

Sorry, not a real answer, but too much to write in a comment:

There are reasons why entities do not support dependency injection - mainly because their life cycle is separate from the life cycle of managed beans.

Although I, of course, see use cases for DI in entities, I would double (and triple) check if the advantages of this approach exceed the risk. Perhaps you can crack the persistence context in some second-level cache;)

+2
source

Source: https://habr.com/ru/post/1432188/


All Articles