Apache Camel - the dark side

Apache Camel is a popular integration framework with a long history and a good community around. It implements many integration patterns and has a big list of ready-to-use integrations.

It is very possible that I didn't get it or I didn't spend enough time working with it, but my experience with Camel is not great. I worked with Camel in two different teams with a different set of skills and experience but all Camel projects had several characteristics:

  • no tests or tests in bad shape
  • low type safety due to large number of casts
  • huge and complex routes

After a lot of pain, we decided to drop Camel and to use plain Spring Boot and a few things changed:

  • it became easier to write tests
  • easier to design and write the code
  • team happiness increased

Even after this, I don't think Camel is a bad framework and it can be successful in certain contexts. It is important to understand its good and bad parts and decide for yourself. I will highlight its bad parts as its good parts are easy to find e.g.

type safety

Exchange is central to the route and it provides no type safety. It is too easy to expect a rabbit but to get an orange. Exchange is like a raw Map but producer and consumer are most of usually in different files which makes this hard to spot.

testing

It was really difficult to write tests with Camel. Mocking did not work as expected, code to be tested was very coupled and negative testing was almost impossible. The resulting test was usually very complicated and very difficult to read. The number of disabled tests grew constantly as it was difficult to understand what went wrong.

surprising behavior

Nobody is probably happy when the behavior of a certain piece of code surprises. Something like a printReport method does also some updates in a database. Or when exceptions are swallowed and everything looks rosy. It was quite a surprise to find that this is the default Camel exception handling.

abstraction inversion

It gets really funny when people start implementing everything in routes. Do we need to add two numbers? Let's create a new route. We start coding in Camel DSL and things are getting complicated. Let's add more routes to solve this. In the end, something which can be done in a few lines of Java code becomes a huge untested route.

learning curve

We got so many times in situations where we knew something can be solved with plain Spring but we were in a route context and we had to find a Camel solution. Hence we spent hours and sometimes days doing something which could have been done in minutes. And so many times we realized later that the solution we found was not doing what we expected to do.

design

Camel seemed to stay in your way and not let you design code in the way wanted. We found it especially difficult to implement wrapping logic. Think about try-finally Java concept. We had to transform a local wrapping logic into a linear logic having its endpoints far away in the code.

custom integration

We had a case of one request - many responses pattern on a JMS interface. Camel supports only one request - one response pattern so the team had to work around this. A very unmaintainable solution was found for something which was done later in a different project very simple with plain Spring solution.

combining frameworks

We must always be careful when we add libraries to our projects. Adding 2 similar frameworks like Camel and Spring to a project is close to insanity. You'll find all crazy combinations of these 2 frameworks and interesting problems to solve when conflicts between libraries happen.

In closing words, be very careful when you decide what framework to use in your project. Question everything, start small and grow the solution slowly.