在自定义范围内使用注入
Use injections in custom scope
是否可以使用 @SessionScoped
bean 作为自定义范围上下文中的字段?
我正在用 CDI 编写自定义作用域 ("ScreenScoped"),因此它的行为与 CDI 的 @ViewScoped
大致相同(我这样做是因为后者与 WebSphere 不兼容)。到目前为止,我的范围就像 @ApplicationScoped
一样。我想使用我的 @SessionScoped NavigationHandler
class,它在每次用户单击 link 或按钮时调用,以确定我的 ScreenScoped 生命周期何时结束。但是,当我尝试使用 @Inject
ed 字段时确实出现错误。
public class ScreenContext
implements Context
{
@Inject
private NavigationHandler navigationHandler;
...
}
因此出现 NullPointerException @Inject
:
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());
您不能在 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
实现中,您可以使用 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));
}
是否可以使用 @SessionScoped
bean 作为自定义范围上下文中的字段?
我正在用 CDI 编写自定义作用域 ("ScreenScoped"),因此它的行为与 CDI 的 @ViewScoped
大致相同(我这样做是因为后者与 WebSphere 不兼容)。到目前为止,我的范围就像 @ApplicationScoped
一样。我想使用我的 @SessionScoped NavigationHandler
class,它在每次用户单击 link 或按钮时调用,以确定我的 ScreenScoped 生命周期何时结束。但是,当我尝试使用 @Inject
ed 字段时确实出现错误。
public class ScreenContext
implements Context
{
@Inject
private NavigationHandler navigationHandler;
...
}
因此出现 NullPointerException @Inject
:
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());
您不能在 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
实现中,您可以使用 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));
}