我有一个onMessage方法,我从队列中恢复一个ObjectMessage并使用该信息来填充和保存JPA实体对象。但是当持久化实体对象出现问题时,它会重新执行onMessage()。我的猜测是它将ObjectMessage推回队列,因此onmessage再次被执行。这样我就进入了无限循环。如何停止onMessage()再次执行或控制执行的次数。这是我的代码。 saveAuditData(auditInfo)发生错误。
public void onMessage(Message inMessage) {
log.debug("Entering onMessage() Method.");
AuditInfo auditInfo = null;
try {
ObjectMessage om = (ObjectMessage) inMessage;
auditInfo = (AuditInfo) om.getObject();
log.debug("Message received : " + auditInfo.getApiUsed());
log.debug("Calling saveAuditData().");
saveAuditData(auditInfo);
log.debug("Leaving onMessage() Method.");
}
catch (Exception e) {
e.printStackTrace();
log.debug("Error persisting Audit Info.",e);
log.debug("Printing Audit Info:");
log.debug(auditInfo.toString());
}
}
private void saveAuditData(AuditInfo auditInfo) {
log.debug("Entering saveAuditData() Method.");
log.debug("Populating Audit Object.");
IdmAudit idmAudit = new IdmAudit();
idmAudit.setApiUsed("API");
idmAudit.setAppClientIpAddress("localhost");
idmAudit.setAuditActivity("activity1");
idmAudit.setAuditData(auditInfo.getAuditData());
idmAudit.setAuditGroup(AUDIT_GROUP);
idmAudit.setAuditType("Type");
idmAudit.setIdmAuditCreationDate(new Date());
idmAudit.setLocationCd("Location");
idmAudit.setPurgeDate(null);
idmAudit.setSubscriberId(new BigDecimal(0));
idmAudit.setSuccessInd("Y");
idmAudit.setUserId(new BigDecimal(0));
idmAudit.setAuditSource("Source");
idmAudit.setVersionNumber(new BigDecimal(0));
log.debug("Saving Audit.");
entityManager.persist(idmAudit);
entityManager.flush();
log.debug("Leaving saveAuditData() Method.");
}
答案 0 :(得分:8)
当容器启动容器管理的事务以处理JMS消息时,JDBC连接中的任何故障或线程中抛出的异常都将导致全局XA事务的回滚。因此,消息将返回队列,稍后将根据队列配置重试:重试之间的时间段,在将消息移动到死信队列之前的最大重试次数。
所以你有以下选择:
在MDB部署描述符中选择“Bean managed”事务模式,并使用UserTransaction从查找到java:comp/UserTransaction
手动调用begin
,commit
或rollback
,所以要小心你的异常处理。
保留“容器管理”事务,但查询JMS消息上的重新传递计数属性以决定下一步操作:再次尝试可能失败的操作或跳过此步骤并将数据保存在数据库中。如果您的JMS提供商提供,您可以从Message.getJMSRedelivered()
或Message.getLongProperty("JMSXDeliveryCount")
获取有关您的消息的重新发送信息。
或者,将您的saveAuditData
方法移动到部署描述符中具有事务支持RequiresNew
的EJB StatelessBean,以便创建新事务并保存您的数据,无论您的MDB事务发生什么。此选项可与前一个选项结合使用。
答案 1 :(得分:2)
您只需使用TransactionType注释标记onMessage方法:
@TransactionAttribute(value=TransactionAttributeType.REQUIRES_NEW)
public void onMessage(Message message) {
.....
}