2012-04-21 29 views
0

我有一個基於JSF 2 @ViewScoped的web應用程序,我不能讓事務正確地進行,或者說:它們根本不會啓動無法啓動JSF @ViewScoped @Stateless bean

我也使用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頁面用來顯示一個DataTable一個簡單的列表。由於它具有基於AJAX的操作來添加項目,移除項目並通過RichFaces(過濾)對其進行排序,因此它被視爲範圍。

我爲每個啓動事務的方法調用添加了@Stateless(或者如果不存在,則創建一個新的,默認值爲TransactionAttributeType.REQUIRED)。這個想法來自於「核心JavaServer Faces,第三版」一書,但是我還沒有找到任何能夠匹配我自己的例子。

注入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(基本上是從亞當邊的例子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頁面訪問:

<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: [email protected] 
    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。

回答

3

您正在使用CDI放棄JSF註釋。 JSF註釋不會像CDI那樣控制EJB。您可能會將容器與正在使用的註釋混淆。您也可以使用MyFaces CODI進行一些擴展,或者查看使用CDI重新創建ViewScope。網上有幾個例子。

+0

謝謝。Seam 3面臨我正在尋找的解決方案嗎?我終於想知道其他人如何在沒有CDI的普通Java EE 6中從這樣的@ViewScoped bean獲取事務。這將如何工作/看起來像? – Kawu 2012-04-22 00:25:57

+1

是的,它可以工作,但是,Seam 3沒有被積極開發。工作正在進入DeltaSpike,但我們尚未解決JSF問題。至於另一個問題,您將爲UserTransaction執行JNDI查找並手動處理事務邊界。 – LightGuard 2012-04-23 03:44:14

+0

那麼,現在我只需要一個解決方案,可以開始交易**。我會繼續關注DeltaSpike,請參閱http://www.infoq.com/news/2012/04/seam-deltaspike。感謝這個頂級信息! – Kawu 2012-04-23 10:36:30

相關問題