Как остановить откат в MDB? - PullRequest
4 голосов
/ 25 марта 2011

У меня есть метод 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.");
}

Ответы [ 2 ]

8 голосов
/ 04 мая 2011

Когда управляемая контейнером транзакция запускается контейнером для обработки сообщения JMS, любой сбой в соединениях JDBC или исключение, выданное в потоке, приведет к откату глобальной транзакции XA.Таким образом, сообщение возвращается в очередь и будет повторяться позже в соответствии с конфигурацией очереди: период между повторными попытками, максимальное количество повторов перед перемещением сообщения в очередь недоставленных сообщений.

Итак, у вас есть следующие варианты:

  • Выберите режим транзакции "Управляемый компонентом" в дескрипторе развертывания MDB и используйте UserTransaction от поиска до java:comp/UserTransaction для вызова begin, commit или rollback вручную, поэтомубудьте внимательны с обработкой исключений.

  • Сохраните транзакцию "Управляемый контейнером", но запросите свойство количества повторных поставок в сообщении JMS, чтобы решить, что делать дальше: либо попробуйте снова что-то, что может дать сбой, либо пропуститеэтот шаг и сохранить ваши данные в базе данных.Вы можете получить информацию о доставке вашего сообщения от Message.getJMSRedelivered() или Message.getLongProperty("JMSXDeliveryCount"), если ваш провайдер JMS доставит его.

  • Или же, переместите ваш метод saveAuditData в EJB StatelessBean с транзакциейподдержка RequiresNew в дескрипторе развертывания для создания новой транзакции и сохранения ваших данных независимо от того, что происходит с вашей транзакцией MDB.Эта опция может быть объединена с предыдущей.

2 голосов
/ 24 января 2014

Вы можете просто пометить метод onMessage с помощью аннотации TransactionType:

@TransactionAttribute(value=TransactionAttributeType.REQUIRES_NEW)
public void onMessage(Message message) {
     .....
}
...