Route Configuration

Camel 3.12 introduces route configuration which is used for separating configurations from the routes. This can be used in situations such as configuring different error handling across a set of routes. In previous versions of Camel this was more cumbersome to do, as you would either have to copy the same configuration to a set of routes or rely on global error handling configuration.

Now you can configure a number of route configurations, and then specify on each route which configuration to use (you can use match by ids, wildcards, and regular expression).

The route configuration is supported by all DSL’s, so useable by: Java, XML, Groovy, Kotlin and so forth.

In the route configuration you can setup common strategies for:

Route Configuration Builder in Java DSL

With Java DSL you can use RouteConfigurationBuilder to specify the configuration as shown below. The builder is similar to RouteBuilder so it’s use is familiar.

public class MyJavaErrorHandler extends RouteConfigurationBuilder {

    @Override
    public void configuration() throws Exception {
        routeConfiguration("javaError")
            .onException(Exception.class).handled(true)
            .log("Java WARN: ${exception.message}");
    }
}
The RouteConfigurationBuilder uses configuration as the method where the configuration is coded. This is on purpose not to use the configure method which the regular Java DSL RouteBuilder uses for coding Camel routes.

In the example above, then there is only one route configuration which has been assigned the ID javaError. This ID allows us to refer to this configuration later when you want to assign which routes are using the configuration.

This configuration is a basic configuration that just catches and handles all exceptions and logs a WARN message.

Assigning route configurations to routes

To use this configuration in your routes, then you can assign it with routeConfigurationId as shown:

public class MyJavaRouteBuilder extends RouteBuilder {

    @Override
    public void configure() throws Exception {
        from("timer:java?period=2s")
            // refer to the route configuration by the id to use for this route
            .routeConfigurationId("javaError")
            .setBody(method(MyJavaRouteBuilder.class, "randomNumber"))
            .log("Random number ${body}")
            .filter(simple("${body} < 30"))
                .throwException(new IllegalArgumentException("The number is too low"));
    }

    public static int randomNumber() {
        return new Random().nextInt(100);
    }
}

In the routeConfigurationId the configuration to use is specified by the ID, eg javaError.

Multiple configurations can be assigned (separated by comma), such as:

.routeConfigurationId("javaError,myAudit")

The route configurations supports matching by:

  • match by exact ID name. This is the sample we have seen above.

  • match by wildcard

  • match by regular expression.

Wildcards are text ending with a *; they are matched when the configuration ID starts with the specified text followed by any characters. For instance you can do:

.routeConfigurationId("java*,myAudit")

Here we use wildcard in java* which means any configuration that starts with java is a match.

Match by regular expression is just like match by wildcard but using regex instead.

.routeConfigurationId(".*error.*")

Here we want to match any routes that has error in the name.

Adding route configurations to CamelContext

Because a RouteConfigurationBuilder is also a RouteBuilder then you add route configurations the same way for RouteBuilder such as using the API on CamelContext

CamelContext context = ...
// add the route configuration
context.addRoutes(new MyJavaErrorHandler());
// add the regular route
context.addRoutes(new MyJavaRouteBuilder());

If you use Spring Boot, then your Camel routes and route configurations can be auto-discovered by the spring boot component scanning. This requires adding the @Component annotation to the class.

Route configuration with Endpoint DSL

The Endpoint DSL can also be used for route configurations. This requires adding camel-endpointdsl to the classpath, and then using org.apache.camel.builder.endpoint.EndpointRouteConfigurationBuilder, which offers the type safe DSL for Camel endpoints.

Default route configurations

Route configurations are either given an explicit unique ID, or the configuration is nameless. A nameless configuration is used as default/fallback configuration, for routes which have NOT been explicitly assigned route configurations.

Suppose you have one nameless configuration and another named javaError:

public class MyJavaErrorHandler extends RouteConfigurationBuilder {

    @Override
    public void configuration() throws Exception {
        routeConfiguration()
            .onException(Exception.class).handled(true)
            .log("WARN: ${exception.message}");

        routeConfiguration("retryError")
            .onException(Exception.class).maximumRedeliveries(5);
    }
}

And the following two routes:

   from("file:cheese").routeId("cheese")
        .to("kafka:cheese");

   from("file:beer").routeId("beer")
        .routeConfigurationId("retryError")
        .to("jms:beer");

In the example above, the cheese route has no route configurations assigned, so the route will use the default configuration, which in case of an exception will log a warning.

The beer route on the other hand has route configuration retryError assigned, and this configuration will in case of an exception retry again up till 5 times and then if still an error then fail and rollback.

If you add more routes, then those routes can also be assigned the retryError configuration if they should also retry in case of error.

Route Configuration in XML

When using XML DSL then you can code your route configurations in XML files as shown below:

<routeConfiguration id="xmlError">
    <onException>
        <exception>java.lang.Exception</exception>
        <handled><constant>true</constant></handled>
        <log message="XML WARN: ${exception.message}"/>
    </onException>
</routeConfiguration>

And in the XML routes you can assign which configurations to use:

<route routeConfigurationId="xmlError">
    <from uri="timer:xml?period=5s"/>
    <log message="I am XML"/>
    <throwException exceptionType="java.lang.Exception" message="Some kind of XML error"/>
</route>

In this example the route is assigned the xmlError route configuration by the exact ID.

Route Configuration in YAML

When using YAML DSL then you can code your route configurations in YAML files as shown below:

- route-configuration:
    - id: "yamlError"
    - on-exception:
        handled:
          constant: "true"
        exception:
          - "java.lang.Exception"
        steps:
          - log:
              message: "YAML WARN ${exception.message}"

And in the YAML routes you can assign which configurations to use:

- route:
    # refer to the route configuration by the id to use for this route
    route-configuration-id: "yamlError"
    from: "timer:yaml?period=3s"
    steps:
      - set-body:
          simple: "Timer fired ${header.CamelTimerCounter} times"
      - to:
          uri: "log:yaml"
          parameters:
            show-body-type: false
            show-exchange-pattern: false
      - throw-exception:
          exception-type: "java.lang.IllegalArgumentException"
          message: "Error from yaml"

In this example the route is assigned the yamlError route configuration by the exact ID.

Mixing DSLs

Routes and route configuration are not required to use the same language. For example you can code route configurations in Java, and then use XML DSL for the routes, and they would work together.

Packaging route configurations in reusable JARs

You can package common route configurations into JARs which you can then use together with your Camel applications, by adding the JARs as dependencies to the classpath (such as in Maven pom.xml file).

This allows for example to use a common practice among your Camel applications.

Logging Summary

If you set startup-summary-level=verbose then Camel will log for each route which route configurations they have been assigned.

This option can be configured via Java API and also in application.properties for Camel on Spring Boot, Quarkus, and Camel standalone via camel-main

camelContext.setStartupSummaryLevel(StartupSummaryLevel.Verbose);

And with Spring Boot:

camel.spring-boot.startup-summary-level = verbose

And in Camel Main / Quarkus:

camel.main.startup-summary-level = verbose