Is it possible to use a @SessionScoped
bean as a field in a custom scope's Context ?
I am writing a custom scope ("ScreenScoped") with CDI, so that it approximately has the same behavious than CDI's @ViewScoped
(I do this because the latter is not WebSphere-compatible). So far my scope acts like as @ApplicationScoped
would. I would like to use my @SessionScoped NavigationHandler
class, which is called everytime a user clicks a link or button, to determine when my ScreenScoped life-cycle ends. However I do get an error when I try to use an @Inject
ed field.
public class ScreenContext
implements Context
{
@Inject
private NavigationHandler navigationHandler;
...
}
A NullPointerException appears because of this @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:]
Line 38 is the first time I call the injected field:
System.out.println("Navigation is used: " + navigationHandler.getUserId());
You can't inject a Bean in Context
. You need to use the BeanManager
to access the NavigationHandler
bean.
Your context is registered via CDI Extension observing AfterBeanDiscovery
event of CDI lifecycle. That's here that you pass the BeanManager
to the context :
public void afterBeanDiscovery (@Observes final AfterBeanDiscovery event, final BeanManager beanManager)
{
event.addContext(new ScreenContext(beanManager));
}
And then in your ScreenContext
implementation you can get the NavigationHandler
bean (in myMethod
below) using the 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));
}