Christian Posta

About Christian Posta

Christian is a Principal Consultant at FuseSource specializing in developing enterprise software applications with an emphasis on software integration and messaging.

From inside the code: Camel Routing Engine Part I

So I’ve recently re-kindled my interest in how Apache Camel works. Camel is such a powerful integration tool and is very widely used, but anytime I put it to work, I can’t help but think “well, how the hell does it do all that!!” … guess I just have knack for not just accepting that it’s wonderful.. I want to know why.

If you’ve followed some of my posts in the past, you’ll remember I do have a blog post that dives into how the Camel DSL API works. More specifically, how can you just magically type “from(..)” “choice(..)” “simple(..)” etc and the DSL is just smart enough to know what you mean and how to string everything together. If you’re interested in how that all works, please take a peak at that post. Be forewarned, there is a couple UML class diagrams in there that are quite verbose and long.

So if you recall from the previous post, the DSL (whether it’s the Java DSL, or XML, or Scala, or any others) has a very specific role. It helps the author of the integration route express very clearly his/her intent and then build that into an abstraction called a RouteDefinition. The RouteDefinition is kind of the “blueprint” of your route, and knows about all of your processors, EIPs, and components. You can consider any time you call from(..) to be the start of a new RouteDefinition. The rest of the route gives it its shape. So for every from(..) there is a one-to-one mapping to RouteDefinition.

So when the CamelContext starts up, it gathers up all of the RouteDefinition(s) and begins to build a route from them. Take a look at DefaultCamelContext#doStartCamel for the entry point to all of this. Among other important things, like putting together the registry, endpoints, starting basic services, management, etc, etc.. you’ll see a call to DefaultCamelContext#startRouteDefinitions. This tells the RouteDefinitions to build Route objects, which are the actual Consumers (input) + Pipeline of processors (output) that route exchanges.

The next block goes into a little more detail about how this all works. Just like in previous blog posts about the internal workings of Camel, this detail is mostly for me: i.e., in the future when I have forgotten half of this, I want a refresher. And some people who’d like to contribute to Camel may find this interesting. For all others.. Feel free to skip this block.

– Start detailed section –

The DefaultCamelContext will loop through each RouteDefinition and will try to build a list of RouteS and RouteContextS.

Quick Detour:

What is a RouteContext though? In simple terms, you can think of it as the brains of the Route, and a place where the route-specific configurations live (stream caching? tracing? handle faults? etc, etc). It knows about the “from” consumer, the rest of the pipeline, the intercept strategies, route policy, and is able to construct the Route that will operate on exchanges.

It can be kind of confusing because there are a chain of calls to methods named “addRoutes()” when really they are building RouteContexts and building Routes. But look that aside for a moment. So the call to RouteDefinition#addRoutes(..) will return a list of RouteContext objects. It will also populate a List of (initially empty) routes. The multiplicity here is basically n to n. Because you can have multiple inputs to a RouteDefinition (e.g., by stringing together multiple from(..).from(..)), a single 1-to-1 RouteContext to Route can be expected, with a single pair PER from(). So in the previous example, there would be two RouteContexts and two Routes in the List. In the call to addRoutes(..) it also tries to turn the output definitions into real Processors. The Processors are the meat of the Route object. Each processor is built based on its respective definition (e.g., ChoiceDefinition, LogDefinition), but ultimately gets wrapped in a Channel object and added to the RouteContext.

sequence

So to wrap this up, The RouteDefinition will create the Route, RouteContext, and will also turn the individual output definitions into Processors. After these are created, a RouteService is created from the newly minted Route + RouteContext pairs, and this is established with the CamelContext for later starting and controlling the lifecycle of the route.

– End detailed section –

blocks

So …once we have the RouteService initialized, we need to start the routes, depending on whether they are auto-start up or not and their order. Take a look at DefaultCamelContext#doStartCamel once more, and toward the bottom is the call to DefaultCamelContext#doStartOrResumeRoutes. This will loop through our RouteServiceS and identify the correct startup order for the routes and then start them.

Routes are started in two phases:

  • WarmUp: In warm up phase, we look through all of the routes and start all of the “outputs” or processors/eips. Camel takes care to make sure
    this happens first, because we do NOT want to have the “inputs” or consumers started before all of the “outputs” are available.
  • Start/Resume: Start the consumer! This is endpoint/component specific. For example, the JMS Consumer will begin listening to a destination.

Note, at all parts of these stages in the lifecycle, there are callbacks that can be invoked so that you can plug in to this lifecycle and add your own custom startup code to coordinate with your application. Take a look at the Camel API for the type of callbacks available LifecylceStrategy

And there you have it. This is how route definitions are converted to actual routes and then started.

In Part II, I hope to go into how the processors are chained together, including a little more advanced chaining with the AsyncProcessor.
 

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

Leave a Reply


× 8 = sixty four



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close