确保JPA在另一个服务访问数据之前提交我的事务
感觉很简单: 我有一个确保JPA在另一个服务访问数据之前提交我的事务,jpa,jsf-2,transactions,jta,Jpa,Jsf 2,Transactions,Jta,感觉很简单: 我有一个ViewScopedbean(JPA2+EE6+Seam3,如果需要的话),web应用程序的用户可以在其中调用如下方法: public void save() { doEntityManagerStuff(); // manipulates data in the database callRemoteWebservice(); // which is to read said data and propagate it to other systems }
ViewScoped
bean(JPA2+EE6+Seam3,如果需要的话),web应用程序的用户可以在其中调用如下方法:
public void save() {
doEntityManagerStuff(); // manipulates data in the database
callRemoteWebservice(); // which is to read said data and propagate it to other systems
}
不幸的是,save()
在开头的方括号处启动事务,但在结尾的方括号之前没有提交,这意味着远程web服务无法读取新数据
我已尝试显式提取和注释数据库工作:
@TransactionAttribute(REQUIRES_NEW)
private void doEntityManagerStuff() {
blabla(); // database stuff
}
但这根本没有任何影响。(可能是因为那是EJB的东西,我在seam上运行…?)
到目前为止,对我来说唯一有效的方法是注入@UserTransaction
,并在save()
或doEntityManagerStuff()
的末尾强制提交事务,但这让我觉得非常肮脏和危险
另一种选择是为整个项目关闭容器管理的事务,但这意味着我必须让我的所有bean手动管理它们的事务,这样我才能使这一个案例起作用
有更好的方法吗?来回答我自己的问题: 我只走了一半,这就是为什么它不起作用。我对EJB及其boudaries了解得不够,天真地说,在我的视图范围内的CDI/SeamBean中,用事务属性注释
doEntityManagerStuff(…)
方法就足够了
事实并非如此
当我将所述方法移动到一个单独的、无状态的EJB中,将其注入到我的CDI/Seam bean中并从那里调用它时,一切都按预期进行
及
等等,您的JSF托管bean是事务性的。。?这不是默认行为。您的JSF支持bean类上都有哪些注释?基本上,您应该将事务方法分离为一个真正的服务类,然后依次将其注入JSF托管bean中。仅
javax.faces.bean.ViewScoped
@BalusC-显然,我的web应用程序所做的一切都会打开一个事务。我为com.arjuna.ats.jta
打开了跟踪日志记录,我得到了一些事务,比如从服务器请求一个静态PNG,甚至在一个根本不涉及EntityManager和数据库的bean中只运行@Schedule(…)
方法。有些东西被误解了,这一点似乎很清楚。我应该从哪里开始寻找?“我应该从哪里开始寻找?”web.xml中的servletfilters?@Kukeltje-谢谢,这也是我的想法,实际上有两三个。但它们都没有任何事务性内容或注释。不过我找到了罪犯。我们的项目是一个奇怪的混蛋,它使用EE6和Seam来获得@viewscope
bean。作为Seam的一部分,org.jboss.Seam.transaction
中的依赖项Seam事务
。一旦进入,每个调用都会触发BaseTransaction.begin
。我看看能不能把它处理掉。
@Stateless
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public class MyPersister {
...
public void doEntityManagerStuff() {
blabla(); // database stuff
}
...
}
@ViewScoped
public class MyWebsiteBean {
...
@Inject MyPersister persister;
...
public void save() {
persister.doEntityManagerStuff(); //uses its own transaction
callRemoteWebService();
}
...
}