A Basic Guide to Apache Camel Architecture

Lakshmeesh achar
8 min readJan 10, 2024

--

Why Apache camel?

Apache Camel is an open-source framework that facilitates and simplifies integration of various systems, applications, and data types. It offers an effective and scalable platform for developing enterprise integration patterns (EIP) with simplicity and elegance.

In the ever-changing environment of software development, enterprises must integrate varied applications and systems that frequently speak distinct languages. Apache Camel serves as a bridge between various diverse systems, facilitating seamless data interchange.

Architecture

Camel architecture is consists of

  • End points: Represent a message producer or consumer used by Camel runtime.
  • Components: These are essentially a factory of Endpoint instances.
  • RouteBuilder: It encapsulates rules, end points, and components to be consumed by Camel runtime.

The Camel Context is a fundamental part of the Camel architecture, and it encapsulates several key components and concepts that collectively define the behaviors of integration routes in Apache Camel.

Endpoints:
Endpoints in Camel are like entry and exit doors, which connect Camel to the outside world. These doors represent were Camel talks to other systems, services, or parts of a program. They decide where messages start and where they go.

Example: Imagine you want Camel to read and process files from a directory. You would use a file endpoint to specify the location.

from("file:/path/to/inputDirectory")
.to("processData");

In this example, the file endpoint “file:/path/to/inputDirectory” says that Camel should pick up files from that directory and send them to the “processData” route. Here from and to are two endpoints, you can consider it as entry and exit doors.

Routes:
Routes on Camel are the heart of the processing. It consists of a flow, which start on a endpoint, pass through a stream of processors/convertors and finishes on another endpoint. It is possible to chain routes by calling another route as the final endpoint of a previous route. A route can also use other features, such as EIPs, asynchronous and parallel processing.

A route is the step-by-step movement of a Message from an input queue, through various types of operations and reaching (such as filters and routers) to a destination queue (if any). The simplest way to define a route is as a chain of processors. Each route in Camel has a unique identifier that’s used for logging, debugging, monitoring, and starting and stopping routes. Routes also have exactly one input source for messages, so they’re effectively tied to an input endpoint.

        // Route to read from the input directory
from("file:/path/to/inputDirectory")
.log("Read file: ${header.CamelFileName}")
.to("direct:secondRoute");

