除非另有說明拋出的異常,如果ejb方法調用引發異常,則應該回退。另外,如果所有對數據庫的調用都在同一個事務中,那麼它們在交易週期結束時被認爲是承諾的。回想起來,所有攔截器都是在它所攔截的ejb方法所在的同一個事務中被調用的(這就是攔截器在發生異常時可能決定的原因,或者回滾或者仍然提交事務)。
因此,您可以確定地知道,如果在攔截器調用中成功完成事務,在繼續被調用並返回後,沒有異常拋出,並且可能會發生事務回滾。
在方案
所以:
@AroundInvoke
public Object logMethodEntry(InvocationContext ctx) throws Exception {
Object proceed = null;
try {
proceed = ctx.proceed();
// is the transacction finished/commited already?
// The transaction is successful, but afaik, it is not yet committed, until this method returns successfully
// is it still open ? More or less. You can still grab the Ejbtransaction and commit it manually or rollback if some other conditions have not been met yet
return proceed;
} catch (Exception e) {
//If this happens, and you propagate it, then for sure the transaction will be rolledback, and never get committed. Since all db calls were being done within this transaction, then no DB commit will be done.
throw e;
}
}
編輯: 爲你實際上是在一個攔截器提交事務,你將需要運行的應用程序管理的事務,否則,它被禁止EJB規範調用一個容器管理事務的提交,你當然可以調用EJBContext的setOnrollback方法。 編輯 如果你真的想要做一些數據庫的變化,我建議:
- 用戶ApplicationManaged交易,從中你手動啓動 和攔截
- 內提交事務,使用的概念觀察者,並監聽@Observes(AFTER_SUCCESS)事件,當事務成功提交併完成時將調用該事件,因此您可以保證執行db調用,並且新更新將爲 可用。
- 如果你可以忽略BCE模式,並剝離了新的交易做了更新,使其成功返回後,你會得到保證承諾的,然後繼續正常
```
@Stateless
public class TransactionService {
@TransactionAttribute(REQUIRES_NEW)
public Object executeTransaction(final Callable<Object> task) {
return task.call();
}
}
@Interceptor
public class MyInterceptor {
@EJB
private TransactionService service;
@AroundInvoke
public Object logMethodEntry(InvocationContext ctx) throws Exception {
Object proceed = null;
try {
proceed = service.executeTransactional(()->ctx.proceed());
//If you reach here, you will be guaranteed of commit and then you can do the elastic search update
return proceed;
} catch (Exception e) {
//If this happens, and you propagate it, then for sure the transaction will be rolledback, and never get committed. Since all db calls were being done within this transaction, then no DB commit will be done.
throw e;
}
}
}
我想你可能會誤解Adam Bien。你寫道:「邊界上的所有EJB調用都會啓動並完成一個事務,這意味着沒有嵌套的EJB調用」,但事實並非如此。您可以嵌套EJB調用,除非您特別重寫它,否則調用將發生在同一個事務中。無論如何,我不認爲BCE意味着您不能在單個邊界呼叫中使用多個交易。最後一個提示:'AroundInvoke'調用發生在與方法相同的事務中,因此您的問題中的代碼註釋無法實現。 – DavidS 2017-04-12 16:56:11