I am creating a custom CDI scope and am using the BeanManager
to get an injection of my NavigationHandler
custom class. But the beans it returns are quite strange.
So I use the BeanManager that way :
public class ScreenContext implements Context
{
private NavigationHandler getNavigationHandler()
{
final Set<Bean<?>> beans = m_beanManager.getBeans(NavigationHandler.class);
final Bean<?> bean = m_beanManager.resolve(beans);
NavigationHandler reference =
(NavigationHandler) m_beanManager.getReference(bean, NavigationHandler.class,
m_beanManager.createCreationalContext(bean));
System.out.println("Found "+reference+" (hash="+reference.hashCode()+")");
return reference;
}
...
}
I expect, when I use my project using two different browsers, to get two different NavigationHandler
, which are defined that way :
@Named
@WindowScoped
public class NavigationHandler
implements Serializable, INavigationHandlerController
But my debugger returns true
when I test reference1==reference2
. I also get strange hash codes :
Found NavigationHandler@593e785f (hash=1261587818)
Found NavigationHandler@b6d51bd (hash=1261587818)
I don't understand why the hashes used in the toString() are different, but the hash used in hashCode() are the same.
I think I figured out the reason for these two linked problems, that was a tricky one !
m_beanManager.getReference(..)
does not return the NavigationHandler instance, but a proxy which is supposed to select and act as the correct NavigationHandler among the existing ones in the scope's context.Link to understand the concept of Proxy/Context/BeanManager: https://developer.jboss.org/blogs/stuartdouglas/2010/10/12/weld-cdi-and-proxies
So my
getNavigationHandler()
method is not suited for the work : my pool which calls this method will hold NavigationHandler proxies instead of NavigationHandlers. Because my pool is not an@Inject
ed field, the proxy will not get automatically updated by CDI, hence the reference returned is always the one from the last context actively used by a proxy.For the same reason in this output:
In one case I get the hash of the
NavigationHandler
instance, and in the other case I get the hash of theNavigationHandler
's proxy. Yet I don't know which one is which. I am willing to believe the proxy's toString() is used, asbeanManager.getReference(..)
is supposed to serve a new proxy each time, and the hashCode is supposed to be practically unique for object each instances.Link that says every instance's hashcode is unique hashcode and cannot change over time: http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#hashCode%28%29
So the correct way to implement
getNavigationHandler()
is:Link that explains the difference between
beanManager.getReference(..)
andbeanManager.getContext(..).get(..)
: Canonical way to obtain CDI managed bean instance: BeanManager#getReference() vs Context#get()