2011-06-14 45 views
1

我是CDI的新手,希望将其用于JSF2应用程序。类MyUser是一个简单的@Entity -Bean和对象是在@PostConstruct方法豆创建:将实体注入到ViewScoped Bean中

@Stateful 
@Named @javax.faces.bean.SessionScoped 
public class UserBean implements Serializable 
{ 
    @Named 
    private MyUser user; 

    //setter and getter 
    //@PostConstruct 
} 

访问的JSF页面的用户就像一个魅力:#{user.lastName}。但是现在我想从其他bean访问这个对象,例如在此@ViewScopedBean

@Named @javax.faces.bean.ViewScoped 
public class TestBean implements Serializable 
{  
    @Inject private MyUser user; 
} 

我想当前(登录)MyUser user是在其他几个豆可用,但我不知道如何做到这一点。只是@Inject它没有工作(我敢肯定,这将是简单 litte位)。

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] 

什么是从其他豆类访问user的最佳方法是什么?似乎UserBean bean = (UserBean)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("UserBean");似乎是老式的JSF1.2风格代码!

回答

4

首先:你不想直接注入实体。实体由ORM框架完全独立控制,并有自己的生命周期。不要将它们用作托管的bean。

根据这个定义,JPA 实体技术上管理 豆。但是,实体具有其自己特殊的生命周期,状态和 标识模型,通常由JPA实例化或使用新的。 因此我们不建议直接注入一个实体类 。我们 特别建议不要将 范围指定为@Dependent到 实体类,因为JPA无法以 坚持注入CDI代理。

有关详细信息,请参阅here

回答你的问题:即使在Seam 2中这是可能的,你也不能“输出”类似(经过验证的)用户,但CDI的整个代理机制不再允许这样做。你需要做的是以下几点:

  • 编写一个托管bean来处理认证并将其放在正确的作用域(可能是会话作用域)中。
  • 如果登录成功,请使用此bean的属性来存储经过身份验证的用户。
  • 使用生产方法(可能与像@LoggedIn限定符),使用户在速效您的应用程序

注入这样的用户:

@Inject 
@LoggedIn 
private User user 

这就是CDI路;-)

+0

谢谢你的回答,帮助我理解CDI。通过您提供的关键字,我还发现了这个http://www.oracle.com/technetwork/articles/javaee/javaee6overview-141808.html,它的工作方式与您的示例类似。我唯一想知道的是'@ LoggedIn'注释。它不能在这里解决! '@ Poduces'解析为'javax.enterprise.inject.Produces'。 – Thor 2011-06-15 11:13:23

+2

@LoggedIn是一个限定符 - 你自己的注释:-)。这就是类型安全在CDI中的工作原理:只要有多于一个特定类型的bean(比如User),就需要告诉容器哪个用户要注入 - 并且这是通过限定符实现的。详情请参阅:http://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#d0e1217 – 2011-06-15 18:03:26

0

@Inject ed bean也是一个@named bean吗?

如果是,则让MyUser bean的范围小于TestBean。请记住,@ViewScoped bean的托管属性必须是@ViewScoped,@SessionScoped或@ApplicationScoped

+0

是的,看代码。这两个豆都是'@命名'。我想从'@ ViewScoped' bean访问'@ SessionScoped' bean的属性。 – Thor 2011-06-14 12:41:18

+0

对于纯粹的JSF,你必须关心这个问题。如果您正在使用CDI,并且MyFaces CODI,你不必再关心它了。 – 2011-08-27 22:20:32

0

CDI不指定@ViewScoped注释。这是一个JSF2注释。允许的唯一可能的注释是:@RequestScoped,@SessionScoped,@ApplicationScoped,@Dependent@ConversationScoped。前三个是CDI允许的唯一JSF范围。

如果您需要支持@ViewScope注释,则需要自己写。幸运的是,someone else has done this before

+0

这两个范围都从包javax.faces.bean中导入(上面的代码已更新)幸运的是SeamFaces模块可用,我会尝试使用它。我仍然想知道在这种情况下**方法**是否允许将'@ Inject'属性转换为另一个bean。 – Thor 2011-06-14 12:58:36

+0

嗯,至少可以使用seam-faces,因为我有它的maven依赖项... – Thor 2011-06-14 13:06:03

+0

MyFaces CODI和SeamFaces都将ViewScoped注释转换为CDI范围。请注意你现在使用哪一个,因为SeamFaces转换器已经损坏了Weld(https://issues.jboss.org/browse/SEAMFACES-44) – 2011-08-27 22:17:16