0

私は JSF 2@ViewScopedベースの Web アプリケーションを持っていますが、トランザクションを正しく処理できません。つまり、トランザクションがまったく開始されません

Java EE 6 の CDI と EJB3 も使用しています。

メインビーンは次のとおりです。

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 ページから使用され、データテーブルに単純なリストを表示します。アイテムの追加、アイテムの削除、RichFaces による並べ替え (フィルター処理) を行う AJAX ベースの操作があるため、ビュー スコープになりました。

すべてのメソッド呼び出しに対してトランザクションを開始するように追加しまし@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私の知る限り継承されておらず、サブクラスを注入するだけなので、それもコメントアウトしました。

つまり、Bean は JSF ページからアクセスされます。

  <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 です)。

TransactionAttributeType.MANDATORY上のを削除し、拡張エンティティ マネージャを使用すると、トランザクションを使用しなくてもページが正しく表示されることに注意してくださいJpaCrudService。ただし、これはテスト目的のためのものです。

しかし、なぜこれが機能しないのですか?ここでトランザクションが開始されないのはなぜですか? JSF @ViewScopedBean には何かありますか? 非互換?

これをどうやって修理しますか?

PS: JBoss AS 7.1.1 を使用しています。

4

1 に答える 1

3

CDI を使用している場合は、JSF アノテーションを削除してください。JSF アノテーションは、CDI のように EJB を制御しません。コンテナーと使用されている注釈を混同している可能性があります。一部の拡張機能に MyFaces CODI を使用するか、CDI を使用して ViewScope を再作成することもできます。オンラインでいくつかの例があります。

于 2012-04-21T21:29:31.367 に答える