我们最近在PROD中遇到了一个非常意外的问题,我们设法重现了该问题,但是我们仍然不清楚导致问题的原因,更重要的是如何解决它。
我们的系统是一个供应商工作流框架,为我们提供了添加自定义行为的挂钩。它运行在WebSphere Application Server上,由Camel和Spring以及EJB混合而成。最初它是纯EJB,但几年前,该供应商添加了Camel,以摆脱应用服务器。
现在是问题:
处理的开始是使用 PROPAGATION_REQUIRED 属性进行交易的骆驼路线。处理的一部分是对EJB方法的本地调用。除了受容器管理之外,没有公开设置任何EJB方法。这意味着EJB调用应该获得 REQUIRED 的隐式值。 EJB调用的一部分发生了数据更改。 EJB的引用是使用以下代码获得的:
String repositoryName = MBLLookupUtil.getInstance().getRepositoryName();
RepositoryInstanceFacadeHome facadeHome = MBLLookupUtil.getInstance().getRepositoryInstanceFacadeHome(
repositoryName);
RepositoryInstanceFacade facade = facadeHome.create();
// Here is when the data change happens:
facade.doSomeWork();
应用程序日志清楚地表明EJB处理与客户端在同一线程中进行。拨打电话后,发生超时异常时,主叫客户端中还有更多工作要做。
我们希望客户端上的数据更改和作为EJB调用的一部分更改的数据都将被回滚,但是在客户端(骆驼)被回滚的同时,通过EJB调用更改的数据将保持提交状态。
在spring应用程序上下文中,我们使用WebSphereUowTransactionManager
,这是IBM建议的配置事务管理器的方式:
<bean id="txManager" class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>
任何有关可能导致这种情况或我们如何进一步调查的提示都将不胜感激。预先谢谢你。
更新:
如tomgeraghty3的评论所建议,我进行了代码更改以记录TransactionSynchronizationManager.isActualTransactionActive()
的值,结果为 true
更新2:
我们花费数小时来分析反编译的供应商代码,从而找出问题所在。事务传播是在application-context.xml文件中配置的,但是它也直接用PO @Transactional(propagation=REQUIRED_NEW)
注释覆盖了。我们通过从供应商jar中删除POJO类,并在我们的其中一个中添加了一个没有注释的同一个包,从而证明了问题所在。只是为了证明我们的怀疑而非常肮脏。
现在,我们最大的挑战是说服供应商解决此问题。希望这只是一个错误,而不是有影响的更改。