1

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 @Injecting 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.DeploymentException: 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!

skaffman
  • 398,947
  • 96
  • 818
  • 769
Thor
  • 6,607
  • 13
  • 62
  • 96

3 Answers3

4

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 ;-)

Jan Groth
  • 14,039
  • 5
  • 40
  • 55
  • Thank you for this answer helping me to understand CDI. With the keyowrds you provided I also found this http://www.oracle.com/technetwork/articles/javaee/javaee6overview-141808.html and it works like in your example. The only thing I'm wondering is the `@LoggedIn` annotation. It cannot resolved here! `@Poduces` is resolved to `javax.enterprise.inject.Produces`. – Thor Jun 15 '11 at 11:13
  • 2
    @LoggedIn is a qualifier - your own annotation :-). That's how type-safety works in CDI: Whenever there is more then one bean of a certain type (say User), you'll need to tell the container which user you want to inject - and that's achieved via qualifiers. See here for more details: http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1217 – Jan Groth Jun 15 '11 at 18:03
0

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

Alex Such
  • 471
  • 4
  • 11
  • Yes, see the code. Both beans are `@Named`. I want to access the property of `@SessionScoped` bean from a `@ViewScoped` bean. – Thor Jun 14 '11 at 12:41
  • You are right with pure JSF you have to care about this question. If you are using CDI and e.g. MyFaces CODI, you don't have to care about it any longer. – Dar Whi Aug 27 '11 at 22:20
0

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.

Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • Both scopes are imported from the package `javax.faces.bean` (code above is updated) Fortunately the SeamFaces module is available, and I'll try to use it. I'm still wondering if the **approach** to `@Inject` the property into another bean is allowed in this case. – Thor Jun 14 '11 at 12:58
  • Well, at least seam-faces is available, because I have a maven dependency for it ... – Thor Jun 14 '11 at 13:06
  • Both MyFaces CODI and SeamFaces convert the ViewScoped annotation to a CDI Scope. Take care which one you use right now, because the SeamFaces converter is broken with Weld (https://issues.jboss.org/browse/SEAMFACES-44) – Dar Whi Aug 27 '11 at 22:17