Having reread my old blog post about the Camel Quarkus 1.0.0 release from last year, I realised that in the code examples I casually mentioned things like ‘bootstrap’ and ‘Camel Main’, but never covered those terms in any detail.
Here follows a brief overview of how Camel Quarkus applications are bootstrapped and some different ways in which a Camel Quarkus application can written.
Similar to Camel on Spring Boot, Camel Quarkus automatically creates a
CamelContext, discovers any
RouteBuilder implementations and loads any XML based
CamelContext definitions. The major difference in Camel Quarkus, is that there’s a lot of work happening at build time, instead of in a traditional application where most things happen at run time.
There are some obvious benefits to doing ‘heavy duty’ configuration work at build time, rather than runtime. Many of the Camel Quarkus component extensions do work at build time to configure some aspect of the application. Such as configuring components, adding beans to the Camel registry and other tasks that help to make the user experience and performance better.
Once the build time configuration steps are completed, a lightweight Camel runtime is assembled as is executed as part of the ‘Runtime Init’ Quarkus bootstrap phase.
There are a few ways to build and configure Camel Quarkus applications. I won’t delve into the specifics of how configuration properties work, as Alexandre Gallice covered this recently in his blog post, Camel Quarkus Configuration Tips.
Instead, I’ll focus on the choices available for wiring together a Camel Quarkus application and how they differ with regards to configuration options.
Configuration with Camel Quarkus Main
Component configuration options
With Camel Main, you can configure component and endpoint properties like this.
Each Camel Quarkus component extension documentation page lists and links to all of the supported configuration options.
Camel Main has a feature where it can automatically discover beans that are in the Camel registry and wire them into the corresponding types on any component or endpoint properties.
For example, the log component has the option for providing a custom
ExchangeFormatter. To do that, we define a CDI bean producer method as follows.
With this code in place, the following is reported during application startup indicating Camel Main autowired the
ExchangeFormatter into the component:
Custom main class
With Camel Main, it is possible to take advantage of Quarkus command line style applications and write a custom main method where you can choose when the Camel runtime is started. You can also leverage Quarkus command line support. Peter Palaga previously covered this in a Blog Post.
Configuration without Camel Main
Without Camel Main, you can leverage CDI to do any required custom configuration. For example, to configure a component.
Note the use of
@Named is quite important in this instance. It determines the URI scheme that is used to reference the component in a route. If we had used
@Named("foo"), then our route would look like
Something else to note is that manually creating components in this way replaces and overrides any pre-configuration and optimisation that was done at build time by the related component extension. For example, the Vert.x component extension sets up the component at build time like this.
If you were to configure the component manually with CDI, the work done at build time would effectively be ignored.
You can preserve the pre-configuration via an observer method to catch when the component is added to the
CamelContext like this.
A note on ‘unused’ beans
A potential pitfall when configuring CDI beans for Camel to use, is that Quarkus will attempt to remove what it deems to be ‘unused’ beans. There’s more information about this in the Quarkus documentation.
Consider the following example for the Camel JMS component. Camel can auto discover a
ConnectionFactory from the registry, so we attempt to take advantage of this by doing the following.
Since the ConnectionFactory bean is neither
@Injected anywhere in the application, Quarkus considers it a candidate for removal. When Camel attempts to look up the bean in the registry, it wont find anything.
The solution is to annotate the producer method with
@Named. Or you can disable bean removal entirely.
NOTE: Since Camel Quarkus 2.1.0, explicitly annotating beans bound for Camel registry lookups with
@Unremovableis no longer required. Camel Quarkus automatically marks types required by Camel components as unremovable.
Configuration with XML
It’s possible to create routes using XML like this. If you need to reference beans or processors, then you can use CDI to create them and refer to their name in the route XML.
There’s also some limited support for Spring provided via the Quarkus Spring extensions. Note this is not a full replacement for camel-spring or camel-spring-boot. But it provides the capability to write a Camel application using Spring, within the confines of what Quarkus supports. E.g there is no Spring XML support in Quarkus, so Camel Spring XML context definitions cannot be used.
If kotlin is your thing then routes can be defined and configured with Quarkus Kotlin.
Hopefully that short excursion into the world of Camel Quarkus application bootstrapping and configuration was useful in explaining the different choices available to build applications.
Happy Camel quarking!