【问题标题】:Providing EntityManager by an @ConversationScoped method通过 @ConversationScoped 方法提供 EntityManager
【发布时间】:2011-10-02 13:05:29
【问题描述】:

我尝试在 JBoss7 中运行由 maven archetype groupId: org.fluttercode.knappsack , artifactID: jee6-sandbox-archetype 生成的简单 JEE6 应用程序。 (通过这个turial,对不起,德语)

但是,当调用欢迎 JSF 时,我收到以下错误消息:

org.jboss.weld.exceptions.IllegalProductException: WELD-000053 Producers 
  cannot declare passivating scope and return a non-serializable class:  
  [method] @Produces @DataRepository @ConversationScoped 
  public org.rap.jee6project.bean.DataRepositoryProducer.getEntityManager()
org.jboss.weld.bean.AbstractProducerBean.checkReturnValue(AbstractProducerBean.java:264)
org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:362)
org.jboss.weld.context.AbstractContext.get(AbstractContext.java:122)

确实,应该返回 EntityManager 实例的 DataRepositoyProducer 类被定义为以下注释:

@Stateless
public class DataRepositoryProducer {


private EntityManager entityManager;

@Produces @DataRepository @ConversationScoped
public EntityManager getEntityManager() {
    return entityManager;
}

@PersistenceContext
public void setEntityManager(EntityManager entityManager) {
    this.entityManager = entityManager;
}

} 

如果我使用@RequestScoped,应用程序将按承诺运行。我想知道为什么其他完成本教程的人没有遇到这个问题?以及如何正确修复它(使用@RequestScoped 意味着为每个用户请求重新创建bean,对吗?我预计效率不是很高)

官方 JEE6 教程说:“使用会话、应用程序或会话范围的 Bean 必须是可序列化的,但使用请求范围的 bean 不必是可序列化的”。但是,这似乎不是问题所在,因为服务器并没有抱怨 bean 不可序列化,而是生产者 bean 的产品。

【问题讨论】:

  • 它在使 DataRepositoryProducer 成为有状态 bean 并将整个类注释为 @ConversationScoped 时起作用。不知道我是否应该对这个解决方案感到满意。也许,生产者的概念并不是容器提供对象(如 EntityManager)的最佳实践。

标签: java-ee-6 cdi entitymanager jboss-weld conversation-scope


【解决方案1】:

应该是..

@Stateful
@ConversationScoped
public class ProducerCreator implements Serializable{
    @PersistenceConText
    private EntityManager entityManager;
    ....
}

如果你想在每个对话中使用相同的实体上下文,它应该是

@PersistenceContex(type = PersistenceContextType.EXTENDED)

最后,如果你想有服务层,应该创建有状态并注入到会话 bean

【讨论】:

  • 谢谢,这就是我在评论中提到的解决方案。我想知道是否应该使用 Producer 来获取 EntityManager 实例,因为有状态的 EJB 会损害可伸缩性。为什么不以 JEE5 方式注入它,直接使用 @PersistenceContext 而不是使用专用的生产者 bean。
  • 默认情况下 EntityManager 是事务范围的。我认为,将 entityManager 更改为对话范围是没有意义的。让我们看看Seam Persistence Module seamframework.org/Seam3/PersistenceModule,如果你真的想制作EntityManager。
【解决方案2】:

我在 jboss7 上运行演示时遇到了同样的问题。

只需在 getEntityManager() 中删除 @ConversationScoped 就可以让我部署它。

虽然有些瑕疵:

javax.servlet.ServletException: javax.faces.component.StateHolderSaver cannot be cast to [Ljava.lang.Object;    
javax.faces.webapp.FacesServlet.service(FacesServlet.java:606) 
org.jboss.weld.servlet.ConversationPropagationFilter.doFilter(ConversationPropagationFilter.java:62)

我不确切知道,如果它是相关的,但我想是的。

【讨论】:

    【解决方案3】:

    记住:EntityManager是不可序列化的,所以不能存储在ConversationScope

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 2017-09-15
      • 1970-01-01
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-16
      • 2012-09-26
      相关资源
      最近更新 更多