Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get only in-service CDI managed beans

Tags:

jsf-2

cdi

My goal is to get a collection of all in-service CDI managed beans (of a certain parent class) from within a JSF2 ExceptionHandlerWrapper. Note the exception handler part is significant because the class is not a valid injection target itself. So my assumption (maybe incorrect) is that my only route is programmatic through BeanManager.

Using BeanManager.getBeans, I can successfully get the set of all beans available for injection. My issue is that when using BeanManager.getReference to obtain the contextual instance of the bean, the bean will be created if it does not already exist. So I am looking for an alternative that will only return instantiated beans. The code below is my starting point

public List<Object> getAllWeldBeans() throws NamingException {
    //Get the Weld BeanManager
    InitialContext initialContext = new InitialContext();
    BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");

    //List all CDI Managed Beans and their EL-accessible name
    Set<Bean<?>> beans = bm.getBeans(AbstractBean.class, new AnnotationLiteral<Any>() {});
    List<Object> beanInstances = new ArrayList<Object>();

    for (Bean bean : beans) {
        CreationalContext cc = bm.createCreationalContext(bean);
        //Instantiates bean if not already in-service (undesirable)
        Object beanInstance = bm.getReference(bean, bean.getBeanClass(), cc);
        beanInstances.add(beanInstance);
    }

    return beanInstances;
}
like image 378
jdessey Avatar asked Nov 15 '13 16:11

jdessey


1 Answers

Here we are...poking through the javadoc I found Context which has two versions of a get() method for bean instances. One of them, when passing in a creational context, has the same behavior as BeanManager.getReference(). However the other just takes a Bean reference and returns either the contextual instance (if available) or else null.

Leveraging that, here is the version of the original method which returns only instantiated beans:

public List<Object> getAllCDIBeans() throws NamingException {
    //Get the BeanManager via JNDI
    InitialContext initialContext = new InitialContext();
    BeanManager bm = (BeanManager) initialContext.lookup("java:comp/BeanManager");

    //Get all CDI Managed Bean types
    Set<Bean<?>> beans = bm.getBeans(Object.class, new AnnotationLiteral<Any>() {});
    List<Object> beanInstances = new ArrayList<Object>();

    for (Bean bean : beans) {
        CreationalContext cc = bm.createCreationalContext(bean);
        //Get a reference to the Context for the scope of the Bean
        Context beanScopeContext = bm.getContext(bean.getScope());
        //Get a reference to the instantiated bean, or null if none exists
        Object beanInstance = beanScopeContext.get(bean);
        if(beanInstance != null){
            beanInstances.add(beanInstance);
        }
    }

    return beanInstances;
}
like image 152
jdessey Avatar answered Jan 03 '23 10:01

jdessey