Monday, March 7, 2016

Direct vs Seda vs Direct-Vm vs VM end points in Apache Camel

Apache camel is a rule based routing and mediation engine. It provides facility to perform seamless integration of various type of components via routes and endpoints.

Camel comes up with four camel aware end points.These end points have following similarities-
1. All of these end points accept camel exchange message only.
2. All of these end points are in-memory. Message in these queues would get lost in case of abrupt shutdown of system.

All of these queues provide better performance than other end points because no camel message transformation is performed by the end point.

Despite having multiple similarities, the purpose of each and every end point is different.The exact nature of difference can be noticed from the following matrix -


With In Same Camel Context
Across Camel contexts in a Single JVM
Synchronous
direct
direct-vm
Asynchronous
seda
vm

Synchronous communication refers to the communication, where the sender sends the message and proceed ahead only when response is retrieved back. In this case, all further processing happens on the received message.

Asynchronous communication refers to the kind of communication, where sender sends a copy of message to the receiver and proceeds without waiting for the processing at receiver to be completed.

In the following example, I will show you the behavior of direct end point and let you use the same example to test and understand the behavior of seda, direct-vm and vm end points. In case of any difficulty, you can download the complete project with the example of all of the end points from the following git hub location.-


Technology used -
java version "1.8.0_73"
Apache Camel 2.16.2
Apache Maven 3.0.4

pom.xml -
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>camel</groupId>
 <artifactId>CamelAwareEndPoints</artifactId>
 <packaging>jar</packaging>
 <version>1.0-SNAPSHOT</version>
 <dependencies>
  <dependency>
   <groupId>org.apache.camel</groupId>
   <artifactId>camel-core</artifactId>
   <version>2.16.2</version>
  </dependency>
  <dependency>
   <groupId>org.slf4j</groupId>
   <artifactId>slf4j-simple</artifactId>
   <version>1.6.4</version>
  </dependency>
 </dependencies>
</project>
Project Structure

DirectEndPointRouter.java-
package com.salil.camelawareendpoints.router;

import org.apache.camel.builder.RouteBuilder;

public class DirectEndPointRouter extends RouteBuilder  {

 public static final String DIRECT_END = "direct:End";
 public static final String DIRECT_START = "direct:start";

 @Override
 public void configure() throws Exception {
  from(DIRECT_START).routeId("StartRouteId")
  .setBody().simple("Start Message")
  .to(DIRECT_END)
  .log("Message at start route completion = ${body}");
  
  
  from(DIRECT_END).routeId("EndRouteId")
  .setBody().simple("End Message")
        .log("message after end-route completion = ${body}");
 }

}

DirectEndPointBehaviorExample.java-
package com.salil.camelawareendpoints.ContextExample;

import com.salil.camelawareendpoints.router.DirectEndPointRouter;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.impl.DefaultCamelContext;

/**
 * Created by Salil on 29-02-2016.
 */
public class DirectEndPointBehaviorExample {

    public static void main(String[] args) throws Exception {
        CamelContext camelContext = new DefaultCamelContext();
        camelContext.addRoutes(new DirectEndPointRouter());
        camelContext.start();

        ProducerTemplate producerTemplate=camelContext.createProducerTemplate();
        producerTemplate.sendBody(DirectEndPointRouter.DIRECT_START, "Initial Message");
    }
}

Execution output-
427 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.16.2 (CamelContext: camel-1) is starting
429 [main] INFO org.apache.camel.management.ManagedManagementStrategy - JMX is enabled
843 [main] INFO org.apache.camel.impl.converter.DefaultTypeConverter - Loaded 182 type converters
973 [main] INFO org.apache.camel.impl.DefaultRuntimeEndpointRegistry - Runtime endpoint registry is in extended mode gathering usage statistics of all incoming and outgoing endpoints (cache limit: 1000)
1280 [main] INFO org.apache.camel.impl.DefaultCamelContext - AllowUseOriginalMessage is enabled. If access to the original message is not needed, then its recommended to turn this option off as it may improve performance.
1280 [main] INFO org.apache.camel.impl.DefaultCamelContext - StreamCaching is not in use. If using streams then its recommended to enable stream caching. See more details at http://camel.apache.org/stream-caching.html
1441 [main] INFO org.apache.camel.impl.DefaultCamelContext - Route: StartRouteId started and consuming from: Endpoint[direct://start]
1451 [main] INFO org.apache.camel.impl.DefaultCamelContext - Route: EndRouteId started and consuming from: Endpoint[direct://End]
1451 [main] INFO org.apache.camel.impl.DefaultCamelContext - Total 2 routes, of which 2 is started.
1459 [main] INFO org.apache.camel.impl.DefaultCamelContext - Apache Camel 2.16.2 (CamelContext: camel-1) started in 1.031 seconds
1501 [main] INFO EndRouteId - message after end-route completion = End Message
1501 [main] INFO StartRouteId - Message at start route completion = End Message

In this case, we can notice following things
1- The output of end route got printed before the completion of start route
2- Both start route and end route had the same message in the body of the message at the time of printing
3- All the execution happens on the main thread only

This behavior appears because of synchronous nature of direct end point, where at the call of '.to(DIRECT_END)', the execution of first route stopped & it resumed again on receiving of the message with body 'End Message'

Let us know whether you could understand the behavior of seda, direct-vm and vm points, or faced any difficulty even after executing the examples at following git hub location

4 comments:

  1. using direct-vm getting class cast exception for cross camelcotext.

    I was trying like this.

    ----First camel context--





    exchange.getIn().setBody(new Employee());

    -----In second camelcontext------
    Employee emp=exchange.geIn().gettBody(Employee.class);

    using this approach facing issue of class cast exception.

    The same approach is working using direct component in the one same camelcontext.
    Can you please help me understand this.

    ReplyDelete
    Replies
    1. Make sure you build the whole app, also check whether the Employee class is the same one on both places.

      Delete
  2. For Direct-vm i am getting below output...I didn;t understand why message body not printed for first camel context
    781 [main] INFO EndRouteId - Message at 'end route' completion in second camel context = End Message
    781 [main] INFO StartRouteId - Message at 'start route' completion in first camel context =

    ReplyDelete