Tom Donohue Tom Donohue

Can you have multiple Camel Contexts in one app?

Can you run multiple Camel Contexts in one app?

Let’s say you’ve defined a bunch of Camel contexts in different files, and you want them to be started in one container.

The answer to the question is… no. In fact, it’s worth having a read of the Camel 3 migration guide, because it’s pretty clear on this:

Multiple Camel Contexts, no longer supported

This means that, even if it’s possible for you to have multiple Camel contexts now, it’s probably not going to be possible from Camel 3.x onwards.

So is there another way?

One option worth considering is putting the routes you want to include inside a RouteContext instead of a CamelContext.

A RouteContext is like a subset of a CamelContext.

Then you reference the RouteContexts you want to import, and Camel will read them and add them to your context.

Using RouteContexts to add multiple routes to a Camel application

Here’s an example, using Spring XML.

In one file, camel-errorsubmit.xml, I have defined a RouteContext containing a route which will submit an error to a queue:

<?xml version="1.0" encoding="UTF-8"?>
<beans ...>
    <routeContext xmlns="http://camel.apache.org/schema/spring"
                  id="errorSubmit">
        <route id="error-submit-route">
            <from uri="direct:submit-error"/>
            <setBody>
                <constant>An error happened!</constant>
            </setBody>
            <log message="Logging an error on a message queue"/>
            <to uri="jms:queue:error.queue"/>
        </route>
    </routeContext>
</beans>

Note how I’m using a routeContext (not a camelContext) - and I’m assigning it an ID - errorSubmit.

In another file, camel-errorhandle.xml, I define a RouteContext containing a route which will handle the error:

<beans ...>
  <routeContext xmlns="http://camel.apache.org/schema/spring"
                id="errorHandle">
      <route id="error-handling-route">
          <from uri="jms:queue:error.queue"/>
          <log message="Received an error - ${body}"/>
      </route>
  </routeContext>
</beans>

Now let’s add both of these into my containing application.

In my main Camel context, I can simply use routeContextRef, to include the two RouteContexts. This will include my custom error submit and handling routes:

<camelContext xmlns="http://camel.apache.org/schema/spring">

    <!-- This will add the route definitions
    in errorSubmit and errorHandle -->
    <routeContextRef ref="errorSubmit"/>
    <routeContextRef ref="errorHandle"/>

    <route id="main-route">
        <from uri="timer:mytimer?period=5000"/>
        <log message="Throwing an error"/>
        <to uri="direct:submit-error"/>
    </route>

</camelContext>

Now, if I look at the Camel context using a monitoring tool like Hawtio, I can see that there is now one Camel Context containing three routes:

Multiple routes running under the same Camel Context (Hawtio)

The key to this solution is to make sure that Spring loads and parses all of these XML files.

In the case of Spring Boot, you can use the @ImportResource annotation to do this, which will look for any XML files at the locations you give:

@SpringBootApplication
@ImportResource("classpath*:camel-*.xml")
@EnableAutoConfiguration
public class MultipleContextsApplication {
    public static void main(String[] args) {
        SpringApplication.run(MultipleContextsApplication.class, args);
    }
}

Are there any other options?

If you only want to import Camel routes from XML files, and you’re not also defining any Spring beans in those same files, you can also look into using Camel’s RouteCollector.

This will automatically scan for any XML files on the classpath containing Camel routes, matching classpath:camel/*.xml. It will also look for any Camel REST DSL definitions using at classpath:camel-rest/*.xml.

Photo by Philippe Verheyden on Unsplash  

Comments

What do you think? You can use Markdown in your comment.

To write code, indent each line with 4 spaces. Or, to paste a lot of code, you can put it in pastebin.com and share the link in your comment.