Apache Camel - запуск задачи при запуске для запуска только один раз - PullRequest
14 голосов
/ 10 октября 2011

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

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

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

Спасибо!

Ответы [ 7 ]

19 голосов
/ 10 октября 2011

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

from("timer://runOnce?repeatCount=1&delay=5000").to("bean:runOnceBean");
10 голосов
/ 11 октября 2011

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

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

3 голосов
/ 24 ноября 2015

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

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

void afterApplicationStart(CamelContext camelContext);

И в onApplicationEvent из 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
        }
    };
}

ОБНОВЛЕНИЕ: Этот запрос извлечения объединен.

2 голосов
/ 10 октября 2011

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

@Component
class SomeClass {

 @PostConstruct
 void init() {
 }

}

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

1 голос
/ 10 октября 2011

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

1 голос
/ 10 октября 2011

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

0 голосов
/ 01 июля 2014

Вы можете использовать функциональность порядка запуска в 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. Таким образом, вы можете иметь свой маршрут с потребителем таймера в любой точке, в которую вы хотите, до или после того, как ваши маршруты были запущены.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...