Guide to Camel’s SEDA, Direct and VM components(FW)
(from :https://cleverbuilder.com/articles/camel-direct-vm-seda/, author:Tom Donohue)
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.
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?
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 which starts with from(direct):
from("direct:yourname")...
…will create a Direct endpoint called yourname. 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
Apache Camel’s 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.
Example: using the Direct component
Example: using the Direct component
from("file:/home/files/in") // receive a file
.to("direct:processTheFile"); // send to direct endpoint
.to("Body is now ${body}"); // will print 'Eggs!'
// meanwhile...
from("direct:processTheFile") // receive from direct endpoint
.setBody("Eggs!"); // modify the message body
2
3
4
5
6
7
This very simple example receives files using Camel’s File component. Each file processed is passed, as an Exchange, to the direct endpoint processTheFile.
Separately, we have defined the processTheFile endpoint as the start component for a route which modifies the message body. Once this is done, the new message is returned back to the calling route. All of this happens synchronously, within the same thread.
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 container where your Camel routes are created and booted up.
So what happens if you want to access a route in another CamelContext? You use the next component, Direct-VM.
Direct-VM component
Direct-VM is a component that allows you to synchronously call another endpoint in the same JVM, even if it’s in a different CamelContext.
When used as a start component, Direct-VM exposes that route as an endpoint which can 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).
Example: using the Direct-VM component
If we wanted to show off the Direct-VM component, we could define a route in Application A:
from("file:src/files/input")
.to("direct-vm:process-file") // invoke the direct-vm endpoint
2
Which would call this Direct endpoint, located in Application B…:
from("direct-vm:process-file") // receive from direct-vm endpoint
.to("log:samplelog"); // log the message
2
As long as both of these applications are running in the same JVM – for example, using an application container, like Apache Karaf, Wildfly or even different CamelContexts in the same Spring Boot application – then Application A will be able to call the direct-vm endpoint in Application B.
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
Camel’s SEDA component allows you to join routes together using a simple queue.
In a Camel route, when a message is sent to a SEDA endpoint, it is stored in a basic in-memory queue, and control is returned back to the calling route immediately.
Then, independently, a SEDA consumer picks up the message from the queue, and begins processing it.
Example: Using the SEDA component
rest("/orders").post() // receive an order via REST
.to("seda:processOrder"); // send to the seda queue
.setBody("Thanks for ordering!"); // create a REST response
from("seda:processOrder") // receive from the seda queue
.log("Processing an order...")
.to("file:orders/out");
2
3
4
5
6
7
8
9
In the example above, messages will be received via a REST service and published to the SEDA endpoint. Messages arrive at the processOrder SEDA endpoint and are processed, where they are written to a location on disk, using the file: component.
SEDA does this by creating its own buffer which is used to store the incoming messages. Out of the box, SEDA creates a pool of threads to process incoming messages, meaning that 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.
Guide to Camel’s SEDA, Direct and VM components Updated: May 22, 2018 Guide to Camel’s SEDA, Direct and VM components
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.
ON THIS PAGE FIRST…AN EXAMPLE SCENARIO DIRECT COMPONENT EXAMPLE: USING THE DIRECT COMPONENT DIRECT-VM COMPONENT EXAMPLE: USING THE DIRECT-VM COMPONENT SEDA COMPONENT EXAMPLE: USING THE SEDA COMPONENT VM COMPONENT DRAWBACKS OF SEDA AND VM SUMMARY AND BEST PRACTICES COMPARISON OF DIRECT, SEDA, VM AND DIRECT-VM 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 which starts with from(direct):
from("direct:yourname")... …will create a Direct endpoint called yourname. 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 Apache Camel’s 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.
Example: using the Direct component Let’s illustrate the Direct component with an example:
from("file:/home/files/in") // receive a file .to("direct:processTheFile"); // send to direct endpoint .to("Body is now ${body}"); // will print 'Eggs!'
// meanwhile...
from("direct:processTheFile") // receive from direct endpoint
.setBody("Eggs!"); // modify the message body
This very simple example receives files using Camel’s File component. Each file processed is passed, as an Exchange, to the direct endpoint processTheFile.
Separately, we have defined the processTheFile endpoint as the start component for a route which modifies the message body. Once this is done, the new message is returned back to the calling route. All of this happens synchronously, within the same thread.
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 container where your Camel routes are created and booted up.
So what happens if you want to access a route in another CamelContext? You use the next component, Direct-VM.
Direct-VM component Direct-VM is a component that allows you to synchronously call another endpoint in the same JVM, even if it’s in a different CamelContext.
When used as a start component, Direct-VM exposes that route as an endpoint which can 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).
Example: using the Direct-VM component If we wanted to show off the Direct-VM component, we could define a route in Application A:
from("file:src/files/input") .to("direct-vm:process-file") // invoke the direct-vm endpoint Which would call this Direct endpoint, located in Application B…:
from("direct-vm:process-file") // receive from direct-vm endpoint .to("log:samplelog"); // log the message As long as both of these applications are running in the same JVM – for example, using an application container, like Apache Karaf, Wildfly or even different CamelContexts in the same Spring Boot application – then Application A will be able to call the direct-vm endpoint in Application B.
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 Camel’s SEDA component allows you to join routes together using a simple queue.
In a Camel route, when a message is sent to a SEDA endpoint, it is stored in a basic in-memory queue, and control is returned back to the calling route immediately.
Then, independently, a SEDA consumer picks up the message from the queue, and begins processing it.
Example: Using the SEDA component Here’s an example of a SEDA queue in action:
rest("/orders").post() // receive an order via REST .to("seda:processOrder"); // send to the seda queue .setBody("Thanks for ordering!"); // create a REST response
from("seda:processOrder") // receive from the seda queue
.log("Processing an order...")
.to("file:orders/out");
In the example above, messages will be received via a REST service and published to the SEDA endpoint. Messages arrive at the processOrder SEDA endpoint and are processed, where they are written to a location on disk, using the file: component.
SEDA does this by creating its own buffer which is used to store the incoming messages. Out of the box, SEDA creates a pool of threads to process incoming messages, meaning that 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, as long as 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.
Guide to Camel’s SEDA, Direct and VM components
Updated: May 22, 2018 Guide to Camel’s SEDA, Direct and VM components
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.
ON THIS PAGE FIRST…AN EXAMPLE SCENARIO DIRECT COMPONENT EXAMPLE: USING THE DIRECT COMPONENT DIRECT-VM COMPONENT EXAMPLE: USING THE DIRECT-VM COMPONENT SEDA COMPONENT EXAMPLE: USING THE SEDA COMPONENT VM COMPONENT DRAWBACKS OF SEDA AND VM SUMMARY AND BEST PRACTICES COMPARISON OF DIRECT, SEDA, VM AND DIRECT-VM 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 which starts with from(direct):
from("direct:yourname")... …will create a Direct endpoint called yourname. 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 Apache Camel’s 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.
Example: using the Direct component Let’s illustrate the Direct component with an example:
from("file:/home/files/in") // receive a file .to("direct:processTheFile"); // send to direct endpoint .to("Body is now ${body}"); // will print 'Eggs!'
// meanwhile...
from("direct:processTheFile") // receive from direct endpoint
.setBody("Eggs!"); // modify the message body
This very simple example receives files using Camel’s File component. Each file processed is passed, as an Exchange, to the direct endpoint processTheFile.
Separately, we have defined the processTheFile endpoint as the start component for a route which modifies the message body. Once this is done, the new message is returned back to the calling route. All of this happens synchronously, within the same thread.
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 container where your Camel routes are created and booted up.
So what happens if you want to access a route in another CamelContext? You use the next component, Direct-VM.
Direct-VM component Direct-VM is a component that allows you to synchronously call another endpoint in the same JVM, even if it’s in a different CamelContext.
When used as a start component, Direct-VM exposes that route as an endpoint which can 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).
Example: using the Direct-VM component If we wanted to show off the Direct-VM component, we could define a route in Application A:
from("file:src/files/input") .to("direct-vm:process-file") // invoke the direct-vm endpoint Which would call this Direct endpoint, located in Application B…:
from("direct-vm:process-file") // receive from direct-vm endpoint .to("log:samplelog"); // log the message As long as both of these applications are running in the same JVM – for example, using an application container, like Apache Karaf, Wildfly or even different CamelContexts in the same Spring Boot application – then Application A will be able to call the direct-vm endpoint in Application B.
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 Camel’s SEDA component allows you to join routes together using a simple queue.
In a Camel route, when a message is sent to a SEDA endpoint, it is stored in a basic in-memory queue, and control is returned back to the calling route immediately.
Then, independently, a SEDA consumer picks up the message from the queue, and begins processing it.
Example: Using the SEDA component Here’s an example of a SEDA queue in action:
rest("/orders").post() // receive an order via REST .to("seda:processOrder"); // send to the seda queue .setBody("Thanks for ordering!"); // create a REST response
from("seda:processOrder") // receive from the seda queue
.log("Processing an order...")
.to("file:orders/out");
In the example above, messages will be received via a REST service and published to the SEDA endpoint. Messages arrive at the processOrder SEDA endpoint and are processed, where they are written to a location on disk, using the file: component.
SEDA does this by creating its own buffer which is used to store the incoming messages. Out of the box, SEDA creates a pool of threads to process incoming messages, meaning that 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, as long as 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.
Drawbacks of SEDA and VM
The biggest drawback of using in-memory messaging like SEDA and VM is that if the application crashes, there’s a big chance you’ll lose all your messages.
This isn’t a major consideration if you’re designing the kind of integrations where it doesn’t matter if the message goes missing.
But think back to 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 might be more appropriate to hand over the message to an external message 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.
Summary and best practices
So now you’ve learned about each component, which should you use, and when?
SEDA vs Direct:
For synchronous (request/response) interactions within the same CamelContext, use Direct
For asynchronous (fire-and-forget) processing within the same CamelContext (to process messages in a queue-like fashion), use SEDA
VM vs Direct-VM:
- For synchronous (request/response) interactions in another CamelContext but within the same JVM, use Direct-VM
- For asynchronous (fire-and-forget) interactions in another CamelContext but within the same JVM, use VM
Comparison of Direct, SEDA, VM and Direct-VM
Component | Type | Within same CamelContext | Within same JVM |
---|---|---|---|
Direct | Synchronous | Yes | No |
Direct-VM | Synchronous | Yes | Yes |
SEDA | Asynchronous | Yes | No |
VM | Asynchronous | Yes | Yes |