I am new to CDI and want to use this for a JSF2 application. The class MyUser
is a simple @Entity
-Bean and a object is created in a @PostConstruct
method in bean:
@Stateful
@Named @javax.faces.bean.SessionScoped
public class UserBean implements Serializable
{
@Named
private MyUser user;
//setter and getter
//@PostConstruct
}
Accessing the user in a JSF pages works like a charm: #{user.lastName}
. But now I want to access this object from other beans, e.g. in this @ViewScopedBean
:
@Named @javax.faces.bean.ViewScoped
public class TestBean implements Serializable
{
@Inject private MyUser user;
}
I want the current (logged in) MyUser user
to be available in a couple of other beans, but I'm not sure how to do this. Simply @Inject
ing it did not work (and I'm pretty sure this would be a litte bit to simple).
13:56:22,371 ERROR [org.jboss.kernel.plugins.dependency.AbstractKernelController]
Error installing to Start: name=vfs:///Applications/Development/
jboss-6.0.0.Final/server/default/deploy/test.ear_WeldBootstrapBean state=Create:
org.jboss.weld.exceptions.DeploymentExc开发者_C百科eption: WELD-001408 Unsatisfied
dependencies for type [MyUser] with qualifiers [@Default] at injection
point [[field] @Inject private test.controller.mbean.TestBean.user]
What is the best approach to access the user
from other beans? JSF1.2 style code like UserBean bean = (UserBean)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("UserBean");
seems seems to be old fashioned!
First of all: You don't want to directly inject entities. Entities are pretty independently controlled by the ORM-framework, and have their own life cycle. Don't use them as managed beans.
According to this definition, JPA entities are technically managed beans. However, entities have their own special lifecycle, state and identity model and are usually instantiated by JPA or using new. Therefore we don't recommend directly injecting an entity class. We especially recommend against assigning a scope other than @Dependent to an entity class, since JPA is not able to persist injected CDI proxies.
See here for details.
To answer your question: You cannot "outject" something like an (authenticated) user, even though this was possible in Seam 2, the whole proxy mechanism of CDI doesn't allow this anymore. What you need to do is the following:
- Write a managed bean which handles the authentication and put it in the correct scope (probably session scope).
- If login succeeds, use an attribute of this bean to store the authenticated user.
- Use a producer method (probably with a qualifier like
@LoggedIn
) to make the user availabe in your application
Inject the user like this:
@Inject
@LoggedIn
private User user
That's the CDI-way ;-)
Is the @Inject ed bean a @Named bean, too?
If it is, has the MyUser bean a lesser scope than the TestBean. Remember that a @ViewScoped bean's managed properties have to be @ViewScoped, @SessionScoped or @ApplicationScoped
CDI does not specify a @ViewScoped
annotation. This is a JSF2 annotation. The only possible annotations allowed are : @RequestScoped
, @SessionScoped
, @ApplicationScoped
, @Dependent
and @ConversationScoped
. The first three are the only JSF scopes allowed by CDI.
If you need to support the @ViewScope
annotation, you'll need write it yourself. Luckily, someone else has done this before.
精彩评论