Подтвердить что ты не робот

Apache Camel - запуск задачи при запуске для запуска только один раз

Я работаю над проектом Java с помощью Camel и Spring. Мы хотели бы инициировать метод инициализации на singleton bean после того, как Spring закончил свою работу, и Camel закончил строить все маршруты.

Мы не можем вызвать метод во время создания класса, поскольку он имеет динамические связи с другими классами, которые он извлекает из аннотации @Component Spring, и мы не знаем, когда/если эти классы еще загружены, чтобы фактически запустить init метод как часть конструктора.

Как я могу вызвать вызов метода или методов для запуска только один раз сразу после запуска запуска Camel?

Спасибо!

4b9b3361

Ответ 1

Если bean должен вызываться после того, как CamelContext запустил все маршруты и т.д., вы можете, как Бен, предложить использовать маршрут с таймером.

Возможной лучшей альтернативой является использование API EventNotifier от Camel. А затем вызовите логику при запуске CamelContextStartedEvent. Некоторые подробности о API EventNotifier здесь: http://camel.apache.org/eventnotifier-to-log-details-about-all-sent-exchanges.html

Ответ 2

другой простой вариант, который дает вам немного большую гибкость, заключается в использовании camel-timer с repeatCount = 1 и значением задержки достаточно долго, чтобы пусть все инициализируется. вы также можете добавить основную обработку исключений для задержки/повтора и т.д.

from("timer://runOnce?repeatCount=1&delay=5000").to("bean:runOnceBean");

Ответ 3

Одним из решений было бы исправить пару файлов (см. PR https://github.com/apache/camel/pull/684): CamelContextConfiguration.java и RoutesCollector.java.

В CamelContextConfiguration добавьте метод:

void afterApplicationStart(CamelContext camelContext);

И в onApplicationEvent of RoutesCollector добавьте что-то вроде:

        if (camelContextConfigurations != null) {
            for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
                camelContextConfiguration.afterApplicationStart(camelContext);
            }
        }

Вы можете опустить if (camelContextConfigurations != null), используя последнюю версию с этой даты.

Затем создайте Spring bean следующим образом, чтобы добавить код:

@Bean
CamelContextConfiguration contextConfiguration() {
    return new CamelContextConfiguration() {

        @Override
        public void beforeApplicationStart(CamelContext camelContext) {
        }

        @Override
        public void afterApplicationStart(CamelContext camelContext) {
            // Put your code here
        }
    };
}

UPDATE: этот запрос на перенос был объединен.

Ответ 4

Добавьте логику в метод вашего bean и аннотируйте его с помощью @PostConstruct - spring вызывается этот метод, как только этот bean будет полностью инициализирован и будут установлены все его зависимости.

@Component
class SomeClass {

 @PostConstruct
 void init() {
 }

}

Если логику нужно вызвать, если весь контекст приложения spring полностью инициализирован, вы можете сделать это, выполнив LifeCycle интерфейс.

Ответ 5

Вы можете попробовать ввести контекст верблюда в свой синглтон bean. Инъекция не произойдет, пока контекст не будет полностью инициализирован... включая создание всех маршрутов. Недостатком является то, что на самом деле вам не нужен контекст в вашем bean. Я возился в голове с мыслью связать зависимость singleton bean с инициализацией camelContext в файле конфигурации spring, но не уверен, что это действительно сработает.

Ответ 6

Как уже намекнул в ответах, прежде чем это скорее Spring, чем проблема Верблюда. В Spring вы можете просто реализовать InitializingBean и реализовать menthod afterPropertiesSet. Это называется, когда проводка выполнена.

Ответ 7

Вы можете использовать функцию заказа на запуск в Camel, зарегистрированную в http://camel.apache.org/configuring-route-startup-ordering-and-autostartup.html: -

<route startupOrder="1" id="thisOneGoesFirst">    
  <from uri="seda:foo"/>
  <to uri="mock:result"/>
</route>
<route startupOrder="2" id="thisOneGoesSecond">
  <from uri="direct:start"/>
  <to uri="seda:foo"/>
</route> 
<route id="thisOneGoesLast">
  <from uri="direct:bar"/>
  <to uri="seda:bar"/>
</route>

где маршруты с атрибутом startupOrder будут выполняться в порядке и перед всеми маршрутами, у которых нет startupOrder. Таким образом, вы можете использовать свой маршрут с потребителем таймера, который вам когда-либо нравился, до или после того, как ваши маршруты были запущены.