【问题标题】:Transactions not starting on JSF @ViewScoped @Stateless bean未在 JSF @ViewScoped @Stateless bean 上启动事务
【发布时间】:2012-04-21 15:47:36
【问题描述】:

我有一个基于 JSF 2 @ViewScoped 的 web 应用程序,我无法正确处理事务,或者更确切地说:它们根本没有启动

我也在使用 Java EE 6 的 CDI 和 EJB3。

这是主要的 bean:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
...

@ManagedBean
@ViewScoped
@Stateless
public class PqManager implements Serializable
{
    private List<PqListItem> pqItems;

    @Inject
    private PqService pqService;

    public List<PqListItem> getPqItems()
    {
        if ( pqItems == null )
        {
            pqItems = pqService.findActivePqs();
        }

        return pqItems;
    }

    ...
}

视图范围的 bean 在 JSF 页面中用于显示数据表中的简单列表。它是视图范围的,因为它具有基于 AJAX 的操作来添加项目、删除项目以及通过 RichFaces 对它们进行排序(过滤)。

我为每个方法调用添加了@Stateless 以启动事务(或者如果不存在则创建一个新的,默认为TransactionAttributeType.REQUIRED)。这个想法取自“Core JavaServer Faces, 3rd ed.”一书,但是我没有找到任何与我自己相匹配的示例。

注入的 PqService 类(改用@EJB 没有区别):

@Stateless
public class PqService extends JpaCrudService
{
    ...

    public List<PqListItem> findActivePqs()
    {
        return em.createQuery("SELECT NEW ... whatever not interesting here... WHERE pq.workflow = '" + Workflow.ACTIVE + "' GROUP BY pq.id", PqListItem.class).getResultList();
    }

    ...
}

JpaCrudService(基本上取自 Adam Bien 的示例 http://www.adam-bien.com/roller/abien/entry/generic_crud_service_aka_dao):

//@Stateless
//@Local(CrudService.class)
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public abstract class JpaCrudService implements CrudService
{
    @PersistenceContext(unitName = "PqGeneratorPu")
    protected EntityManager em;

    @Override
    public <T> T create(T t)
    {
        em.persist(t);
        em.flush();
        em.refresh(t);

        return t;
    }

    ...
}

唯一的区别是我将JpaCrudService 子类化,因为我不喜欢存储在实体中/实体处的查询。所以我省略了 @Local 注释(如果错了,请纠正我)。 @Stateless 没有继承 AFAIK,我只注入了子类,所以我也注释掉了。

也就是说,然后从 JSF 页面访问 bean:

  <rich:dataTable value="#{pqManager.pqItems}"
                  var="pq">
    <f:facet name="header">
      <h:outputText value="Active" />
    </f:facet>
    ...

但是,在加载页面时,我得到一个异常:

javax.ejb.EJBTransactionRequiredException: Transaction is required for invocation: org.jboss.invocation.InterceptorContext@7a6c1c92
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.mandatory(CMTTxInterceptor.java:255)
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:184)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.as.ee.component.TCCLInterceptor.processInvocation(TCCLInterceptor.java:45)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
    at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:165)
    at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:173)
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288)
    at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61)
    at org.jboss.as.ee.component.ProxyInvocationHandler.invoke(ProxyInvocationHandler.java:72)
    at de.company.webapp.service.PqService$$$view95.findActivePqsFor(Unknown Source)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.jboss.weld.util.reflection.SecureReflections$13.work(SecureReflections.java:264)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.run(SecureReflectionAccess.java:52)
    at org.jboss.weld.util.reflection.SecureReflectionAccess.runAsInvocation(SecureReflectionAccess.java:137)
    at org.jboss.weld.util.reflection.SecureReflections.invoke(SecureReflections.java:260)
    at org.jboss.weld.bean.proxy.EnterpriseBeanProxyMethodHandler.invoke(EnterpriseBeanProxyMethodHandler.java:111)
    at org.jboss.weld.bean.proxy.EnterpriseTargetBeanInstance.invoke(EnterpriseTargetBeanInstance.java:56)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:105)
    at de.company.webapp.service.PqService$Proxy$_$$_Weld$Proxy$.findActivePqs(PqService$Proxy$_$$_Weld$Proxy$.java)
    at de.company.webapp.facade.PqManager.getPqItems(PqManager.java:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    .
    .
    .

失败是因为调用 pqService.findActivePqsFor() 没有在现有事务中运行(TransactionAttributeType.MANDATORY继承了 AFAIK)。

请注意,通过删除JpaCrudService 上的TransactionAttributeType.MANDATORY 并使用扩展实体管理器,可以在不使用事务的情况下正确显示页面,但这仅用于测试目的。

但是为什么这不起作用?为什么这里没有开始交易? JSF @ViewScoped bean 有什么东西吗?不兼容?

您如何修复此问题?

PS:我使用的是 JBoss AS 7.1.1。

【问题讨论】:

    标签: jsf-2 transactions ejb-3.0 cdi stateless-session-bean


    【解决方案1】:

    如果您正在使用 CDI,请删除 JSF 注释。 JSF 注释不像 CDI 那样控制 EJB。您可能会将容器与正在使用的注释混淆。您还可以将 MyFaces CODI 用于某些扩展或查看使用 CDI 重新创建 ViewScope。网上有几个例子。

    【讨论】:

    • 谢谢。 Seam 3 Faces 是我正在寻找的解决方案吗?我终于想知道其他人如何在没有 CDI 的普通 Java EE 6 中从这样的 @ViewScoped bean 获取事务。这将如何工作/看起来如何?
    • 是的,它会起作用,但是,Seam 3 并没有被积极开发。 DeltaSpike 的工作正在进行中,但我们还没有解决 JSF。至于另一个问题,您将对 UserTransaction 进行 JNDI 查找并手动处理事务边界。
    • 好吧,现在我只需要一个完全开始交易的解决方案。我会密切关注 DeltaSpike,请参阅 infoq.com/news/2012/04/seam-deltaspike。感谢您提供此重要信息!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 2014-02-14
    • 2012-09-29
    • 1970-01-01
    • 2013-02-01
    • 2012-08-27
    相关资源
    最近更新 更多