2015-03-03 2 views
1

Я работаю с управляемой командами системой с использованием JMS и Apache Camel для маршрутизации. В следующей ситуации:Обработка ошибок исключений/ошибок Camel без возникновения исключения клиента

  • Я посылаю системе команду запроса-ответа «X».

  • Система получает «Х» по трансактируемому маршруту верблюда.

  • При обработке «X» система посылает несколько событий, «Y» & «Z», , но в качестве части транзакционного маршрута они не должны быть промыты , пока транзакция не будет завершена.

  • Исключение возникает во время выполнения - это должно привести к отказу транзакции .

Я хочу, чтобы иметь возможность перехватывать исключение и отвечать подлинным сообщением (а не исключением) клиенту. Таким образом я начал осуществлять обработчик ошибок:

onException(RuntimeException.class) 
     .handled(true) 
     .markRollbackOnly() 
     .filter(header(Header.REPLY_TO.getName()).isNotNull()) 
     .to(DESTINATION_FOR_EXCEPTION_HANDLING) 
     .to(DESTINATION_FOR_REPLIES); 

Где:

  • DESTINATION_FOR_EXCEPTION_HANDLING является боб, который принимает исключение и возвращает объект сообщения
  • DESTINATION_FOR_REPLIES является боб, который устанавливает из тела к объекту сообщения

Проблема в том, что если включить «markRollbackOnly()» это:

  • Препятствует "Y" & "Z" от смывания - ХОРОШИЙ
  • Вызывает исключение обмена на клиенте, делающего requestReply - BAD

И если я не включить его, то:

  • "Y" & "Z" сбрасываться - BAD
  • Я получаю подлинный объект сообщения на клиенте - ХОРОШО

Как настроить верблюд как для предотвращения промывки сообщений в транзакции, так и для того, чтобы преобразовать исключение в обработанное сообщение об ошибке?

ответ

0

Я пробовал подход Клауса, но не мог заставить его работать по какой-то причине, я, должно быть, неправильно понял или установил что-то неправильно.

В конце концов я решил эту проблему, распространяя вторую транзакцию внутри, один обработчик ошибок я мог тогда «markRollbackOnlyLast» вторая сделка, но реагировать с «хорошим» сообщением о первой сделке:

TransactionTemplate newTransactionTemplate = new TransactionTemplate(platformTransactionManager); 
    newTransactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRES_NEW); 
    Policy requireNewTransaction = new SpringTransactionPolicy(newTransactionTemplate); 

    onException(RuntimeException.class) 
     .onWhen(header(Header.REPLY_TO.getName()).isNotNull()) 
      .log(LoggingLevel.ERROR, EXCEPTION_STACKTRACE) 
      .to(PROCESSOR_FOR_EXCEPTION_HANDLING) 
      .to(PROCESSOR_FOR_REPLY) 
      .handled(true) 
      .markRollbackOnlyLast(); 

    from(FROM) 
     .policy(requireNewTransaction)... 
0

Если отправление onException в эти 2 адресата использует тот же компонент Camel, что и from, тогда вам нужно будет использовать отдельный компонент для этого, чтобы они были независимыми. Поскольку откат в противном случае заставил бы всех их откатить.

Предполагая, что вы используете ActiveMQ, вы просто объявить два компонента

<bean id="activemq" ...> 

    <bean id="activemq2" ...> 

И затем использовать activemq2 в OnException. Затем можно настроить тот же самый brokerUrl и все такое. А для второго вам может потребоваться установить транзакцию = false.

+0

бы, не все еще вызывает исключение на клиенте, поскольку исходный компонент все равно будет реагировать на исключение обмена? – James