// send the file to a different directory
from("direct:secondRoute")
.log("Sending file to a different directory:
${header.CamelFileName}")
.to("file:/path/to/outputDirectory");

Here the first route starts from the “file:/path/to/inputDirectory” endpoint, logs the filename of the read file, and then forwards the message to the “direct:secondRoute” endpoint.
The second route starts from the “direct:secondRoute” endpoint, logs the filename of the file being sent, and finally sends it to the “file:/path/to/outputDirectory” endpoint.
The “direct:secondRoute” endpoint acts as the connector between the two routes.

Data formats:
Data formats are specifications that govern the representation and structure of data during its journey through integration routes. These formats define how data is transformed and interpreted as it moves between different systems and components within the Camel framework.

Consider a scenario where an e-commerce application receives product information in JSON format and needs to transform it into XML format before sending it to system. In this case, Camel’s data format handling comes into play.

Language:
Languages in Apache Camel refer to scripting or expression languages that are used to define dynamic and expressive processing logic within integration routes. These languages allow developers to write custom code, make decisions, and manipulate data during the routing process.

Consider a scenario where you want to filter messages based on a custom condition. You can use the Simple language in Camel to achieve this

              from("direct:start")
.choice()
.when().simple("${body} contains 'important'")
.to("mock:importantMessages")
.otherwise()
.to("mock:otherMessages");

Similar to Simple language, In Apache Camel, you have the flexibility to use various languages to express conditions, transformations, and other processing logic within your routes.

Registry
In Apache Camel, a registry is a mechanism for storing and retrieving objects or components used in the Camel routes. It acts as a central repository for managing and looking up various resources, such as beans, endpoints, or custom components. Camel provides several types of registries, including SimpleRegistry, JndiRegistry, and others.

Consider a scenario where you want to create a custom bean and register it in a Camel registry for use in your routes. Below is an example using the SimpleRegistry.

        // Create a SimpleRegistry
SimpleRegistry registry = new SimpleRegistry();

// Register a custom bean in the registry
registry.put("myBean", new MyCustomBean());

// Create Camel context with the custom registry
CamelContext camelContext = new DefaultCamelContext(registry);

from("direct:start")
.bean("myBean")
.to("mock:result");

Here integration route uses the registered bean (“myBean”) in the bean DSL

Type Convertors:
Type converters in Apache Camel are components that automatically convert the message payload from one data type to another, facilitating smooth integration between heterogeneous systems and components.

Let’s consider a scenario where you have a route that receives an XML payload and needs to convert it to a Java object for further processing. Camel’s type converters can handle this transformation easily.

                from("direct:start")
.convertBodyTo(MyJavaObject.class)
.to("mock:result");

The convertBodyTo(MyJavaObject.class) statement automatically converts the XML payload to a Java object of type MyJavaObject.

Component:
In Apache Camel, components are the fundamental building blocks for connecting to external systems and services. They act as bridges that allow Camel to interact with various endpoints like databases, queues, APIs, and files. Imagine them as adapters that plug Camel into the diverse world of technologies and protocols.

For example, the file component lets you read and write data from files, while the jms component connects to JMS messaging systems.

Camel supports over 200+ built-in components. These components cover a wide range of technologies and protocols, allowing you to connect to various databases, queues, APIs, file systems, messaging systems, and more.

Messaging Models

In Camel, there are two abstractions for modelling messages, both of which we’ll cover in this section.

org.apache.camel.Message: The fundamental entity containing the data being carried and routed in Camel

org.apache.camel.Exchange: The Camel abstraction for an exchange of messages. This exchange of messages has an “in” message and as a reply, an “out” message.

org.apache.camel.Message:

Messages are the data itself that is transferred inside a Camel route. A Message can have a body, which is the data itself and headers, which are, like properties on a Exchange, key-value entries that can be used along the processing.

The Message body can be made of several types of data, such as binaries, JSON, etc. Messages are the entities used by systems to communicate with each other when using messaging channels.

Messages flow in one direction from a sender to a receiver

Messages are uniquely identified with an identifier of type java.lang.String. The message creator verifies and certifies that the identifier is unique, it’s protocol dependent, and it doesn’t have a guaranteed format. For protocols that do not define a unique message identification, Camel uses its own UID generator. Messages have a body (a payload), headers, and optional attachments.

Headers and attachments:
Headers are values associated with the message, such as sender identifiers, hints about content encoding, authentication information, and so on. Headers are key-value pairs, the name is a unique, case-insensitive string, and the value is of type java.lang.Object. This means that Camel imposes no constraints on the type of the headers. Headers are stored as a map within the message. A message can also have optional attachments, which are typically used for the web service and email components.

Body:
The body is of type java.lang.Object. That means that a message can store any kind of content. It also means that it’s up to the application designer to make sure that the receiver can understand the content of the message. When the sender and receiver use different body formats, Camel provides a number of mechanisms to transform the data into an acceptable format, and in many cases the conversion happens automatically with type converters, behind the scenes.

org.apache.camel.Exchange:

During routing, messages are contained in an exchange.

An exchange in Camel is the message’s container during routing. An exchange also provides support for the various types of interactions between systems, also known as message exchange patterns (MEPs).

MEPs are used to differentiate between one-way and request-response messaging styles. The Camel exchange holds a pattern property that can be either.

InOnly: A one-way message (also known as an Event message). For example, JMS messaging is often one-way messaging.

InOut: A request-response message. For example, HTTP-based transports are often request reply, where a client requests to retrieve a web page, waiting for the reply from the server.

A Exchange can have 2 messages inside, one representing the input and another one representing the output of a integration. The output message on Camel is optional, since we could have a integration that doesn’t have a response.

An exchange contains following elements:

  • Exchange ID: A unique ID that identifies the exchange. Camel will generate a default unique ID, if you don’t explicitly set
  • MEP: A pattern that denotes whether you’re using the InOnly or InOut messaging style. When the pattern is InOnly, the exchange contains an in message. For InOut, an out message also exists that contains the reply message for the caller.
  • Exception: If an error occurs at any time during routing, an Exception will be set in the exception field.
  • Properties: Similar to message headers, but they last for the duration of the entire exchange. Properties are used to contain global-level information, whereas message headers are specific to a particular message. Camel itself will add various properties to the exchange during routing. we can store and retrieve properties at any point during the lifetime of an exchange.
  • In message: This is the input message, which is mandatory. The in message contains the request message.
  • Out message: This is an optional message that only exists if the MEP is InOut. The out message contains the reply message.

In summary, Apache Camel’s architecture not only simplifies the complexities of integration but also elevates efficiency, making it a valuable tool for organizations seeking agile and reliable communication between different applications and services.

--

--