Learn how the Apache Camel framework can assist you in creating microservice style applications in Java with just a few lines of code.
This article is also featured in this month’s JAX Magazine. For more tutorials like this, click here to get your free download going.
I‘ve been using microservice architectures before I knew they were called so. I used to create pipeline applications made up of isolated modules which interacted with each other through queues. Since then, a number of (ex)ThoughtWorks gurus have talked about microservices. Fred George[1], then James Lewis[2] and finally Martin Fowler[3] have all blogged about microservices, all of them helping to make it the next buzzword and now every company wants to have few microservices.
Nowadays there are #hashtags, endorsements, likes, trainings, even two day conferences [4] about it. The more I read and listen about microservice architectures, the more I realize how Apache Camel (and the accompanying projects around it) fits perfectly with this style of applications. In this post we will see how the Apache Camel framework can help us create microservice style applications in Java with few lines of code.
There is nothing new in microservices. Many similar applications have been designed and implemented as such for a long time. Microservices is just a new term that describes a style of software systems that have certain characteristics and follow certain principles. It is an architectural style where an application or software system is composed of individual standalone services communicating using lightweight protocols in event based manner. In the same way as TDD helps us to create decoupled single responsibility classes, microservices principles guide us to create simple applications at system level.
Here, we will not discuss the principles and characteristics of such architectures or argue whether it is a way of implementing SOA or a totally new approach to application design, but rather look at the most common practices used for implementing microservices and how Apache Camel can helps us accomplish that in practice. There is not a definitive list (yet) but if you read around or watch the videos posted above, you will notice that the following are quite common practices for creating microservices:
1. Small in size. The very fundamental principle of microservices says that each application is small in size and it only does one thing and does it well. It is debatable what constitutes small or large, the number varies from 10 LOC to 1000 but personally, I like the idea that it should be small enough to fit in your head. There are people with big heads, so even that is debatable ;) but I think that as long as an application does one thing and does it well so that it is not considered a nanoservice[5], that is a good size.
Camel applications are inherently small in size. A CamelContext with couple of routes with error handling and helper beans is approximately 100 LOC. Thanks to Camel DSLs and URIs for abstracting endpoints, receiving an event either through HTTP or JMS, unmarshaling it, persisting and sending a response back is around 50 LOC. That is small enough to be understood endtoend easily, rewritten and even thrown away without feeling any remorse.
2. Having transaction boundaries. An application consisting of multiple microservices forms an eventually consistent system of systems where the state of the whole system is not known at any given time. This on its own creates a barrier for understanding and adopting microservices in teams who are not used to work with this kind of distributed applications. Even though the state of the whole system is not fixed, it is important to have transaction boundaries that define where a message currently belongs.
Ensuring transactional behaviour across heterogeneous systems is not an easy task, but Camel has great transactional capabilities. Camel has endpoints that can participate in transactions, transacted routes and error handlers, idempotent consumers and compensating actions, all of which help developers easily create services with transactional behavior.
3. Self monitoring. This is one of my favorite areas of microservices. Services should expose information that describes the state of various resources it depends on and the service itself. These are statistics such as average, min, max time to process a message, number of successful and failed messages, being able to track a message, memory usage and so forth.
This is something you get OOTB with Camel without any effort. Each Camel application gathers JMX
statistics by default for the whole application, individual routes, endpoints and custom beans. It will tell you how many messages have completed successfully, how many failed, where they failed, etc. This is not read only API, JMX allows also updating and tuning the application at run time, so based on these statistics, using the same API you can tune the application accordingly. Also the information can be accessed with tools such as jConsole, VisualVM, Hyperic HQ, exposed over HTTP using Jolokia or feed into a great web UI called Hawtio[6].
Figure 1: Hawtio
If the functionality that is available with OOTB doesn’t fit your custom requirements, there are multiple extension points such as the nagios, jmx, amazon cloudwatch components and Interceptors for custom events.
Logging in messaging applications is another challenge, but Camel’s MDC logging combined with Throughput logger makes it easy to track individual messages or get aggregated statistics as part of the logging output.
5. Designed for failure. Each of the microservices can be down or unresponsive for some time but that should not bring the whole system down. Thus microservices should be fault tolerant and be able to recover when that is possible.
Camel has lots of helpful tools and patterns to cope with these scenarios too. Dead Letter Channel can make sure messages are not lost in case of failure the retry policy can send a message a couple of times for certain error conditions using custom backoff method and collision avoidance. Patterns such as Load balancer which supports Circuit breaker[7], Failover and other policies, Throttler to make sure certain endpoints do not get overloaded, Detour, Sampler, are all needed in various failure scenarios. So why not use them rather than reinventing the wheel in each service?
6. Highly Configurable. It should be easy to configure the same application for high availability, scale it for reliability or throughput, or said another way: have different degrees of freedom through configuration. When creating a Camel application using the DSLs, all we do is to define the message flow and configure various endpoints and other characteristics of the application. So Camel applications are highly configurable by design. When all the various options are externalized using properties component, it is possible to configure an application for different expectations and redeploy without touching the actual source code at all. Camel is so configurable that you can change an endpoint with another one(for example replace HTTP endpoint with JMS) without changing the application code at all which we will cover next.
7. With smart endpoints. Micro services favour RESTish protocols and lightweight messaging rather than Web Services. Camel favors anything. It has HTTP support as no other framework.It has components for Asynchronous HTTP, GAE URL fetch service, Apache HTTP Client, Jetty, Netty, Servlet, Restlet, CXF and multiple data formats for serializing/deserializing messages. As for the queuing support, OOTB there are connectors for JMS, ActiveMQ, ZeroMQ, Amazon SQS, Amazon SNS, AMQP, Kestrel, Kafka, Stomp, you name it.
8. Testable. There is no common view on this characteristic. Some favor no testing at all and relying on business metrics. Some cannot afford to have bad business metrics ever. I like TDD and for me having the ability to test my business POJOs in isolation from the actual message flow, then test the flow separately by mocking some of the external endpoints is invaluable. Camel testing support can intercept and mock endpoints, simulate events, verify expectations with ease. Having a well tested individual microservice is the only guarantee to have the whole system to work as expected.
9. Provisioned individually. The most important characteristics of microservices is that they run in isolation from other services most commonly as standalone Java applications. Camel can be embedded in Spring, OSGI or web containers. Camel can also run as a standalone Java application with embedded Jetty endpoints easily. But managing multiple processes, all running in isolation without a centralized tool is a hard job. This is what Fabric8[8] is made for. Fabric8 is developed by the same guys who developed Camel and supported by Red Hat JBoss. It is a poly Java application provisioning and management tool that can deploy and manage a variety of Java containers and standalone processes. To find out more about Fabric8, here is [9] nice post by Christian Posta.
10. Language neutral. Having small and independently deployed applications allow developers to choose thebest suited languagage for the given task. Camel has XML, Java, Scala, Groovy and few other DSLs with similar syntax and capabilities .But if you don’t want to you use Camel at all for a specific micro service, you can still use Fabric8 do deploy and manage applications written in other languages and run them as native processes [10].
In summary: Microservices are not strictly defined and that’s the beauty. It is a lightweight style of implementing SOA that works. So is Apache Camel. It is not a full featured ESB, but it can be as part of JBoss Fuse. It is not a strictly defined specification driven project, but a lightweight tool that works and developers love it.
References
[1] MicroService Architecture, by Fred George (video) https://www.youtube.com/watch?v=2rKEveL55TY
[2] MicroServices Java, the UNIX way, by James lewis (video) http://jz13.java.no/presentation.html?id=2a7b489a
[3] Microservices, by Martin Fowler http://martinfowler.com/articles/microservices.html
[4] μCon: The Microservices Conference https://skillsmatter.com/conferences/6312mucon
[5} Nanoservices http://arnon.me/wpcontent/uploads/2010/10/Nanoservices.pdf
[6] Hawtio http://hawt.io/
[7] Circuit Breaker Pattern in Apache Camel by Bilgin Ibryam http://www.ofbizian.com/2014/04/circuitbreakerpattern-inapachecamel.html
[8] Fabric8 http://fabric8.io/
[9] Meet Fabric8: An opensource integration platform by Christian Posta http://www.christianposta.com/blog/?p=376
[10] Micro Services the easy way with Fabric8 by James Strachan http://macstrac.blogspot.co.uk/2014/05/micro-serviceswithfabric8.html
REST APIs are the cornerstone of modern digital transformation, enabling seamless integration, automation, and monetization across industries. This comprehensive whitepaper explores how businesses can leverage REST APIs to drive growth, streamline operations, and unlock new revenue streams. With real-world success stories from companies like Twilio, Stripe, and Google, along with actionable strategies for API monetization, integration, and management, this guide provides everything you need to harness the full potential of REST APIs. Learn how to position APIs as core business assets, build developer-friendly ecosystems, and navigate the challenges of adoption to achieve transformative business outcomes.