Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 5.3

Camel Guice

As of 1.5 we now We have support for Google Guice as a dependency injection framework.

Maven users will need to add the following dependency to their pom.

To use it just be dependent on camel-guice.jar which also depends on

xml for this component:

Code Block
xml
xml

<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; though there's also the CamelModule which automatically creates a Guice-aware CamelContext, using Guice as the injector to create any of the default strategies, Component or Endpoint instances.

When you create a CamelModule you can specify a list of RouteBuilder classes which will then be dependency injected and installed.

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

Code Block
Injector injector = Guice.createInjector(new CamelModuleCamelModuleWithRouteTypes(MyRouteBuilder.class, AnotherRouteBuilder.class));
// if required you can lookup the CamelContext
CamelContext camelContext = injector.getInstance(CamelContext.class);

Or inject them all

Code Block

Injector injector = Guice.createInjector(new CamelModuleWithRouteTypes());
// if required you can lookup the CamelContext
CamelContext camelContext = injector.startgetInstance(CamelContext.class);

You can then use Guice in the usual way to inject the route instances or any other dependent objects.

Custom binding of RouteBuilder

You can create your own derivation of CamelModule which overloads the configureRoutes() method to allow you to use the Multibinder in Guice to bind different route builders.

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

Code Block

public
Code Block

public static class MyModule extends CamelModuleCamelModuleWithMatchingRoutes {
    /**
     * Lets add the routes@Provides
     */@JndiBind("jms")
    @Override
    protected void configureRoutes(Multibinder<Routes> binderJmsComponent jms(@Named("activemq.brokerURL") String brokerUrl) {
        binderreturn JmsComponent.addBinding().to(MyHardcodeRoute.class);
        binder.addBinding().to(MyRouteInstaller.classjmsComponent(new ActiveMQConnectionFactory(brokerUrl));
    }
}

Creating multiple RouteBuilder instances per type

In addition to the above mechanism of binding explicit instances, its sometimes useful to use a single RouteBuilder as a factory of other route builder instances.

This is because the configure() method on a RouteBuilder is called after the CamelContext is created and it is bound to a CamelContext, so you can resolve any components or endpoint dynamically through the CamelContext (using Guice under the covers for any dependency injection).

The following example shows how we can add multiple instances of a RouteBuilder class with different parameters. We can clearly dependency inject the MyRouteInstaller from Guice and use those values to pass into the RouteBuilder instances.

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

Code Block

import org.apache.camel.guice.CamelModuleWithMatchingRoutes;
import com.google.common.collect.Lists;

public class MyModule extends CamelModuleWithMatchingRoutes
Code Block

public class MyRouteInstaller extends RouteBuilder {

    public@Provides
   void configure@JndiBind() throws Exception {"foo")
    Collection<RouteBuilder>    addRoutes(new MyConfigurableRoute(endpoint("direct:a"), endpoint("direct:b")));foo(@Named("fooUrl") String fooUrl) {
        addRoutesreturn Lists.newArrayList(new MyConfigurableRoute(endpoint("direct:c"MyRouteBuilder(fooUrl), new endpointMyRouteBuilder("directactivemq:dCheeseQueue")));
    }
}

See Also