【问题标题】:Use injections in custom scope在自定义范围内使用注入
【发布时间】:2017-02-10 16:18:06
【问题描述】:

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

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

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());

【问题讨论】:

  • 使用BeanManager获取NavigationHandler bean
  • 由于自定义上下文是通过扩展注册的,因此无法执行注入

标签: java scope cdi weld custom-scope


【解决方案1】:

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

您的上下文通过 CDI 扩展注册,观察 CDI 生命周期的 AfterBeanDiscovery 事件。在这里,您将 BeanManager 传递给上下文:

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

然后在您的ScreenContext 实现中,您可以使用BeanManager 获得NavigationHandler bean(在下面的myMethod 中):

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));
   }

【讨论】:

  • 经过测试,我发现即使 NavigationHandler 是 WindowScoped,但从两个不同的浏览器调用时,该方法总是返回相同的对象。
  • 我重新接受了您的回答,因为我的评论是由于另一个问题,该问题已在以下帖子中得到解决:stackoverflow.com/questions/42256767/…
  • 很高兴这对你有帮助:-)
猜你喜欢
  • 2021-11-28
  • 1970-01-01
  • 2018-06-29
  • 1970-01-01
  • 2017-02-15
  • 2016-11-18
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多