2014-01-27 2 views
1

Время от времени операция в моем состоянии EJB (3.0) запускает SQLException (время ожидания истекло). Метод, в котором это происходит:Как справиться с отброшенным компонентом сеанса с состоянием

@PersistenceContext(unitName = "MYPU") 
EntityManager entityManager; 

List<Message> list; 

public List<Message> newSearch() { 
    // do some unsignificant things 
    loadFirstPage(); 
} 

@TransactionAttribute(TransactionAttributeType.REQUIRED) 
public List<Message> loadFirstPage() { 
    CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery(); 
    cq.select(cq.from(entityClass)); 
    list = getEntityManager().createQuery(cq).getResultList(); 
} 

Этот SFSB был введен в другой класс:

private MyBean myBean; 
@EJB(name = "messageloaderbean") 
public void setMyBean(MyBean myBean) { 
    this.myBean = myBean; 
} 

А затем его ссылка передается в качестве параметра в классе вызывающего:

public class Controller{ 
    private MyBean myBean; 

    public Controller(MyBean myBean){ 
     this.myBean = myBean; 
    } 
    public void methodThatCallsMyBean(){ 
     this.myBean.newSearch(); 
    } 
} 

Что происходит, если генерируется исключение во время выполнения (например, SQLException), поскольку я использую CMT и, согласно спецификации EJB, заключается в том, что контейнер сначала откатывает транзакцию, а затем отбрасывает EJB. Затем, если я хочу снова использовать этот EJB после его отбрасывания, я получаю javax.ejb.NoSuchEJBException: Bean has been deleted.

Это имеет смысл, поскольку боб был отброшен, но как я могу получить ссылку на новый новый бобин с состоянием?

Должен ли я вместо этого исключить исключение в моем SFSB и избежать этого отбрасывания? Что с состоянием транзакции, если я поймаю исключение? Должен ли я выполнять ручной откат?

Спасибо.

ответ

0

но как я могу получить ссылку на новую новую фазу с состоянием?

Контейнер вводит прокси-сервер в начале жизненного цикла компонента, поэтому в этом случае каждый новый экземпляр bean-bean-компонента будет вводить ссылку statefull только один раз. Альтернативой может быть получение справки через поиск JNDI, но это будет более громоздким.

Должен ли я вместо этого исключить исключение из своего SFSB и избежать этого отказа?

Да, я думаю, что это лучшее решение.

Должен ли я выполнять ручной откат?

Да. Когда контейнер перехватывает исключение RuntimeException, он отмечает транзакцию для отката. Мне нужно сохранить это поведение, чтобы текущая транзакция была отмечена вручную. Существует несколько альтернатив:

a) Бросьте исключение приложения и добавьте его в примечание @AnnotationException (rollback = true). В этом случае контейнер будет отмечать транзакцию для отката, не отбрасывая экземпляр компонента.

b) Отметить транзакцию методом SessionContext.setRollbackOnly().

//inject a SessionConetext instance 
@Resource 
SessionContext session; 

try { 
    //your code goes here 
} catch (RuntimeException e) 
//log the error 
    session.setRollbackOnly(); 
{ 
Смежные вопросы