Camel’s SEDA, Direct and VM components: a guide with examples


Camel’s SEDA, Direct and VM components: a guide with examples

When designing your Camel routes, you may sometimes want a route to have multiple inputs. Maybe you want to receive messages from a web service and from a JMS queue.

You can’t have multiple from() methods in the same route, so how can you have multiple entry points to the same route?

Similarly, you might want to reuse the same Camel message processing logic in multiple places, so how do you avoid duplicating code?

The answer to both these questions is to join your routes together, using Camel’s in-memory messaging components: Direct, Direct-VM, VM and SEDA.

In this article I’ll explain each of these components, how they differ, and how you can use them to make your routes more modular and awesome.

First…an example scenario

First I’m going to start with an example.

I have defined a route that validates an incoming order, by passing a message to some underlying system. My orders initially arrive through JMS messages.

Joining camel routes example scenario

But what happens when orders start coming from new sources - such as a file upload, or a web service call?

To avoid having to repeat the same route code, Camel has features built-in which allow routes to have multiple inputs, by using a range of joining components to glue these routes together.

So how does it work? Camel glues endpoints together using the components Direct, VM and SEDA.

These components join your Camel routes together in different ways. They are collectively known as Camel’s in-memory messaging components, because they allow messages to be passed between routes, while the message stays in memory at all times. This is a really important detail, which I’ll touch on again later.

But for now, let’s now look at each of these components to see how they differ, and where you might use them.

Direct component

This has to be one of the most frequently-asked questions by Camel beginners:

What does “direct” mean in a route?

The Direct component in Camel

You’ve probably seen the code direct:... in so many Camel tutorials on the web. But what does direct actually do?

direct is one of the most simple ways of linking your routes together. When it’s used in a from() definition, it creates a synchronous endpoint that can be invoked by other Camel routes. For example, this code:


Means that a Direct endpoint called yourname is created. That same endpoint can then be invoked in another to() statement somewhere else, like this:

.to("direct:yourname");  // sends the message to the direct:yourname endpoint

The Direct component joins routes in a synchronous way. This means that when one route sends a message to another direct endpoint using to("direct:myroute"), the route myroute will be executed in the same thread as the first route, and a response message will be returned.

In examples, it’s often used because it provides a simple entry point into a route, without having to expose a web service, or otherwise rely on an external interface.

The simplicity of Direct comes with some drawbacks.

Direct endpoints can only be accessed by other routes that are running in the same CamelContext and in the same JVM. This means that you cannot access a Direct endpoint from another CamelContext. Remember the CamelContext is the environment where your Camel routes are defined and later instantiated.

So what happens if you want to access a route in another CamelContext? You use the next component, Direct-VM.

Direct-VM component

This synchronous component works in a very similar way to the Direct component described above.

When used as a start component, Direct-VM allows a route to be invoked synchronously from another route.

The difference with the Direct-VM component is that direct-vm endpoints can be seen from other Camel Contexts, as long as they share the same Java Virtual Machine (JVM).

This opens up possibilities of linking routes together that were not developed in the same CamelContext. For example, you might use this component if you have different CamelContexts deployed in one container - such as when you’re deploying into JBoss Fuse or Talend ESB.

SEDA component

SEDA stands for staged event-driven architecture. The SEDA component joins Camel routes together asynchronously using an in-memory message queue.

While the Direct and Direct-VM components take a synchronous approach to joining routes, SEDA does the opposite. SEDA asynchronously joins routes together.

When a Camel route publishes a message to a seda: endpoint, the message is sent and control is returned immediately to the calling route.

A SEDA consumer endpoint contains a buffer which is used to store the incoming messages. SEDA is configured by default to create a pool of threads to process incoming messages, so several messages can be processed at once, making it potentially more performant.

In this way, SEDA can be thought of as a simple replacement for JMS queues. It provides queue-like functionality, but without the overhead of running an external message broker like ActiveMQ.

Remember that Camel publishes messages to a SEDA endpoint asynchronously.

You can only access SEDA endpoints that are located in the same CamelContext. So what happens if you want to send a message to a SEDA queue in another CamelContext? You use the next component, VM.

VM component

In a similar way to how Direct and Direct-VM are related, VM is a similar component to SEDA.

When used as a start component, SEDA allows a route to be invoked asynchronously from another route.

However the difference between SEDA and VM is that the VM component allows endpoints to be accessed from different Camel Contexts, if they are running in the same JVM.

Again, the VM component opens up possibilities of linking routes together that were not developed in the same Camel Context, in an asynchronous manner.

Summary and best practices

TL;DR? Here’s a reminder of the characteristics of the four components:

  Direct Direct-VM SEDA VM
Type Synchronous Synchronous Asynchronous Asynchronous
Within same CamelContext Yes Yes Yes Yes
Within same JVM - Yes - Yes

Thinking about using these components in your routes? Remember

The biggest drawback of using in-memory messaging is that if the application fails, there’s a big chance you’ll lose your messages.

This isn’t a major consideration if you are designing the kind of integrations where it doesn’t matter if the message goes missing.

But think back to the case of the order processing example at the top of this article. If an order gets lost during a server outage, this potentially means lost business. Uh-oh.

Have a think about when it’s appropriate to use these in-memory messaging components, and when it’s more appropriate to hand over the message to an external broker, such as ActiveMQ, for reliability.

There isn’t a hard and fast rule. The right solution always depends on your use case. So when designing integrations using Camel, think about what you’d do if you lost messages. Would it matter? If it would, consider using transactions and persistent messaging to minimise any message loss.

Has this article helped you understand the difference between the Direct, VM and SEDA components? How are you planning to use these components in your Camel routes? Please share your comments, thoughts and questions in the box below!

Leave a Comment