在JBoss AS7堆栈上使用ViewScope和避免LazyInitializationException的最简单方法(JSF2,CDI,JPA2,Seam?)

tli*_*ind 3 cdi seam3 jsf-2 jpa-2.0 jboss7.x

我正在尝试建立一个基于JBoss AS7的Web应用程序堆栈,用于满足以下要求的小规模研究原型和学生项目:

  1. 我想使用与Ajax相关的范围,例如ViewScope - 或者可能是MyFaces Orchestra中的(View)AccessScope - 用于我的托管bean,以及PrimeFaces组件.

  2. 基于JPA的持久性应该相当简单,无需处理OpenSessionInView模式等.我对JPA2的主要问题是可怕的LazyInitializationException,尤其是在AJAX调用中.我要求在谈话手动控制.

  3. 我希望尽可能少地使用依赖项,因此主要依赖于JBoss AS7附带的内容.

现在,我已经建立了一个项目,其中包含以下(主要是提供的)Maven依赖项:

  • CDI
  • 冬眠-2.0-API
  • 的jboss-EJB-api_3.1_spec
  • 的jboss-JSF的api_2.1_spec
  • JBoss的数据注解,api_1.1_spec
  • PrimeFaces 3

到目前为止看起来相当苗条.缺少的是对JSF特定范围的进一步支持,并且当在JSF页面中迭代集合时,我总是得到一个LazyInitializationException.现在,我的持久性服务类看起来像这样:

import javax.ejb.Stateful;
import javax.enterprise.context.RequestScoped;

@Stateful @RequestScoped
public class TestEntityService implements Serializable {
    @PersistenceContext(type=PersistenceContextType.EXTENDED)
    private EntityManager entityManager;

    // ... some methods working with the entityManager ...
}
Run Code Online (Sandbox Code Playgroud)

和我的ResourceFactory bean:

public class ResourceFactory {
    @Produces @PersistenceUnit
    private EntityManagerFactory entityManagerFactory;
}
Run Code Online (Sandbox Code Playgroud)

我尝试过失败与组合@Named代替@Stateful@SessionScoped代替@RequestScoped.然而,我发现添加Seam 3 Persistence,Solder&Faces模块似乎可以解决我的大多数问题,但这会为我的项目增加大量的新依赖项(例如,seam-security,prettyfaces,drools,joda-time和其他依赖项) ).

我的问题是:

  1. EJB是否会对LazyInitializationException有任何帮助?或者由于@Stateful注释,我实际上已经在这里使用EJB了吗?我把这个从一个JBoss,作为示例应用程序,但我对所有这些之间的差异心乱如麻@ManagedBean,@Named,@Stateful,@LocalBean注解:我所知道的是,我不知怎么需要我的实体管理器的生命周期绑定到的范围服务bean.

  2. 有没有人知道解决这个问题的其他简单方法?使用EAGER提取不是一种选择,因为如果每个实体不超过一个集合,这似乎只能起作用...

  3. 我刚读过Apache CODI,它似乎是MyFaces Orchestra的CDI继任者.这是Seam Faces的更好选择吗?据我所知,它提供了ViewScope和ViewAccessScope,但在事务管理方面却没有.

如果在这个领域有更多经验的人能够对此有所了解,那将是很好的 - 我目前有点困惑,因为那里有很多库处理类似的问题,尽管大多数显然彼此不相容(参见例如在这里).谢谢!

Ant*_*and 6

你是对的.所有这一切都令人困惑.这种混淆来自JSF2和CDI提供相同的功能.由于这两个规范需要在没有其他规范的情况下工作,因此它们具有范围和EL展示的类似注释.这篇博文详细介绍了这些令人困惑的领域以及如何做出正确的选择.简而言之,当使用带有JSF的CDI时,请始终使用CDI注释或CDI将通过扩展控制的注释(如javax.faces.ViewScoped在项目中有Seam Faces或CODI时)

回答你的问题

  1. 您已经在使用带@Stateful注释的EJB .EJB不会直接帮助你,LazyInitializationException但它们是处理事务和数据库的更自然的选择(你不能@PersistenceContext在pojo CDI bean中使用注释).关于我已经回答的令人困惑的注释
  2. 我对Seam Persistence有很好的经验.此CDI扩展创建一个托管的实体管理器,它存在于对话中并允许在EJB外部使用事务(如果您没有Java EE容器).使用此实体管理器可以显着减少Lazy Lodaing问题.它可以注入一个无状态的EJB来管理你的DAO,这要归功于允许注入不同范围Bean的CDI魔法.与Seam Faces结合使用,您将获得JSF ViewScope对CDI的支持以及与JSF生命周期相关的事务
  3. 我对CODI没有任何经验,似乎带来了嵌套对话等有用的功能.

总而言之,请注意Seam和CODI目前正处于Apache Delta Spike的合并过程中,因此您即将构建的解决方案应在未来一个月内重新评估,以包括Delta Spike.