4

我有一个 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.");
}
4

2 回答 2

8

当容器启动容器管理事务处理 JMS 消息时,任何 JDBC 连接失败或线程中抛出的异常都将导致全局 XA 事务的回滚。因此消息返回队列,稍后将根据队列配置重试:重试间隔,将消息移动到死信队列之前的最大重试次数。

因此,您有以下选择:

  • 在您的 MDB 部署描述符中选择“Bean 管理”事务模式,并使用 UserTransaction 从查找java:comp/UserTransaction到调用或手动进行begin,因此请注意您的异常处理。commitrollback

  • 保留“容器管理”事务,但查询 JMS 消息上的重新交付计数属性以决定下一步做什么:或者重试可能失败的操作,或者跳过此步骤并将数据保存在数据库中。您可以从您的 JMS 提供商处 Message.getJMSRedelivered()Message.getLongProperty("JMSXDeliveryCount")您的 JMS 提供商是否交付消息中获取有关您的消息的重新传递信息。

  • 或者,将您的saveAuditData方法移动到部署描述符中具有事务支持的 EJB StatelessBean,RequiresNew以便创建新事务并保存您的数据,无论 MDB 事务发生什么。此选项可以与前一个选项结合使用。

于 2011-05-04T10:29:09.563 回答
2

您可以简单地使用 TransactionType 注释标记 onMessage 方法:

@TransactionAttribute(value=TransactionAttributeType.REQUIRES_NEW)
public void onMessage(Message message) {
     .....
}
于 2014-01-23T23:57:40.817 回答