Apache Camel - Triggering a task on startup to run only once
I am working on a Java project using Camel & Spring. We would like to trigger an initialize method on a singleton bean after Spring finished doing its thin开发者_JAVA技巧g and Camel has finished building all routes.
We cant call the method at class creation time as it has dynamic linkings to other classes that it picks up from the @Component spring annotation and we dont know when/if these classes have been loaded yet to actually run the init method as part of a constructor.
How can I go about invoking a method or methods to run only once right after Camel startup is complete?
Thanks!
another simple option which gives you a little more flexibility is to use camel-timer with a repeatCount=1 and a delay value long enough to let everything initialize. you can also add basic exception handling to delay/retry, etc...
from("timer://runOnce?repeatCount=1&delay=5000").to("bean:runOnceBean");
If the bean must be invoked after CamelContext has started all the routes etc, then you can as Ben suggest use a route with a timer.
A possible better alternative is to use the EventNotifier API from Camel. And then invoke the logic on the CamelContextStartedEvent being fired. Some details on the EventNotifier API here: http://camel.apache.org/eventnotifier-to-log-details-about-all-sent-exchanges.html
Add the logic in a method of your bean and annotate it with @PostConstruct - spring will invoke this method once this bean is fully initialized and all its dependencies are set.
@Component
class SomeClass {
@PostConstruct
void init() {
}
}
If the logic needs to be invoked once the whole spring application context is fully initialized you can do that by implementing the LifeCycle interface.
One solution would be to patch a couple of files (see PR https://github.com/apache/camel/pull/684): CamelContextConfiguration.java and RoutesCollector.java.
In CamelContextConfiguration, add the method:
void afterApplicationStart(CamelContext camelContext);
And in onApplicationEvent
of RoutesCollector
add something like:
if (camelContextConfigurations != null) {
for (CamelContextConfiguration camelContextConfiguration : camelContextConfigurations) {
camelContextConfiguration.afterApplicationStart(camelContext);
}
}
You may omit the if (camelContextConfigurations != null)
if using the latest version as of this date.
Then create a Spring bean as follows to add your code:
@Bean
CamelContextConfiguration contextConfiguration() {
return new CamelContextConfiguration() {
@Override
public void beforeApplicationStart(CamelContext camelContext) {
}
@Override
public void afterApplicationStart(CamelContext camelContext) {
// Put your code here
}
};
}
UPDATE: This pull request has been merged.
You could use the startup order functionality in Camel documented at 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>
where the routes with a startupOrder attribute will be executed in order and BEFORE all routes which have no startupOrder. So you can have your route with a timer consumer at which ever point you like, before or after your routes have been started.
You might try injecting the camel context into your singleton bean. The injection will not occur until the context is fully initialized ... including the building of all routes. The downside being that you might not actually require the context within your bean. I'm fiddling around in my head with an idea of linking the singleton bean dependency to the camelContext
initialization in the spring configuration file, but not sure that will actually work.
Like already hinted in the answers before this is rather a Spring than a Camel problem. In Spring you can simply implement InitializingBean and implement the menthod afterPropertiesSet. This is called when the wiring is done.
精彩评论