A Camel project example with Java beans and OSGI Blueprint in Karaf
As a framework Camel can be used to write applications in Java or XML DSLs. These can then be hosted in various ways like in a Java or Spring Boot application or Karaf OSGI container.
Enterprise application integration (EAI) solutions are expected to provide specific capabilities like consistent data flow management and logging, environment settings management, simple packaging, frequent deployment and unit testing.
So how does a Camel project running in Karaf that meets such requirements look like?
To answer this question we’ll take as example a simple “database in the middle” integration scenario for which XML DSL Camel routes in an OSGI blueprint will suffice.
For development and unit testing I’m using an IDE like IntelliJ. The project contains the files needed to package and deploy in Karaf where our routes would be expected to run in a real world scenario.
You can find the code for this working example at
The picture below captures the project files. These are described further in the following sections.
Maven Project File
The application uses pom.xml to: a) gather all the Java libraries our code uses to compile and run, and b) define the Maven plugins used to package the Camel routes for deployment to Karaf.
From a command prompt with the project folder as the current directory you can visualize the full dependency tree by executing the following Maven goal:
mvn dependency:tree
Maven plugins employed by this example are listed below together with the reason they are used.
camel-maven-plugin
-> to run Camel routes in this example using "mvn camel:run"camel-bundle-plugin
-> to generate a Karaf specific MANIFEST.MF for the projectmaven-jar-plugin
-> to package the application in a JAR file and include MANIFEST.MFbuild-helper-maven-plugin
-> to add features.xml to the deployment files (so that later can be used by feature:install)
OSGI Blueprint
Application components are defined and glued together by a combination of Java beans and Camel routes in payments-data-flow.xml file.
A JDBC data source refers to an existing database. In this example’s code it is created in two ways: for testing purposes a Derby in-memory database is created using Spring’s DriverManagerDataSource class, while for Karaf deployment the same is created using features.xml described later below.
Once the data source is made available in the blueprint, it is used by TableSetupBean to create/remove payments table, generatePayment-route to post multiple entries into the table, and by processPayment-route to process each new table entry. This last route references PaymentBean and invokes its checkFraud() method to do the job.
The routes themselves use Camel SQL connector which is initialized once to point to the JDBC data source.
Karaf Deployment Manifest
At runtime, when our project runs as an OSGI bundle, blueprint and Java beans dependencies must be resolved by Karaf. features.xml ensures that referenced artifacts are installed explicitly together with our dataflow JAR.
In our case, besides creating the data source that provides persistence, this file brings Camel, JDBC and JNDI libraries and installs them too as OSGI bundles.
For details on managing OSGI dependencies see https://access.redhat.com/documentation/en-us/red_hat_jboss_fuse/6.3/html-single/managing_osgi_dependencies/index
Running the Unit Test
PaymentsDataFlowTest is the unit test class. It overrides org.apache.camel.test.blueprint.CamelBlueprintTestSupport to point to our OSGI blueprint file and create a dedicated data source.
The test method itself waits for a message on mock:result endpoint that processPayment-route posts to.
Before deployment into Karaf we can validate the code by running the unit test as follows:
mvn clean test -Dtest=PaymentsDataFlowTest
Deploying to Karaf
Provided you have Maven and Karaf installed on your machine and a copy of the source code you should be able able to run the steps below to deploy the Camel routes.
From a command prompt with current directory set to example’s pom.xml run:
mvn clean install
This will compile the code, run the unit test and publish the JAR, pom.xml and features.xml to your local Maven repository. Next run the following Karaf commands:
karaf@root()> feature:repo-add mvn:ld.lab.camel.sql/pymts-dataflow/1.0-SNAPSHOT/xml/features
karaf@root()> feature:install pymts-dataflow
Running and Testing from Karaf
To see the features added in the previous section you can run the command below.
karaf@root()> feature:list -i
You should see all the features expected are present, including pymts-dataflow that contains our Camel routes.
To check the deployed Camel routes run:
karaf@root()> camel:route-list
Context Route Status Total # Failed # Inflight # Uptime
— — — — — — — — — — — — — — — — — — — — — — — — — —
payments-data-flow generatePayment-route Started 989 0 0 1 hour 22 minutes
payments-data-flow processPayment-route Started 989 0 0 1 hour 22 minutes
To check the Camel endpoints defined by the routes run:
karaf@root()> camel:endpoint-list
Context Uri Status
— — — — — — — — —
payments-data-flow bean://paymentBean?method=checkFraud Started
payments-data-flow mock://result Started
payments-data-flow sql://insert into payments (id, debit, credit, amount, processed) values (:#id, :#debit, :#credit, :#amount, false) Started
payments-data-flow sql://select * from payments where processed = false?onConsume=update payments set processed = true where id = :#id Started
payments-data-flow timer://foo?period=5000
To check JDBC data source setup for this example run:
karaf@root()> jdbc:ds-list
Name | Service Id | Product | Version | URL | Status
jdbc/ds-payments | 269 | Apache Derby | 10.14.2.0 — (1828579) | jdbc:derby:memory:dbpymts | OK
To check Derby table records run:
karaf@root()> jdbc:query jdbc/ds-payments “select * from payments order by id desc fetch next 10 row only”
To check the data source service consumed by our Camel routes and Java beans run:
karaf@root()> jndi:names
JNDI Name | Class Name
osgi:service/jndi | org.apache.karaf.jndi.internal.JndiServiceImpl
osgi:service/jdbc/ds-payments | org.apache.derby.jdbc.EmbeddedDataSource
Finally, to check the route execution and read Karaf log run:
karaf@root()> log:display
16:47:01.941 INFO [Camel (payments-data-flow) thread #2 — timer://foo] Inserted into db new payment #1141.
16:47:02.441 INFO [Camel (payments-data-flow) thread #1 — sql://select%20*%20from%20payments%20where%20processed%20=%20false] Processed one database record; result message: Payment #1141 from Bob to Tim of 40GBP IS NOT fraud.
16:47:06.942 INFO [Camel (payments-data-flow) thread #2 — timer://foo] Inserted into db new payment #1142.
16:47:07.052 INFO [Camel (payments-data-flow) thread #1 — sql://select%20*%20from%20payments%20where%20processed%20=%20false] Processed one database record; result message: Payment #1142 from Joe to Ana of 98GBP IS fraud.