| = Contexts and Dependency Injection (CDI) in Camel Quarkus |
| :page-aliases: cdi.adoc |
| |
| CDI plays a central role in Quarkus and Camel Quarkus offers a first class support for it too. |
| |
| You may use `@Inject`, `@ConfigProperty` and similar annotations e.g. to inject beans and configuration values to |
| your Camel `RouteBuilder`. Here is the `RouteBuilder` from our `timer-log-cdi` xref:user-guide/examples.adoc[example]: |
| |
| [source,java] |
| ---- |
| import javax.enterprise.context.ApplicationScoped; |
| import javax.inject.Inject; |
| import org.apache.camel.builder.RouteBuilder; |
| import org.eclipse.microprofile.config.inject.ConfigProperty; |
| |
| @ApplicationScoped <1> |
| public class TimerRoute extends RouteBuilder { |
| |
| @ConfigProperty(name = "timer.period", defaultValue = "1000") <2> |
| String period; |
| |
| @Inject |
| Counter counter; |
| |
| @Override |
| public void configure() throws Exception { |
| fromF("timer:foo?period=%s", period) |
| .setBody(exchange -> "Incremented the counter: " + counter.increment()) |
| .to("log:cdi-example?showExchangePattern=false&showBodyType=false"); |
| } |
| } |
| ---- |
| |
| <1> The `@ApplicationScoped` annotation is required for `@Inject` and `@ConfigProperty` to work in a `RouteBuilder`. |
| Note that the `@ApplicationScoped` beans are managed by the CDI container and their life cycle is thus a bit more |
| complex than the one of the plain `RouteBuilder`. In other words, using `@ApplicationScoped` in `RouteBuilder` comes |
| with some boot time penalty and you should therefore only annotate your `RouteBuilder` with `@ApplicationScoped` when |
| you really need it. |
| |
| <2> The value for the `timer.period` property is defined in `src/main/resources/application.properties` of the example project. |
| |
| TIP: Please refer to the https://quarkus.io/blog/quarkus-dependency-injection[Quarkus Dependency Injection guide] for more details. |
| |
| == Accessing `CamelContext` |
| |
| To access `CamelContext` just inject it into your bean: |
| |
| [source,java] |
| ---- |
| import javax.inject.Inject; |
| import javax.enterprise.context.ApplicationScoped; |
| import java.util.stream.Collectors; |
| import java.util.List; |
| import org.apache.camel.CamelContext; |
| |
| @ApplicationScoped |
| public class MyBean { |
| |
| @Inject |
| CamelContext context; |
| |
| public List<String> listRouteIds() { |
| return context.getRoutes().stream().map(Route::getId).sorted().collect(Collectors.toList()); |
| } |
| } |
| ---- |
| |
| == `@EndpointInject` and `@Produce` |
| |
| If you are used to `@org.apache.camel.EndpointInject` and `@org.apache.camel.Produce` from |
| xref:manual::pojo-producing.adoc[plain Camel] or from Camel on SpringBoot, you can continue using them on Quarkus too. |
| This is supported since Camel Quarkus 2.0.0. |
| |
| The following use cases are supported by `org.apache.camel.quarkus:camel-quarkus-core`: |
| |
| [source,java] |
| ---- |
| import javax.enterprise.context.ApplicationScoped; |
| import org.apache.camel.EndpointInject; |
| import org.apache.camel.FluentProducerTemplate; |
| import org.apache.camel.Produce; |
| import org.apache.camel.ProducerTemplate; |
| |
| @ApplicationScoped |
| class MyBean { |
| |
| @EndpointInject("direct:myDirect1") |
| ProducerTemplate producerTemplate; |
| |
| @EndpointInject("direct:myDirect2") |
| FluentProducerTemplate fluentProducerTemplate; |
| |
| @EndpointInject("direct:myDirect3") |
| DirectEndpoint directEndpoint; |
| |
| @Produce("direct:myDirect4") |
| ProducerTemplate produceProducer; |
| |
| @Produce("direct:myDirect5") |
| FluentProducerTemplate produceProducerFluent; |
| |
| } |
| ---- |
| |
| You can use any other Camel producer endpoint URI instead of `direct:myDirect*`. |
| |
| [WARNING] |
| ==== |
| `@EndpointInject` and `@Produce` are not supported on setter methods |
| - see https://github.com/apache/camel-quarkus/issues/2579[#2579] |
| ==== |
| |
| The following use case is supported by `org.apache.camel.quarkus:camel-quarkus-bean`: |
| |
| [source,java] |
| ---- |
| import javax.enterprise.context.ApplicationScoped; |
| import org.apache.camel.Produce; |
| |
| @ApplicationScoped |
| class MyProduceBean { |
| |
| public interface ProduceInterface { |
| String sayHello(String name); |
| } |
| |
| @Produce("direct:myDirect6") |
| ProduceInterface produceInterface; |
| |
| void doSomething() { |
| produceInterface.sayHello("Kermit") |
| } |
| |
| } |
| ---- |
| |
| == CDI and the Camel Bean component |
| |
| `org.apache.camel.quarkus:camel-quarkus-bean` artifact brings support for the following features: |
| |
| === Refer to a bean by name |
| |
| To refer to a bean in a route definition by name, just annotate the bean with `@Named("myNamedBean")` and |
| `@ApplicationScoped` (or some other |
| https://quarkus.io/guides/cdi-reference#supported_features[supported] scope). The `@RegisterForReflection` annotation |
| is important for the native mode. |
| |
| [source,java] |
| ---- |
| import javax.enterprise.context.ApplicationScoped; |
| import javax.inject.Named; |
| import io.quarkus.runtime.annotations.RegisterForReflection; |
| |
| @ApplicationScoped |
| @Named("myNamedBean") |
| @RegisterForReflection |
| public class NamedBean { |
| public String hello(String name) { |
| return "Hello " + name + " from the NamedBean"; |
| } |
| } |
| ---- |
| |
| Then you can use the `myNamedBean` name in a route definition: |
| |
| [source,java] |
| ---- |
| import org.apache.camel.builder.RouteBuilder; |
| public class CamelRoute extends RouteBuilder { |
| @Override |
| public void configure() { |
| from("direct:named") |
| .bean("namedBean", "hello"); |
| /* ... which is an equivalent of the following: */ |
| from("direct:named") |
| .to("bean:namedBean?method=hello"); |
| } |
| } |
| ---- |
| |
| NOTE: We aim at supporting all use cases listed in xref:manual::bean-binding.adoc[Bean binding] section of Camel documentation. |
| Do not hesitate to https://github.com/apache/camel-quarkus/issues[file an issue] if some bean binding scenario does not work for you. |
| |
| === `@Consume` |
| |
| Since Camel Quarkus 2.0.0, the `camel-quarkus-bean` artifact brings support for `@org.apache.camel.Consume` |
| - see the xref:manual::pojo-consuming.adoc[Pojo consuming] section of Camel documentation. |
| |
| Declaring a class like the following |
| |
| [source,java] |
| ---- |
| import org.apache.camel.Consume; |
| public class Foo { |
| |
| @Consume("activemq:cheese") |
| public void onCheese(String name) { |
| ... |
| } |
| } |
| ---- |
| |
| will automatically create the following Camel route |
| |
| [source,java] |
| ---- |
| from("activemq:cheese").bean("foo1234", "onCheese") |
| ---- |
| |
| for you. |
| Note that Camel Quarkus will implicitly add `@javax.inject.Singleton` and `javax.inject.Named("foo1234")` to the bean class, where `1234` is a hash code obtained from the fully qualified class name. |
| If your bean has some CDI scope (such as `@ApplicationScoped`) or `@Named("someName")` set already, |
| those will be honored in the auto-created route. |