In my last post, I looked at Apache Camel as a sort of switchboard, useful in a home monitoring situation; mostly because you could control it just by manipulating the configuration rather than coding. Originally, I was using Camel as a servlet by simply extending the Tomcat Servlet example, which neatly packaged up the end result into a war file, for me to drop onto Jetty. However, if you’ve no use for the web side and just want to load a console app it’s a bit more complicated.
Now there is a Console example: and full marks to the Camel team -it’s one of some 30-odd examples you get to play with. The problem is that mvn compile exec:java works fine, but you’re stuck in the examples folder. What’s needed is a way to make it a proper application with all the dependencies. Now I’m sure this is trivial for the java/maven savvy, but for the rest of us, here’s the recipe:
Step 1 – Add AppAssembler to your pom.
As I understand the Camel/Maven game, and honestly as an occasional java user I don’t really, what’s needed is a method to not only create a jar file and all the dependencies, but also generate a method to kick the whole thing off. A bit of research led me to AppAssembler from CodeHaus. What this does is create a directory for your app, all it’s dependencies and a couple of clever start-up scripts to kick the whole thing off. All you need to do is add the following to your pom file, after the exec-maven plugin (I’ve used the Console example here).
<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>appassembler-maven-plugin</artifactId> <configuration> <programs> <program> <mainClass>org.apache.camel.example.console.CamelConsoleMain</mainClass> <name>camel-console</name> </program> </programs> <repositoryName>lib</repositoryName> <repositoryLayout>flat</repositoryLayout> </configuration> </plugin>
The are lots of things you can configure, but of note in this simple setup are:
- Main-class. Set it to the one in the exec-maven plugin
- Name. The bin scripts use this name so you get camel-console.bat etc.
- RepositoryLayout. I’ve chosen flat which dumps all the jars in one directory. Default is to split them into packages.
Now if you run mvn clean compile appassembler:assemble you will find, after a bit of maven’ing, a new appassembler folder will appear under your target folder with /bin and /lib folders. If you fire up bin/camel-console (after chmod +x ing) or bin/camel-console.bat to suit then you should see the Console example running in all it’s glory. Moreover, you can move this directory anywhere and it will still run perfectly. Result.
However, there’s a problem – our camel-config.xml where the <route>s live is now buried in a jar somewhere. As the whole purpose here was to create a configurable camel, we need a small amount of modification so that we can have our xml file in a handy conf directory.
Step 2 – External config file.
First thing is to tell the code that our config file is external. So, open the CamelConsoleMain.java in src/main/java. In there you’ll find a line like so:
We want an external file so we’ll change this to:
Next, create a src/main/config and copy camel-context.xml into it (why will become clear in a mo’). Rename it to routes.xml. Note, the old config file etc will still get packaged up as well – that’s redundant, but I’m making the fewest mods possible here.
Lastly, we’ll leverage our new friend appassembler. Add the following lines to the pom.xml in the appassembler plugin you added previously, below <name> and run the pithy mvn clean compile appassembler:assemble again:
<!-- Set the target configuration directory --> <configurationDirectory>conf</configurationDirectory> <!-- Copy the contents from "/src/main/config" to the target --> <copyConfigurationDirectory>true</copyConfigurationDirectory> <!-- Include the target configuration directory in the classpath --> <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
These properties tell it to copy anything in /src/main/config into /conf directory in the output. Notice I’ve also included the option not to add the /conf folder to the class path. Now, when our app runs it will find our config file in the right, relative, place. Of course, we could just create a /conf dir and drop our config into it once the assembly had happened. But, doing it this way gives us somewhere to put it in src.
So, it’s fairly simple to create a neat, deployable app that we can use on a variety of OS’s to leverage the power of Camel. If you want to run on a server, a handy App Assembler option is to create Java Service Wrapper scripts so you can start the code as a daemon.
One thing I didn’t handle here is an external log file which is handy if you need to change logging level etc. It turns out to be as simple as moving log4j.properties to our /src/main/config directory and setting the flag to add our /conf directory to the class path. Works like a charm.