• Articles about computing
• Articles about software development
• Apache integration software
Creating an Apache Camel route in Java using Maven, step-by-step
The article follows on from my previous article
Creating an Apache Camel route in Java from the ground
up. In that article I explained how to build and run an Apache
Camel route specified in Java using only a command prompt. In my view, there
is no better way to get a detailed understanding of how software like
Camel or ActiveMQ can be used than to drive it from the command line, managing
all the dependencies manually. If you followed that article, however,
you'll have realized how awkward it is to build and run Java code that has
large numbers of dependencies that way. Of course, that is why we all
use build and dependency management frameworks, even if we don't use
This article describes the implementation of exactly the same file-copier
Camel route, but using Maven to manage the dependencies, and
to build and run the application. Even if you're broadly familiar with the
technology, I would recommend that you read the
previous article, at least in outline, even
if you don't try the detailed steps. Unless you do that, the sophistication
of Maven completely obscures the complexity of the build process.
Pragmatically, that's not a bad thing; but it's not very educational.
This article describes Maven in outline, then explains how to use it to
build a Camel application into a stand-alone JAR file that can be
executed; the JAR file will contain all the dependencies needed to
run the application.
We proceed step-by-step, starting with the installation of
Maven, then entering the necessary code and configuration.
However, if you want to see the example working without cutting-and-pasting
all the source code, the complete Maven workspace is available from
the Downloads section at the end of this article.
Apache Maven is a build and dependency
management tool for Java development. In some ways it is similar to Ant,
in that it automates the steps necessary to build and package an
application. It is different from Ant, and indeed from most build management
tools, in two important ways:
1. It integrates dependency management, and can retrieve libraries from
a central repository, and
This second point is summed up in the phrase convention over
configuration that is often in the context of Maven. Maven assumes
that developers will follow essentially the same conventions about
such things as file naming and directory layout; if they do, then
everything works as if by magic. If not, then getting Maven to behave can
be a battle. My experience is that, if you're going to use Maven in a
software project, it's best to use it from the very start, and let it
set things up as it likes; retro-fitting Maven to an existing, complex
project is not a task to that is likely to give much pleasure.
Like Ant, Maven is configured using an XML file
2. it is configured in a rather declarative way — in general it
is not necessary, and sometimes not even possible, to specify the exact
relationships between build steps.
pom.xml). Although Maven will create a
pom.xml for a project, very often this file will
be managed using an IDE tool — it's not impossible to
use a text editor, but it's not a whole heap of fun. The
XML file not only specifies what
operations will be needed to build the project, but also the other
components on which it has dependencies. Most of the libraries needed to
support development for Apache software (Camel, ActiveMQ, Tomcat...)
are available from a central repository, so adding these to your
project should involve no more work than adding a few lines to
Whatever its strengths and weaknesses, there's no doubt that Maven has become
very popular in the open-source Java domain. Most books and articles
about development with Apache integration software more-or-less assume its
use, so it's difficult get by without at least a working knowledge of
Step 1: obtain and install Maven
How easy or difficult this is depends on your platform;
it's rarely more difficult than downloading and unpacking a tarball, and
setting a few environment variables; and it may be much easier.
Binaries are available from the
Maven download page,
which also contains detailed installation instructions for
On RedHat-based Linux system, installation of Maven should be as
easy as running
# yum install maven
At the time of writing this will get you version 3.0.5, which is not the
latest version, but it's good enough for the purposes of
To test that Maven is correctly installed, just run
It goes without saying that you need a Java JVM to run Maven.
If you are using a RedHat or Fedora Linux system (and possibly other
distributions), be aware that the
Linux installer probably installs the OpenJDK Java compiler, which is
not compatible with Maven, as it lacks the bits
that Maven requires for compiling Java code. If you don't want to
replace the platform Java, just install a Sun/Oracle JDK in a different
directory, and run Maven using |
% mvn --version
which should provide some version information.
Step 2: Create a Maven project workspace
The "convention over configuration"
philosophy adopted by Maven requires that a project workspace is set up
in a particular way. There's nothing particularly objectionable about
its prefered set-up — in fact, it's pretty natural for Java work. However
because we don't all naturally
set things up in exactly the way Maven likes, the usual way to start working
with Maven is to have it create a project workspace, layed out
the way it likes. The workspace is configured according to a template
which is called an archetype in Maven jargon. There are a
great many such archetypes available, to suit different application
For this example, we'll use the
archetype. This archetype has the following characteristics.
To create the project workspace using the
- The project file
pom.xml specifies dependencies on
the Camel core framework, as well as a number of other components
that are likely to be useful, such as
- The project includes some simple boilerplate code to initialize
Camel and configure a simple route; this can be used as the basis of a
- A default
log4j configuration file is created
- The project file includes a plugin to allow the complete application
to be run at the command line, with a classpath that includes all the
layout, issue the following command in a suitable directory.
$ mvn archetype:generate \
version uniquely identify the project so
that it can, in principle,
become part of a Maven repository itself. More prosaically,
artifactId becomes the name of the new directory
created to hold the project files, and
the package name of the boilerplate Java code that Maven
The generated project workspace will have a reasonably familiar layout,
even if it is not the one a particular developer would have
chosen. There is a
Note that it isn't necessary to install Camel explicitly to build a
Camel project with Maven — the necessary bits will be downloaded
automatically, and stored in a local repository
$HOME/.m2/repository on Linux). When we say
archetypeVersion=x.x.x, we're indicating the version
of Camel we want, not the version we have.
src/main/java directory which
forms the root of the Java source code; a
directory for the output of the build process, and
src/main/resources for configuration files.
You can freely add new directories to
Maven will Do the Right Thing and assume you want them compiled.
I'm not going to reproduce the generated
pom.xml here, but
there are a few points of note.
This entry specifies the class that will be run when we tell Maven
to 'exec:java'. The source of this class
is generated automatically, and contains
main() method that initializes Camel and creates a
This section specifies a dependency — on
this case. Maven will automatically download and store dependent
modules before building the project.
Step 3: Coding the route
The automatically-generated boilerplate code will create a default
route; in fact, it should be ready to run as soon as the project
workspace is created. However, I want to make this route the
same as the one described in the earlier article on Camel, so
it will be necessary to replace the default route.
If you look at the boilerplate class
you'll see that it delegates the actual route configuration to
MyRouteBuilder, which is in the same package,
and therefore in the same directory. This should be replaced by
the following code.
public class MyRouteBuilder extends RouteBuilder
public void configure()
This route copies files from the directory
/tmp/out, and logs that it has done so. Of course,
you might need to change these directories on your system.
Step 3: configure logging
We would like to see the DEBUG-level log output from the route, but
not for anything else (unless, of course, we're debugging Camel).
To do this, just add the following line to
Camel itself will get the default, INFO, log level, unless you change it.
Step 4: compiling
With Maven, this could hardly be easier:
$ mvn compile
The first time you execute this command, it could take a long time, because
the entire Camel framework and all its dependencies have to be downloaded
to the local repository — about 100Mb in total. Thereafter it should be
a lot faster.
Note that there's no need to set up any class search path — the Maven
dependency management assumes that libraries downloaded to satisfy
dependencies should be included on the class path.
The compiled output will be written to the
Step 5: running the route
Again, with Maven, this could hardly be simpler:
$ mvn exec:java
This tells Maven (specifically, the
to run the Java class specified in the
pom.xml file; again,
the classpath is managed automatically according to the dependencies.
To test the route is working, copy a file into
(or whatever directory you specified), and check that it appears
/tmp/out. The log should show something like this:
[ExchangePattern: InOnly, BodyType: org.apache.camel.component.file.GenericFile,
Body: [Body is file based: GenericFile[/tmp/in/test.txt]]]
Step 6: building a self-contained application for distribution
With luck, we're now able to run the Camel application under the control
of Maven. But what if we want to distribute the application, or just to
run it without Maven? The problem lies in figuring out which library JARs to
make available on the class search path. When we built the application
manually this was conceptually easy — since we were specifying all the
JARs on the command line, we would know exactly which JARs to distribute;
but if we're using Maven to manage all the dependencies implicitly, we
won't necessarily have that information at hand.
It is possible to get Maven to identify the dependencies in detail but,
since we want in this case to build a self-contained application, it's
perhaps nicer to ask Maven to build the application in a single JAR file,
containing all the dependent classes. We can then run the application
using only that one JAR file.
There are various ways to create a single-JAR application using Maven;
here I describe how to use the
maven-assembly-plugin plugin to
do it. Just add the following block of almost-boilerplate code
plugins section of
The only program-specific code here is:
This tells Maven to add to the JAR file's MANIFEST.MF file the line:
This, in turn, will tell the JVM what class's
to run when we run the JAR. The generated jar will be
To build the complete, self-contained application:
mvn compile assembly:single
Note that we still need to specify
compile as a specific step.
This illustrates a difference between Maven and tools like Ant (and Make,
for that matter): Maven manages dependencies between the project and its
libraries, but it isn't easy to specify dependencies between build steps.
With Ant, it would be trivially easy to specify that the 'assemble' operation
was dependent on successful completion of the 'compile' operation.
With Maven there is, so far as I know, no obvious way to do that.
To run the JAR application, just use the command:
java -jar target/mavencameltest-1.0-SNAPSHOT-jar-with-dependencies.jar
Because this JAR is self-contained, it can be used on a system without
I hope it's clear that using Maven takes away a lot of the administrative
hassle from setting up a Java application with complex dependencies.
The only thing left for the developer to do is to write the actual code...
Source code bundle