简体   繁体   中英

Inject CDI managed bean in SystemEventListener

I have used answer of How to disable elements from within a ViewHandler after jsf has embedded the composite component? to programmatically disable all components in all forms. A SystemEventListener catches and disables all components.

What I would like to add is getting some logic from a CDI bean. It appears that I cannot @Inject a CDI bean inside SystemEventListener . Is there some other mechanism to get logic from CDI beans? I have lots of components and it would be very time consuming to add disabled="#{bean.disabled}" to all components. As I understand this is the right approach to "batch disable" or I'm heavily mistaken here?

It seems that you're not using JSF 2.2 yet. Since that version, a lot of JSF artifacts have been made eligible for CDI injection, including SystemEventListener instances. See also What's new in JSF 2.2? - Issue 763 . If you're running JSF 2.0/2.1 on a Servlet 3.0 capable container, then it should be a minimum of effort to upgrade to JSF 2.2.

If you can't upgrade for some reason, then you can always programmatically grab the CDI managed bean via JNDI. The CDI BeanManager instance is available at JNDI name java:comp/BeanManager . Once having it at hands, use the below getReference() utility method to obtain the reference of interest.

public static <T> T getReference(BeanManager beanManager, Class<T> beanClass) {
    Bean<T> bean = resolve(beanManager, beanClass);
    return (bean != null) ? getReference(beanManager, bean) : null;
}

public static <T> Bean<T> resolve(BeanManager beanManager, Class<T> beanClass) {
    Set<Bean<?>> beans = beanManager.getBeans(beanClass);

    for (Bean<?> bean : beans) {
        if (bean.getBeanClass() == beanClass) {
            return (Bean<T>) beanManager.resolve(Collections.<Bean<?>>singleton(bean));
        }
    }

    return (Bean<T>) beanManager.resolve(beans);
}

public static <T> T getReference(BeanManager beanManager, Bean<T> bean) {
    return (T) beanManager.getReference(bean, bean.getBeanClass(), beanManager.createCreationalContext(bean));
}

(source code from OmniFaces Beans / BeansLocal )

So, in a nutshell:

BeanManager beanManager = (BeanManager) new InitialContext().lookup("java:comp/BeanManager");
YourBean yourBean = getReference(beanManager, YourBean.class);
// ...

Or, if you're already using OmniFaces 1.x, or are open to using it, use its Beans utility class (available since 1.6 only):

YourBean yourBean = Beans.getReference(YourBean.class);
// ...

Both return a proxy reference, you could safely assign it as an instance variable of the SystemEventListener class during its construction.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM