Spring Boot properties and Camel routes - an example
When you’re writing code you’re often reminded that hard-coding is bad; that including environment-dependent parameters inside your code, such as URLs, credentials and database configuration, is bad.
This advice is no different for writing Camel routes. If you find yourself in a situation where you’re hard-coding something - e.g. a REST service endpoint - then you should probably stop, and consider how you can externalise this configuration, in case the URL changes in future.
Fortunately, if you’re using Spring Boot, you get functionality to help you do this, as standard.
One of the cool features of Spring Boot is its ability to manage your application’s configuration and then pass that to your app, all without you having to explicitly write a line of code. You can read in parameters from config files, environment variables, and lots more. This makes it very easy to swap out different configurations for your app when you need them. Or, to make changes to the way your application runs, without having to recompile it.
When used with Camel, it’s especially useful because if you are developing some routes that are very similar, now you can write the code once and run multiple instances of the same route, with just the parameters modified.
Using application properties in Camel with Spring Boot - step-by-step example
Let’s create a Camel app with Spring Boot, and pass some configuration to it:
-
Create your Spring Boot application
You probably already know about Spring Initializr, the web tool for creating Spring Boot apps.
But did you know that you can create Spring apps using the command line as well? Command line FTW!
To do this, you just need to install the Spring Boot CLI. This will install the
spring
command into your environment. (Tip: if you’re using Mac OS, it’s also available through Homebrew; info in the link above).Then, to create a project, you can just run:
spring init -d=camel -g=com.yourcompany your-project-name
Where d=camel states that you want to use the
camel
dependency, and g=com.yourcompany is where you give the package name for your generated classes. -
Add a Camel route
Once we’ve created our project, we need to add some Camel routes.
Spring just gives us an empty boilerplate project, so let’s add a Camel
RouteBuilder
class. This class will configure a basic route that logs a greeting to the console at regular intervals, using a timer.Two aspects of the route are going to take values from Spring Boot configuration: the frequency of the timer, and the greeting phrase in the output. We mark parameters with curly braces {{ and }}, e.g.
{{myvariable}}
.So to create the route, create a file DemoRouteBuilder.java with these contents:
import org.apache.camel.builder.RouteBuilder; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; @Component public class DemoRouteBuilder extends RouteBuilder { @Override public void configure() { from("timer:mytimer?period={{timer.period}}") .setBody(simple("{{greeting.word}}, this is Camel running in Spring Boot!")) .to("log:out"); } }
-
Add configuration parameters
Now we’ll configure the parameters for our application.
Create a file src/main/resources/application.properties (or edit the file if it already exists).
Firstly, add the following line:
camel.springboot.main-run-controller=true
This first line is important as it ensures that Spring Boot stays “up”. In other words, it keeps the Camel route running until you terminate the Spring Boot container.
Then you add two config parameters like this:
timer.period=5000 greeting.word=Nihao
-
Run your application
Then, to run the app:
mvn spring-boot:run
Once Spring Boot has started up, you will see this in the logs:
2017-08-16 21:24:16.126 INFO 70530 --- [inRunController] o.a.camel.spring.SpringCamelContext : Route: route1 started and consuming from: timer://mytimer?period=5000 2017-08-16 21:24:16.128 INFO 70530 --- [inRunController] o.a.camel.spring.SpringCamelContext : Total 1 routes, of which 1 are started. 2017-08-16 21:24:16.129 INFO 70530 --- [inRunController] o.a.camel.spring.SpringCamelContext : Apache Camel 2.19.2 (CamelContext: camel-1) started in 0.300 seconds 2017-08-16 21:24:17.160 INFO 70530 --- [timer://mytimer] out : Exchange[ExchangePattern: InOnly, BodyType: String, Body: Nihao, this is Camel running in Spring Boot!] 2017-08-16 21:24:22.139 INFO 70530 --- [timer://mytimer] out : Exchange[ExchangePattern: InOnly, BodyType: String, Body: Nihao, this is Camel running in Spring Boot!] 2017-08-16 21:24:27.140 INFO 70530 --- [timer://mytimer] out : Exchange[ExchangePattern: InOnly, BodyType: String, Body: Nihao, this is Camel running in Spring Boot!]
You can also change the configuration properties when you run the route by adding the -D argument, like this:
mvn spring-boot:run -Dgreeting.word=Bonjour
Which will give you this output:
2017-08-16 21:27:06.215 INFO 70651 --- [timer://mytimer] out : Exchange[ExchangePattern: InOnly, BodyType: String, Body: Bonjour, this is Camel running in Spring Boot!] 2017-08-16 21:27:11.167 INFO 70651 --- [timer://mytimer] out : Exchange[ExchangePattern: InOnly, BodyType: String, Body: Bonjour, this is Camel running in Spring Boot!]
Get the example code on GitHub
You’ve just witnessed an example of Spring’s convention over configuration, where Spring establishes a convention for something - in this case, application parameters - making it easy to set them up with minimum fuss.
You can use this powerful feature to easily parameterise your Camel routes, and reduce the number of things you hard-code.
You can read more about properties and configuration in the official Spring Boot documentation.