Guice
Since Camel 1.5
We have support for Google Guice as a dependency injection framework.
Maven users will need to add the following dependency to their pom.xml
for this component:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-guice</artifactId>
<version>x.x.x</version>
<!-- use the same version as your Camel core version -->
</dependency>
Dependency Injecting Camel with Guice
The GuiceCamelContext is designed to work nicely inside Guice. You then need to bind it using some Guice Module.
The camel-guice library comes with a number of reusable Guice Modules you can use if you wish - or you can bind the GuiceCamelContext yourself in your own module.
-
CamelModule is the base module which binds the GuiceCamelContext but leaves it up you to bind the RouteBuilder instances
-
CamelModuleWithRouteTypes extends CamelModule so that in the constructor of the module you specify the RouteBuilder classes or instances to use
-
CamelModuleWithMatchingRoutes extends CamelModule so that all bound RouteBuilder instances will be injected into the CamelContext or you can supply an optional Matcher to find RouteBuilder instances matching some kind of predicate.
So you can specify the exact RouteBuilder instances you want
Injector injector = Guice.createInjector(new CamelModuleWithRouteTypes(MyRouteBuilder.class, AnotherRouteBuilder.class));
// if required you can lookup the CamelContext
CamelContext camelContext = injector.getInstance(CamelContext.class);
Or inject them all
Injector injector = Guice.createInjector(new CamelModuleWithRouteTypes());
// if required you can lookup the CamelContext
CamelContext camelContext = injector.getInstance(CamelContext.class);
You can then use Guice in the usual way to inject the route instances or any other dependent objects.
Bootstrapping with JNDI
A common pattern used in J2EE is to bootstrap your application or root objects by looking them up in JNDI. This has long been the approach when working with JMS for example - looking up the JMS ConnectionFactory in JNDI for example.
You can follow a similar pattern with Guice using the GuiceyFruit JNDI Provider which lets you bootstrap Guice from a jndi.properties file which can include the Guice Modules to create along with environment specific properties you can inject into your modules and objects.
If the jndi.properties is conflict with other component, you can specify the jndi properties file name in the Guice Main with option -j or -jndiProperties with the properties file location to let Guice Main to load right jndi properties file.
Configuring Component, Endpoint or RouteBuilder instances
You can use Guice to dependency inject whatever objects you need to create, be it an Endpoint, Component, RouteBuilder or arbitrary bean used within a route.
The easiest way to do this is to create your own Guice Module class which extends one of the above module classes and add a provider method for each object you wish to create. A provider method is annotated with @Provides as follows
public class MyModule extends CamelModuleWithMatchingRoutes {
@Provides
@JndiBind("jms")
JmsComponent jms(@Named("activemq.brokerURL") String brokerUrl) {
return JmsComponent.jmsComponent(new ActiveMQConnectionFactory(brokerUrl));
}
}
You can optionally annotate the method with @JndiBind to bind the object to JNDI at some name if the object is a component, endpoint or bean you wish to refer to by name in your routes.
You can inject any environment specific properties (such as URLs, machine names, usernames/passwords and so forth) from the jndi.properties file easily using the @Named annotation as shown above. This allows most of your configuration to be in Java code which is typesafe and easily refactorable - then leaving some properties to be environment specific (the jndi.properties file) which you can then change based on development, testing, production etc.
Creating multiple RouteBuilder instances per type
It is sometimes useful to create multiple instances of a particular RouteBuilder with different configurations.
To do this just create multiple provider methods for each configuration; or create a single provider method that returns a collection of RouteBuilder instances.
For example
import org.apache.camel.guice.CamelModuleWithMatchingRoutes;
import com.google.common.collect.Lists;
public class MyModule extends CamelModuleWithMatchingRoutes {
@Provides
@JndiBind("foo")
Collection<RouteBuilder> foo(@Named("fooUrl") String fooUrl) {
return Lists.newArrayList(new MyRouteBuilder(fooUrl), new MyRouteBuilder("activemq:CheeseQueue"));
}
}