我有一个MDB
根据某些条件来触发进程(线程)。 process/thread
是一个长期运行的过程,因此我们不想保留触发MDB
的线程。
因此,我们创建了一个新线程,并自由地将其提交给托管任务执行程序,并在事情还没准备好时偶尔进入睡眠状态。
该线程从数据库读取记录,以消息形式发布到另一个MQ/JMS Queue
,然后将记录写入数据库。
我希望MQ/JMS message
和DB写入成为transaction
的一部分-两者都应该一起成功/失败。
如何在IBM liberty environment
中做到这一点。
任何建议/帮助都将受到赞赏。谢谢!!
我尝试用@Transactional
用REQUIRES_NEW
进行注释,但是不起作用。
通常,我们可能必须定义使用JTA transaction's
,然后用@Transactional
进行注释。
答案 0 :(得分:3)
ManagedExecutorService任务不在事务下运行。但是,他们确实具有启动新交易的能力。您可以按照以下步骤进行操作,
executor.submit(() -> {
UserTransaction tx = InitialContext.doLookup("java:comp/UserTransaction");
tx.begin();
try {
try (Connection con = dataSource.getConnection()) {
ResultSet results = con.createStatement().executeQuery(...);
... process result set and send messages
... update database
}
} finally {
tx.commit(); // or tx.rollback
}
return null;
});
答案 1 :(得分:0)
当我们创建自己的线程时,容器不允许我们管理事务-特别是当我们在JMS会话上调用commit时。
以这种方式解决: 我从MDB调用异步会话bean。 容器本身管理此会话Bean的事务。 将消息和数据库事务发布到另一个会话Bean中,该会话Bean管理自己的事务(@TransactionManagement(value = TransactionManagementType.BEAN))。
在Bean托管方法中,注入UserTransaction对象: @资源 UserTransaction userTransaction;
然后使用:userTransaction.begin();管理交易。和userTransaction.commit();和userTransaction.rollback();
答案 2 :(得分:-1)
如果您正在谈论分布式系统,那么您就无法实现JMS消息的可转换性,无论如何您都会发送它。您应该使用幂等性。并且您对db的读写应该处于事务中。
交易: -从数据库读取 -发送JMS -写入db
即使服务失败并且您不继续进行交易,下一次您将再次发送JMS,但是JSM接收器服务将对该操作做出决定性的响应(只是忽略它)