Пометить транзакцию только для отката в MessageDrivenBean, не повторяя сообщение - PullRequest
4 голосов
/ 06 января 2012

У меня есть следующий MessageDrivenBean:

@MessageDriven(mappedName = "jms/...", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryAttempts", propertyValue = "5"),
    @ActivationConfigProperty(propertyName = "endpointExceptionRedeliveryInterval", propertyValue = "1000")
})
public class MyMessageListener implements MessageListener {

    @Resource
    private MessageDrivenContext context;

    @Override
    @TransactionAttribute(REQUIRED)
    public void onMessage(Message message) {            
    }
}

Внутри метода onMessage я выполняю некоторую обработку, которая здесь не важна.В определенных ситуациях я хочу отказаться от обработки.В этих ситуациях я хочу пометить транзакцию только для отката и не хочу повторять попытку.

По крайней мере, на Glassfish 3.1.1, если я вызову context.setRollbackOnly() на MessageDrivenContext и завершуПри обработке без исключения исключение сообщение доставляется бесконечно через очень короткие промежутки времени.Так что это не вариант для меня.

Если я добавлю RuntimeException, сообщение будет доставлено, как я его указал.Он доставляется 5 раз с интервалом в 1 секунду.Но в моем случае я вообще не хочу повторять обработку.

Если я просто завершу обработку без каких-либо исключений и без вызова context.setRollbackOnly(), транзакция будет зафиксирована, как и следовало ожидать.Но мне нужно откатить транзакцию, потому что, возможно, я уже изменил некоторые сущности JPA.

У меня есть вопрос: как пометить транзакцию только для отката без запуска повторной доставки сообщения?

1 Ответ

1 голос
/ 07 января 2012

вижу два варианта:

  1. Аннотируйте компонент с помощью @TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED), используйте управляемую компонентом транзакцию и не используйте AUTO_ACKNOWLEDGE (явное подтверждение сообщения в MDB). Не вариант, если ваш MDB является частью более крупной транзакции XA, у вас не будет возможности повлиять на результат глобальной транзакции.
  2. Проверьте флаг getJMSRedelivered() на сообщении и просто отбросьте доставленное сообщение. Проблема в том, что при повторной доставке вы не знаете, следует ли игнорировать повторную доставку (в некоторых случаях вы сказали, что хотите повторить обработку) & mdash; вам придется временно (в базе данных или в кэше) хранить идентификаторы сообщений, которые не удалось обработать, поэтому вы знаете, можете ли вы их игнорировать безопасно.
...