Ссылка на компонент CDI в неуправляемом компоненте CDI

Можно ли получить экземпляр компонента CDI внутри класса, созданного с использованием new ключевое слово? В настоящее время мы вносим некоторые улучшения в старое приложение, и мы всегда получаем исключение ContextNotActiveException каждый раз, когда выполняем программный поиск компонентов CDI Singleton в нашем приложении.

Код для получения ссылки:

public class ClassCreatedWithNew{
     public void doSomething(){
         MySingletonBean myBean = BeanManagerSupport.getInstance().getBean(MySingletonBean.class);
     }
}

BeanManagerSupport.java

public class BeanManagerSupport {

    private static final Logger LOG = Logger.getLogger(BeanManagerSupport.class);

    private static final BeanManagerSupport beanManagerSupport = new BeanManagerSupport();

    private BeanManager beanManager;

    private BeanManagerSupport() {
        try {
            beanManager = InitialContext.doLookup("java:comp/BeanManager");
        } catch (NamingException e) {
            LOG.error("An error has occured while obtaining an instance of BeanManager", e);
        }
    }

    @SuppressWarnings("unchecked")
    public <T> T getBean(Class<T> clazz) {
        Iterator<Bean< ? >> iter = beanManager.getBeans(clazz).iterator();

        if (!iter.hasNext()) {
            throw new IllegalStateException("CDI BeanManager cannot find an instance of requested type " + clazz.getName());
        }

        Bean<T> bean = (Bean<T>) iter.next();

        return (T) beanManager.getContext(bean.getScope()).get(bean);
    }

    public static BeanManagerSupport getInstance(){
        return beanManagerSupport;
    }
}

2 ответа

Есть 2 возможных решения.

  1. Если у вас есть контейнер JavaEE-7, вы можете использовать CDI.current().get(MySingletonClass.class);

  2. Если у вас есть контейнер JavaEE-6 или даже приложение Java SE, вы можете использовать Apache DeltaSpike BeanProvider. Он пытается найти BeanManager из JNDI, но также выполняет другие приемы, которые также работают, если у вас нет полного контейнера EE. Например, в SE и модульный тест.

Вы также должны позаботиться о том, чтобы загружался не только контейнер, но и чтобы контексты действительно активировались. Обычно это делается через ServletListener. Если вы находитесь в контейнере EE, они регистрируют его для вас. Если вы используете обычный кот, причал и т. Д., То вам нужно активировать его самостоятельно.

Посмотрите этот пример из Apache OpenWebBeans.

если вы используете new, вам необходимо иметь конструктор и вручную инициализировать зависимости и любую логику, которая от них зависит, в методе @PostConstruct. Вместо этого вы можете использовать CDI.current(), например

       MyService service = CDI.current().select(MyService.class).get(); 

тогда вы сможете вызвать все свои методы службы.

Другие вопросы по тегам