17

In the context of JEE/CDI, I find myself typically using a CDI static function when I need to retrieve a CDI managed bean statically from a method. For instance:

MyBean myBean = CDI.current().select( MyBean.class ).get()

However, from what I can tell, another equivalent way to accomplish this is using the BeanManager:

BeanManger bm = new InitialContext().lookup( "java:comp/BeanManager" );
Bean<?> bean = bm.resolve(bm.getBeans( MyBean.class ) );
CreationalContext<?> context = bm.createCreationalContext(bean);
MyBean myBean = bm.getReference(bean, cls, context);

So other than being significantly less code to write using the CDI.current() method, what differences are there in using it? It would seem that reverting to using the BeanManager is a much more complex (and potentially error prone?) methodology. From a functional perspective, are there any drawbacks in using the CDI.current() method instead? Does CDI...select() only work for an @ApplicationScope bean? Or can I use with other scoped beans (ex: @Dependent) as well?

I remember reading something about potentially memory leaks using the CDI method, but do not understand how or why this could be the case.

Eric B.
  • 23,425
  • 50
  • 169
  • 316

2 Answers2

13

Both approaches yield similar result however, there are two major differences differences.

  • CDI.current() is something you can you where you cannot simply @Inject BeanManager.
    • It is just a way to get hold of CDI instances from a non-cdi managed object
  • Instance.get() doesn't take a CreationalContext parameter whereas BM.getReference() does.
    • This is crucial difference in a way that when using Instance, the CreationalContext is managed by container - you needn't care about it and especially about releasing the context. If you are using BM.getReference() you firstly need to obtain that context which usually means creating it and that holds you responsible to also release it once you are done working with it.
Siliarus
  • 6,393
  • 1
  • 14
  • 30
  • Thanks for the insight. How is one supposed to release the context? From what I gather from the javadoc when I release the context, I also destroy all the beans that were retrieved by it. Does that imply that the context would be a different context than that of the container's CDI? (Not even sure how that would be possible). If not, wouldn't releasing the context be tantamount to destroying the container's context beans? – Eric B. Nov 02 '18 at 11:32
  • `CreationalContext.release()` is how you release it. What it entails is letting the CDI container handle any related pre destroy methods hooked onto those instances (or disposal methods in case those beans were produced via producer) as well as destroying the instance itself. – Siliarus Nov 03 '18 at 12:51
  • But does that imply them that if I retrieve an ApplicationScoped bean from the container's context via `@Inject` and one from the `BM.createCreationalContexr`, I'll actually have 2 different @AS beans as I will be working with 2 different contexts? If so, how would I use the BM to retrieve the bean from the container managed context (without `CDI.current()`)? – Eric B. Nov 03 '18 at 17:26
  • Go ahead and test it - you will have the same bean (maybe different proxy but same underlying contextual instance). Otherwise it would go against the whole point of AppScoped. CreationalContext is not a context in a "true CDI meaning" (as would be request,session,... contexts) it just help to glue together actual contextual bean and dependent instances linked to it. Please glance at [this chapter](http://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#creational_context) in specification. – Siliarus Nov 04 '18 at 23:04
8

We use these methods for accessing CDI in your non-CDI code. in CDI code we could inject BeanManager and your beans.

JNDI lookup is used in CDI 1.0. after CDI 1.1 we should use CDI class and its static methods.

http://www.next-presso.com/2016/02/cdi-the-spi-who-loved-me/ says

In CDI 1.0 the only solution you had to access CDI bean graph was to retrieve the BeanManager from JNDI ... This verbosity is the proof that the BeanManager is and advanced CDI tool allowing very basic operation on CDI echos system. It’s obviously not the best solution if you just want to access an instance. That’s why, in CDI 1.1 we introduced the abstract CDI class which use Java Service Loader to retrieve a concrete CDI class from the implementation. ... Retrieving an instance becomes as simple as

CDI<Object> cdi = CDI.current();
MyService service = cdi.select(MyService.class).get();
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Mehran Mastcheshmi
  • 785
  • 1
  • 4
  • 12