【发布时间】:2015-05-08 21:15:40
【问题描述】:
CMT MDB 的默认回滚行为是将消息返回到目标,以便再次处理它。
即使事务回滚,是否可以避免重新传递由托管 MDB 处理的消息? (或者配置容器处理的确认行为)。
到目前为止,我想出了以下替代方案:
-
将业务事务与消息事务隔离 - 我可以在业务方法上使用
TransactionAttributeType.REQUIRES_NEW,但它会创建一个业务场景 事件可能被处理两次,因为消息可能 业务交易成功后不予确认。 - 使用 BMT - 与上述相同的问题,因为事务将与消息事务分开。
- 使用 JMS Server 专有配置处理交付失败 - 如果可能,我希望将此逻辑保留在应用程序中。 由于WebLogic默认设置,我还必须为所有队列处理它 config 是永远重新传递消息。
阅读this tutorial 后,我仍然不确定如何解决这个问题,但到目前为止,使用专有的 WebLogic 控制台控制消息传递失败似乎是正确的选择。在这种情况下,对队列的重新投递设置一个限制 - 例如:3 次尝试。由于无效的业务事件可能会全部失败 3 次,因此会产生处理开销,但我可以保证系统的完整性。
你们觉得呢?
详情
我有一个与业务事务集成的 MDB,它使用 JPA(WebLogic 10.3.6 中的 EclipseLink)。一切都使用 CMT 运行,事务是分布式的。事务和消息确认由容器控制。
如果 JPA 提供程序中发生异常(例如:非空列的空值),则将重新传递消息,因为提供程序正在回滚事务并且未确认消息。我是否捕捉到异常并不重要,EclipseLink 无论如何都会回滚事务。我知道这是 JPA 的正确行为。
此外,使用 MessageDrivenContext.getRollbackOnly() 会返回 false。我希望它是真的。
如果我使用TransactionAttributeType.REQUIRES_NEW 执行我的业务方法,则事务将回滚并且消息不会重新传递,但是消息处理事务将是单独的,这也是不希望的。我确实设置了一个 JDBC 存储来将消息保存在数据库中。
我会留下一些虚拟类来说明我的观点。
MDB 消息处理
提取有效负载后,我将其转发到会话 bean 以处理持久性逻辑。
public void onMessage(Message message) {
try {
// Extract the payload
TextMessage txtMsg = (TextMessage) message;
String employeeName = txtMsg.getText();
// Call service
service.createEmployee(employeeName);
} catch (Exception e) {
e.printStackTrace();
} finally {
// When the JPA provider rollbacks back the transaction, this value
// is still "false"
log.info(String.format("Rollback only: [%s]", mdContext.getRollbackOnly()));
}
}
对 JPA 提供者强制异常
通过将null 留在非空字段中来强制出错。
// Message and business will run in the same transaction
@TransactionAttribute(TransactionAttributeType.MANDATORY)
public void createEmployee(String name) {
Employee employee = new Employee();
employee.setName(null); // Null value to force constraint error
try {
// This part triggers the exception within the JPA provider, and the
// Java EE transaction is rolledback and forces the JMS message to be
// redelivered.
em.persist(employee);
} catch (Exception e) {
// Capturing the exception does not affect the rollback behavior
e.printStackTrace();
}
}
这是 EclipseLink 抛出的错误。它被包裹在RuntimeException 中,因此它是一个系统异常并且事务将回滚。
javax.ejb.EJBTransactionRolledbackException: EJB Exception: ; nested exception is: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.1.v20111018-r10243): org.eclipse.persistence.exceptions.DatabaseException
【问题讨论】:
标签: java jpa transactions jms weblogic