Apache Camel - запуск задачи при запуске для запуска только один раз
Я работаю над проектом Java с помощью Camel и Spring. Мы хотели бы инициировать метод инициализации на singleton bean после того, как Spring закончил свою работу, и Camel закончил строить все маршруты.
Мы не можем вызвать метод во время создания класса, поскольку он имеет динамические связи с другими классами, которые он извлекает из аннотации @Component Spring, и мы не знаем, когда/если эти классы еще загружены, чтобы фактически запустить init метод как часть конструктора.
Как я могу вызвать вызов метода или методов для запуска только один раз сразу после запуска запуска Camel?
Спасибо!
Ответы
Ответ 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. Таким образом, вы можете использовать свой маршрут с потребителем таймера, который вам когда-либо нравился, до или после того, как ваши маршруты были запущены.