在自定义范围内使用注射

时间:2017-02-10 16:18:07

标签: java scope cdi weld custom-scope

是否可以将@SessionScoped bean用作自定义作用域上下文中的字段?

我正在使用CDI编写自定义范围(“ScreenScoped”),因此它与CDI @ViewScoped大致具有相同的行为(我这样做是因为后者与WebSphere不兼容)。到目前为止,我的范围就像@ApplicationScoped那样。我想使用我的@SessionScoped NavigationHandler类,每次用户单击链接或按钮时调用该类,以确定我的ScreenScoped生命周期何时结束。但是,当我尝试使用@Inject ed字段时,我确实收到错误。

public class ScreenContext
    implements Context
{
    @Inject
    private NavigationHandler navigationHandler;
    ...
}

由于此@Inject

而出现NullPointerException
16:55:07,492 SEVERE [javax.enterprise.resource.webcontainer.jsf.application] (http-localhost/127.0.0.1:8443-10) Error Rendering View[/page/hello.xhtml]: javax.el.ELException: /page/hello.xhtml @24,58 visible="#{helloController.popupshowed}": java.lang.NullPointerException

...

Caused by: java.lang.NullPointerException
    at com.mypackage.scope.screenscope.ScreenContext.get(ScreenContext.java:38) [myproject.jar:]

第38行是我第一次调用注入的字段:

System.out.println("Navigation is used: " + navigationHandler.getUserId());

1 个答案:

答案 0 :(得分:2)

您无法在Context中注入Bean。您需要使用BeanManager来访问NavigationHandler bean。

您的上下文是通过CDI Extension观察CDI生命周期的AfterBeanDiscovery事件来注册的。这就是你将BeanManager传递给上下文:

public void afterBeanDiscovery (@Observes final AfterBeanDiscovery event, final BeanManager beanManager)
{
    event.addContext(new ScreenContext(beanManager));
}

然后在您的ScreenContext实施中,您可以使用NavigationHandler获取myMethod bean(位于BeanManager下方):

public class ScreenContext implements Context
{

   private final BeanManager m_beanManager;

   public ScreenContext(final BeanManager p_BeanManager)
   {
      m_beanManager = p_BeanManager;
   }

   public void myMethod()
   {
      NavigationHandler NavigationHandlerBean = getNavigationHandler();
      ...
      ...
   }

   private NavigationHandler getNavigationHandler()
   {
      final Set<Bean<?>> beans = m_beanManager.getBeans(NavigationHandler.class);
      final Bean<?> bean = m_beanManager.resolve(beans);

      return (NavigationHandler) m_beanManager.getReference(bean, NavigationHandler.class, m_beanManager.createCreationalContext(bean));
   }