2012-04-21 4 views
0

У меня есть JSF 2 @ViewScoped на основе webapp, что я не могу правильно обрабатывать транзакции, а точнее: они вообще не начинаются.Сделки не начинаются на JSF @ViewScoped @Stateless bean

Я также использую CDI и EJB3 от Java EE 6.

Вот главный боб:

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; 
    } 

    ... 
} 

Вид в области видимости боб используется со страницы JSF, чтобы отобразить простой список в DataTable. Он был создан с учетом области видимости, потому что он имеет операции на основе AJAX для добавления элементов, удаления элементов и сортировки их через RichFaces (фильтрация).

Я добавил @Stateless для каждого вызова метода, чтобы начать транзакцию (или создать новый, если он не существует, по умолчанию TransactionAttributeType.REQUIRED). Эта идея взята из книги «Core JavaServer Faces, 3-е изд.», Однако я не нашел примеров, которые бы соответствовали моим собственным.

Введенный класс 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 (в основном взяты из примера Адама Biên в 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).

Обратите внимание, что страница отображается правильно, без использования транзакций, удалив TransactionAttributeType.MANDATORY на JpaCrudService и используя расширенный менеджер сущностей, но это было только для целей тестирования.

Но почему это не работает? Почему здесь не начинается транзакция? Есть ли что-нибудь с JSF @ViewScoped bean? Несовместимые?

Как вы это отредактируете?

PS: Я использую JBoss AS 7.1.1.

ответ

3

Вы используете CDI, чтобы удалить аннотации JSF. Аннотации JSF не управляют EJB способом CDI. Вероятно, вы путаете контейнер с используемыми аннотациями. Вы также можете использовать MyDaces CODI для некоторых расширений или посмотреть воссоздание ViewScope с CDI. В Интернете есть несколько примеров.

+0

Спасибо.Is Seam 3 Faces/the solution, которое я ищу? Я, наконец, задаюсь вопросом, что делают другие люди, чтобы получить транзакцию от такого компонента @ViewScoped в простой Java EE 6 без CDI. Как это будет выглядеть/выглядеть? – Kawu

+1

Да, это сработало бы, однако, Seam 3 не активно развивается. Работа идет в DeltaSpike, но мы еще не обращались к JSF. Что касается другого вопроса, вы бы сделали JNDI-поиск для UserTransaction и вручную обработали границы транзакций. – LightGuard

+0

Ну, на данный момент мне просто нужно решение, которое начнет транзакции ** вообще **. Я остановлюсь на DeltaSpike, см. Http://www.infoq.com/news/2012/04/seam-deltaspike. Спасибо за эту верхнюю информацию! – Kawu

Смежные вопросы