Как откатить всю транзакцию для Splitter в случае сбоя любого вложенного сообщения - PullRequest
1 голос
/ 28 мая 2020

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

from("endpoint")    
    .split().method(iteratorProcessor, "execute")
    .shareUnitOfWork()
    .stopOnException()
    .bean(testProcessor, "process") 
    .receipientList(header("destination"));

С указанным выше случай успеха работает должным образом.

Проблема : в случае, если после разделения первая публикация сообщения прошла успешно, а вторая публикация сообщения не прошла, мы наблюдаем, что только второе вспомогательное сообщение направляется обработчику ошибок.

Требование : Если какой-либо сбой происходит во всем процессе, мы хотим перенаправить IN-сообщение обработчику ошибок (полный откат) и не не публиковать никаких других вложенных сообщений.

Ответы [ 2 ]

0 голосов
/ 28 мая 2020

Добро пожаловать в переполнение стека!

В случае ошибки, вызванной оператором stopOnException(), Splitter прерывает обработку.

Это означает, что для вашей цели выполнить полный откат

  • У вас все в порядке для всех еще не обработанных записей.
  • Ваша проблема - это уже успешно обработанные записи

Для них вы должны запустить логи компенсации c как часть ваш откат. Например, если уже обработанные записи записываются в базу данных, вы можете удалить их позже, когда произойдет сбой в Splitter.

Добавлено из-за комментариев

Согласно Splitter docs , поскольку вы используете shareUnitOfWork(), вы должны получить только одно сообщение об ошибке, когда Splitter завершен и произошла как минимум 1 ошибка (вместо одного сообщения об ошибке на неудачное подсообщение). Поэтому, если вы также используете useOriginalMessage() в обработчике ошибок, вы должны получить исходное сообщение IN.

Если это не сработает, может столкнуться с stopOnException() (никогда не пробовал). Это была бы попытка удалить stopOnException() и проверить, работает ли он так.

Вы не можете напрямую компенсировать уже доставленное сообщение JMS, но вы можете построить компенсацию , которую вы можете запустить впоследствии . Например, отправьте неудачные сообщения из обработчика ошибок в другую очередь, потребитель которой откатывает все, что было сделано первым сообщением.

0 голосов
/ 28 мая 2020

Предложение onException предоставляет возможность использовать исходное сообщение.

Из документов Camel:

onException(MyOrderException.class)
.useOriginalMessage()
.handled(true)
.to("jms:queue:order:failed");
...