Inject a @Named @ViewScoped into a @SessionScoped

479 Views Asked by At

I have two beans using @Named, one with @SessionScoped and the other one with @ViewScoped. I can inject the @ViewScoped bean into the @SessionScoped and I try to do the opposite, and I almost works, but I don't have the same instances.

I can see it when I print this.hashCode() inside the @PostContruct method of the view scoped bean and compare it to the one injected inside the session scoped bean.

So I found a solution but I don't know if it is a good practice: inside the @PostContruct method of the view scoped bean after the session scoped bean has been injected, I send the view scoped into the session scoped through a setter.

If I have well understood these objects are tied to the user so it doesn't make any trouble, am I right?

@Named
@ViewScoped
public class ViewScopedBean {

    @Inject
    protected SessionScopedBean sessionScopedBean;

    @PostContruct
    public void init() {

        sessionScopedBean.setViewScopedBean(this);
    }
}

@Named
@SessionScoped
public class SessionScopedBean {

    protected ViewScopedBean viewScopedBean;

    public void setViewScopedBean(ViewScopedBean viewScopedBean) {

        this.viewScopedBean = viewScopedBean;
    }
}
2

There are 2 best solutions below

2
Siliarus On BEST ANSWER

Extracting what I wrote in comments into an answer:

The catch here was that CDI/Weld doesn't @Inject a contextual instance directly but rather hands over proxy instances (for @NormalScoped beans!), which then delegate to one underlying instance of a bean; in this case @ViewScoped bean.

In the question the assumption was made that hashCode() can be used on injected object(s) to verify that they are identical. That, however, does not need to be true as CDI can choose to give you a different proxy for each injection point and hashCode() will be invoked on the proxy object, not the underlying bean instance - hence the differences.

Way to go is checking bean's internal state, which proved to be equal therefore showing that both injection points have injected the same instance of @viewScoped bean.

3
thobens On

I see two problems:

  1. Your main problem here is that you have circular dependencies. Try to avoid that. The ViewScopedBean cannot depend on the SessionScopedBean and vice versa, because CDI won't know wich one to create first. (That's why you have to set your dependency manually in the @PostConstruct method.)
  2. You can't compare Beans by comparing their references, since they get serialized / unserialized and thus are not the same objects. This is why you should compare them using equals() and implement the hashCode() methods.