Since we're on a major migration process of this website, some component documents here are out of sync right now. In the meantime you may want to look at the early version of the new website
https://camel.apache.org/staging/
We would very much like to receive any feedback on the new site, please join the discussion on the Camel user mailing list.
Camel CDIThe Camel CDI component provides auto-configuration for Apache Camel using CDI as dependency injection framework based on convention-over-configuration. It auto-detects Camel routes available in the application and provides beans for common Camel primitives like While the Camel CDI component is available as of Camel 2.10, it's been rewritten in Camel 2.17 to better fit into the CDI programming model. Hence some of the features like the Camel events to CDI events bridge and the CDI events endpoint only apply starting Camel 2.17. More details on how to test Camel CDI applications are available in Camel CDI testing. Auto-Configured Camel ContextCamel CDI automatically deploys and configures a @Inject CamelContext context; That default Note that this bean can be customized programmatically and other Camel context beans can be deployed in the application as well. Auto-Detecting Camel RoutesCamel CDI automatically collects all the class MyRouteBean extends RouteBuilder { @Override public void configure() { from("jms:invoices").to("file:/invoices"); } } Note that you can declare as many Available as of Camel 2.19 In some situations, it may be necessary to disable the auto-configuration of the static void configuration(@Observes CdiCamelConfiguration configuration) { configuration.autoConfigureRoutes(false); } Similarly, it is possible to deactivate the automatic starting of the configured static void configuration(@Observes CdiCamelConfiguration configuration) { configuration.autoStartContexts(false); } Auto-Configured Camel PrimitivesCamel CDI provides beans for common Camel primitives that can be injected in any CDI beans, e.g.: @Inject @Uri("direct:inbound") ProducerTemplate producerTemplate; @Inject MockEndpoint outbound; // URI defaults to the member name, i.e. mock:outbound @Inject @Uri("direct:inbound") Endpoint endpoint; @Inject TypeConverter converter; Camel Context ConfigurationIf you just want to change the name of the default @ContextName("camel-context") class MyRouteBean extends RouteBuilder { @Override public void configure() { from("jms:invoices").to("file:/invoices"); } } Else, if more customization is needed, any @ApplicationScoped class CustomCamelContext extends DefaultCamelContext { @PostConstruct void customize() { // Set the Camel context name setName("custom"); // Disable JMX disableJMX(); } @PreDestroy void cleanUp() { // ... } } Producer and disposer methods can also be used as well to customize the Camel context bean, e.g.: class CamelContextFactory { @Produces @ApplicationScoped CamelContext customize() { DefaultCamelContext context = new DefaultCamelContext(); context.setName("custom"); return context; } void cleanUp(@Disposes CamelContext context) { // ... } } Similarly, producer fields can be used, e.g.: @Produces @ApplicationScoped CamelContext context = new CustomCamelContext(); class CustomCamelContext extends DefaultCamelContext { CustomCamelContext() { setName("custom"); } } This pattern can be used for example to avoid having the Camel context routes started automatically when the container initializes by calling the @ApplicationScoped class ManualStartupCamelContext extends DefaultCamelContext { @PostConstruct void manual() { setAutoStartup(false); } } Multiple Camel ContextsAny number of @ApplicationScoped @ContextName("foo") class FooCamelContext extends DefaultCamelContext { } @ApplicationScoped @BarContextQualifier class BarCamelContext extends DefaultCamelContext { } @ContextName("foo") class RouteAdddedToFooCamelContext extends RouteBuilder { @Override public void configure() { // ... } } @BarContextQualifier class RouteAdddedToBarCamelContext extends RouteBuilder { @Override public void configure() { // ... } } @ContextName("baz") class RouteAdddedToBazCamelContext extends RouteBuilder { @Override public void configure() { // ... } } @MyOtherQualifier class RouteNotAddedToAnyCamelContext extends RouteBuilder { @Override public void configure() { // ... } } The Since Camel version 2.17.0, Camel CDI is capable of managing any kind of The CDI qualifiers declared on the @Inject @ContextName("foo") @Uri("direct:inbound") ProducerTemplate producerTemplate; @Inject @BarContextQualifier MockEndpoint outbound; // URI defaults to the member name, i.e. mock:outbound @Inject @ContextName("baz") @Uri("direct:inbound") Endpoint endpoint; Configuration PropertiesTo configure the sourcing of the configuration properties used by Camel to resolve properties placeholders, you can declare a @Produces @ApplicationScoped @Named("properties") PropertiesComponent propertiesComponent() { Properties properties = new Properties(); properties.put("property", "value"); PropertiesComponent component = new PropertiesComponent(); component.setInitialProperties(properties); component.setLocation("classpath:placeholder.properties"); return component; } If you want to use DeltaSpike configuration mechanism you can declare the following @Produces @ApplicationScoped @Named("properties") PropertiesComponent properties(PropertiesParser parser) { PropertiesComponent component = new PropertiesComponent(); component.setPropertiesParser(parser); return component; } // PropertiesParser bean that uses DeltaSpike to resolve properties static class DeltaSpikeParser extends DefaultPropertiesParser { @Override public String parseProperty(String key, String value, Properties properties) { return ConfigResolver.getPropertyValue(key); } } You can see the Auto-Configured Type ConvertersCDI beans annotated with the @Converter public class MyTypeConverter { @Converter public Output convert(Input input) { //... } } Note that CDI injection is supported within the type converters. Camel Bean IntegrationCamel AnnotationsAs part of the Camel bean integration, Camel comes with a set of annotations that are seamlessly supported by Camel CDI. So you can use any of these annotations in your CDI beans, e.g.:
Bean ComponentYou can refer to CDI beans, either by type or name, from the Camel DSL, e.g., using the Java DSL: class MyBean { //... } from("direct:inbound").bean(MyBean.class); Or to lookup a CDI bean by name from the Java DSL: @Named("foo") class MyNamedBean { //... } from("direct:inbound") .bean("foo"); Referring Beans From Endpoint URIsWhen configuring endpoints using the URI syntax you can refer to beans in the Registry using the from("jms:queue:{{destination}}?transacted=true&transactionManager=#jtaTransactionManager") .to("..."); Having the following CDI bean qualified with @Produces @Named("jtaTransactionManager") PlatformTransactionManager createTransactionManager(TransactionManager transactionManager, UserTransaction userTransaction) { JtaTransactionManager jtaTransactionManager = new JtaTransactionManager(); jtaTransactionManager.setUserTransaction(userTransaction); jtaTransactionManager.setTransactionManager(transactionManager); jtaTransactionManager.afterPropertiesSet(); return jtaTransactionManager; } Camel Events to CDI EventsAvailable as of Camel 2.17 Camel provides a set of management events that can be subscribed to for listening to Camel context, service, route and exchange events. Camel CDI seamlessly translates these Camel events into CDI events that can be observed using CDI observer methods, e.g.: void onContextStarting(@Observes CamelContextStartingEvent event) { // Called before the default Camel context is about to start } From Camel 2.18: it's possible to observe events for a particular route ( from("...").routeId("foo").to("..."); void onRouteStarted(@Observes @Named("foo") RouteStartedEvent event) { // Called after the route "foo" has started } When multiple Camel contexts exist in the CDI container, the Camel context bean qualifiers, like void onRouteStarted(@Observes @ContextName("foo") RouteStartedEvent event) { // Called after the route 'event.getRoute()' for the Camel context 'foo' has started } void onContextStarted(@Observes @Manual CamelContextStartedEvent event) { // Called after the the Camel context qualified with '@Manual' has started } Similarly, the void onExchangeCompleted(@Observes @Default ExchangeCompletedEvent event) { // Called after the exchange 'event.getExchange()' processing has completed } In that example, if no qualifier is specified, the Note that the support for Camel events translation into CDI events is only activated if observer methods listening for Camel events are detected in the deployment, and that per Camel context. CDI Events EndpointAvailable as of Camel 2.17 The CDI event endpoint bridges the CDI events with the Camel routes so that CDI events can be seamlessly observed / consumed (resp. produced / fired) from Camel consumers (resp. by Camel producers). The @Inject CdiEventEndpoint<String> cdiEventEndpoint; from(cdiEventEndpoint).log("CDI event received: ${body}"); This is equivalent to writing: @Inject @Uri("direct:event") ProducerTemplate producer; void observeCdiEvents(@Observes String event) { producer.sendBody(event); } from("direct:event") .log("CDI event received: ${body}"); Conversely, the @Inject CdiEventEndpoint<String> cdiEventEndpoint; from("direct:event") .to(cdiEventEndpoint).log("CDI event sent: ${body}"); This is equivalent to writing: @Inject Event<String> event; from("direct:event").process(new Processor() { @Override public void process(Exchange exchange) { event.fire(exchange.getBody(String.class)); } }).log("CDI event sent: ${body}"); Or using a Java 8 lambda expression: @Inject Event<String> event; from("direct:event") .process(exchange -> event.fire(exchange.getIn().getBody(String.class))) .log("CDI event sent: ${body}"); The type variable @Inject @FooQualifier CdiEventEndpoint<List<String>> cdiEventEndpoint; from("direct:event").to(cdiEventEndpoint); void observeCdiEvents(@Observes @FooQualifier List<String> event) { logger.info("CDI event: {}", event); } When multiple Camel contexts exist in the CDI container, the Camel context bean qualifiers, like @Inject @ContextName("foo") CdiEventEndpoint<List<String>> cdiEventEndpoint; // Only observes / consumes events having the @ContextName("foo") qualifier from(cdiEventEndpoint).log("Camel context (foo) > CDI event received: ${body}"); // Produces / fires events with the @ContextName("foo") qualifier from("...").to(cdiEventEndpoint); void observeCdiEvents(@Observes @ContextName("foo") List<String> event) { logger.info("Camel context (foo) > CDI event: {}", event); } Note that the CDI event Camel endpoint dynamically adds an observer method for each unique combination of event type and event qualifiers and solely relies on the container typesafe observer resolution, which leads to an implementation as efficient as possible. Besides, as the impedance between the typesafe nature of CDI and the dynamic nature of the Camel component model is quite high, it is not possible to create an instance of the CDI event Camel endpoint via URIs. Indeed, the URI format for the CDI event component is: cdi-event://PayloadType<T1,...,Tn>[?qualifiers=QualifierType1[,...[,QualifierTypeN]...]] With the authority cdi-event://org.apache.camel.cdi.example.EventPayload%3Cjava.lang.Integer%3E?qualifiers=org.apache.camel.cdi.example.FooQualifier%2Corg.apache.camel.cdi.example.BarQualifier But more fundamentally, that would prevent efficient binding between the endpoint instances and the observer methods as the CDI container doesn't have any ways of discovering the Camel context model during the deployment phase. Camel XML Configuration ImportAvailable as of Camel 2.18 While CDI favors a typesafe dependency injection mechanism, it may be useful to reuse existing Camel XML configuration files into a Camel CDI application. In other use cases, it might be handy to rely on the Camel XML DSL to configure its Camel context(s). You can use the @ImportResource("camel-context.xml") class MyBean { } Camel CDI will load the resources at the specified locations from the classpath (other protocols may be added in the future). Every <camelContext id="foo"> <endpoint id="bar" uri="seda:inbound"> <property key="queue" value="#queue"/> <property key="concurrentConsumers" value="10"/> </endpoint> <camelContext/> The corresponding CDI beans are automatically deployed and can be injected, e.g.: @Inject @ContextName("foo") CamelContext context; @Inject @Named("bar") Endpoint endpoint; Note that the Conversely, CDI beans deployed in the application can be referred to from the Camel XML configuration, usually using the @Produces @Named("baz") Processor processor = exchange -> exchange.getIn().setHeader("qux", "quux"); A reference to that bean can be declared in the imported Camel XML configuration, e.g.: <camelContext id="foo"> <route> <from uri="..."/> <process ref="baz"/> </route> <camelContext/> Transaction supportAvailable as of Camel 2.19 Camel CDI provides support for Camel transactional client using JTA. That support is optional hence you need to have JTA in your application classpath, e.g., by explicitly add JTA as a dependency when using Maven: <dependency> <groupId>javax.transaction</groupId> <artifactId>javax.transaction-api</artifactId> <scope>runtime</scope> </dependency> You'll have to have your application deployed in a JTA capable container or provide a standalone JTA implementation. Note that, for the time being, the transaction manager is looked up as JNDI resource with the Transaction policiesCamel CDI provides implementation for the typically supported Camel class MyRouteBean extends RouteBuilder { @Override public void configure() { from("activemq:queue:foo") .transacted("PROPAGATION_REQUIRED") .bean("transformer") .to("jpa:my.application.entity.Bar") .log("${body.id} inserted"); } } This would be equivalent to: class MyRouteBean extends RouteBuilder { @Inject @Named("PROPAGATION_REQUIRED") Policy required; @Override public void configure() { from("activemq:queue:foo") .policy(required) .bean("transformer") .to("jpa:my.application.entity.Bar") .log("${body.id} inserted"); } } The list of supported transaction policy names is: Transactional error handlerCamel CDI provides a transactional error handler that extends the redelivery error handler, forces a rollback whenever an exception occurs and creates a new transaction for each redelivery. Camel CDI provides the class MyRouteBean extends CdiRouteBuilder { @Override public void configure() { errorHandler(transactionErrorHandler() .setTransactionPolicy("PROPAGATION_SUPPORTS") .maximumRedeliveries(5) .maximumRedeliveryDelay(5000) .collisionAvoidancePercent(10) .backOffMultiplier(1.5)); } } Auto-configured OSGi integrationAvailable as of Camel 2.17 The Camel context beans are automatically adapted by Camel CDI so that they are registered as OSGi services and the various resolvers (like karaf@root()> camel:context-list Context Status Total # Failed # Inflight # Uptime ------- ------ ------- -------- ---------- ------ camel-cdi Started 1 0 0 1 minute See the Lazy Injection / Programmatic LookupAvailable as of Camel 2.17 While the CDI programmatic model favors a type-safe resolution mechanism that occurs at application initialization time, it is possible to perform dynamic / lazy injection later during the application execution using the programmatic lookup mechanism. Camel CDI provides for convenience the annotation literals corresponding to the CDI qualifiers that you can use for standard injection of Camel primitives. These annotation literals can be used in conjunction with the For example, you can use the provided annotation literal for the @Any @Inject Instance<ProducerTemplate> producers; ProducerTemplate inbound = producers .select(Uri.Literal.of("direct:inbound")) .get(); Or for Endpoint beans, e.g.:@Any @Inject Instance<Endpoint> endpoints; MockEndpoint outbound = endpoints .select(MockEndpoint.class, Uri.Literal.of("mock:outbound")) .get(); Similarly, you can use the provided annotation literal for the @Any @Inject Instance<CamelContext> contexts; CamelContext context = contexts .select(ContextName.Literal.of("foo")) .get(); You can also refined the selection based on the Camel context type, e.g.: @Any @Inject Instance<CamelContext> contexts; // Refine the selection by type Instance<DefaultCamelContext> context = contexts.select(DefaultCamelContext.class); // Check if such a bean exists then retrieve a reference if (!context.isUnsatisfied()) context.get(); Or even iterate over a selection of Camel contexts, e.g.: @Any @Inject Instance<CamelContext> contexts; for (CamelContext context : contexts) context.setUseBreadcrumb(true); Maven ArchetypeAmong the available Camel Maven archetypes, you can use the provided mvn archetype:generate -DarchetypeGroupId=org.apache.camel.archetypes -DarchetypeArtifactId=camel-archetype-cdi Supported ContainersThe Camel CDI component is compatible with any CDI 1.0, CDI 1.1 and CDI 1.2 compliant runtime. It's been successfully tested against the following runtimes:
ExamplesThe following examples are available in the
See Also
|