CDI : invoke a CDI bean inside a standard java class

By | May 19, 2016

These last day, i had to rewrite a project to use CDI. The timing was short so i was not able to rewrite all the architecture to make all classes injectable via CDI. The following solution lets you invoke a CDI Bean inside a standard java class that is not managed by the CDI container and have the benefits of Injection, producer, Event, interceptor etc… .

To make this, we use the BeanManager class with which we can manipulate theĀ  Beans loaded by container in an programmatic manner.

To get this BeanManager class inside our standard class, we just have to write:


BeanManager beanManager = CDI.current().getBeanManager();

Then with the BeanManager instance we can use this snippet of code to get a CDI bean via injection.

public <T> T lookupCDIBean(Class<T> cls, Annotation... annotations) {

    Set<Bean<?>> beans = beanManager.getBeans(cls, annotations);

    Bean<?> bean = beanManager.resolve(beans);

    CreationalContext<?> context = beanManager.createCreationalContext(bean);

    if(bean != null) {

        return (T) beanManager.getReference(bean, cls, context);

    } else {

        throw new Exception("Cannot find a CDI bean with the name :  " + cls.getName());

    }

}

To finish we use this method like this :


lookupCDIBean(MonBeanCDI.class);

lookupCDIBean(MonBeanCDI.class, MyQualifier.class);

That’s all. To finish, just a bemol. This method does not work if your bean is produce with the @produce annotation. The solution is to replace the getReference() method by getInjectableReference(InjectionPoint ip, CreationalContext ctx). The bad thing, it’s that you will have to create manually an injection point.
i don’t find a way to do this. So leave a comment if you have the solution.

See you soon

00

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.