Book Image

Apache Camel Developer's Cookbook

Book Image

Apache Camel Developer's Cookbook

Overview of this book

Apache Camel is a de-facto standard for developing integrations in Java, and is based on well-understood Enterprise Integration Patterns. It is used within many commercial and open source integration products. Camel makes common integration tasks easy while still providing the developer with the means to customize the framework when the situation demands it. Tasks such as protocol mediation, message routing and transformation, and auditing are common usages of Camel. Apache Camel Developer's Cookbook provides hundreds of best practice tips for using Apache Camel in a format that helps you build your Camel projects. Each tip or recipe provides you with the most important steps to perform along with a summary of how it works, with references to further reading if you need more information. This book is intended to be a reliable information source that is quicker to use than an Internet search. Apache Camel Developer's Cookbook is a quick lookup guide that can also be read from cover to cover if you want to get a sense of the full power of Apache Camel. This book provides coverage of the full lifecycle of creating Apache Camel-based integration projects, including the structure of your Camel code and using the most common Enterprise Integration patterns. Patterns like Split/Join and Aggregation are covered in depth in this book. Throughout this book, you will be learning steps to transform your data. You will also learn how to perform unit and integration testing of your code using Camel's extensive testing framework, and also strategies for debugging and monitoring your code. Advanced topics like Error Handling, Parallel Processing, Transactions, and Security will also be covered in this book. This book provides you with practical tips on using Apache Camel based on years of hands-on experience from hundreds of integration projects.
Table of Contents (20 chapters)
Apache Camel Developer's Cookbook
Credits
About the Authors
Acknowledgments
About the Reviewers
www.PacktPub.com
Preface
Index

Spanning Camel contexts within a single Java process


Sometimes it is convenient to share routing logic between integrations hosted in the same container, for example, as web apps or OSGi bundles. Camel provides two components that allow you to do this, synchronously through a Direct VM Component, or asynchronously through a VM Component.

This recipe will show you how a Camel route can call another route running in a different Camel context.

Getting ready

In order for messages to be passed between routes using the vm: or direct-vm: transports, the exact same instance of the camel-core library must be available within the classloader hierarchy of both applications.

In an application server such as Apache Tomcat, this means placing the camel-core.jar file in the /ext directory of the server. Applications deployed onto the server should not contain camel-core within their WAR files.

When using an OSGi container such as Apache Karaf or Apache ServiceMix, it is simply a case of ensuring that the camel-core bundle is installed and running.

No additional work is necessary to use these transports if you intend to communicate between Camel contexts in the same application.

The Java code for this recipe is located in the org.camelcookbook.structuringroutes.vm package. The Spring XML files are located under src/main/resources/META-INF/spring and prefixed with vm.

How to do it...

Create a route to be shared consuming (from) with the vm: endpoint, and reference it from other routes using the same endpoint name.

  1. Split out the integration logic that you want to share into a route and select a VM Component to consume from that best suits your threading requirements. If your route should handle requests using the same thread as the caller, choose direct-vm:, otherwise if you want the exchange to be processed asynchronously by a different thread, choose vm:. Give the endpoint a name that will be unique across the JVM.

    In the XML DSL, this is written as follows:

    <route>
      <from uri="vm:logMessageToBackendSystem"/>
      <to uri="..."/>
    </route>

    In the Java DSL, you express the same thing as:

    from("vm:logMessageToBackendSystem").to(...);
  2. Invoke the shared route from within the top-level route that needs to make use of this logic by using the same URI prefix.

    In the XML DSL, write the following:

    <route>
      <from uri="..."/>
      <to uri="vm:logMessageToBackendSystem"/>
    </route>

    In the Java DSL, this is written as:

    from(...).to("vm:
    logMessageToBackendSystem");

How it works...

The VM Component is equivalent in functionality to SEDA, but works across applications within the same JVM. All of the same configuration options for a seda: endpoint also apply to the vm: endpoint. As in seda: endpoints, care should be taken that the endpoint name used in the top-level route matches that of the shared route. Otherwise, the exchange is placed onto a named in-memory queue that will never be consumed from.

Aside from working across applications, direct-vm: is functionally equivalent to direct:. The endpoint uses the same thread between the two applications, meaning that it can participate in the same transactions. This should be tested thoroughly to ensure that applications have been correctly configured. For this to work, both applications should make use of the same transactional resources (for example, JDBC DataSource or JMS ConnectionFactory) with the same transaction manager.

Note

When using direct-vm: you should pay particular attention to the order in which the applications or contexts are started up. You can use the block=true option on direct-vm: so that it will block until there is an active consumer associated with it. If the top-level route starts sending messages to the shared route before it is available, an exception similar to the following will be thrown by the Camel runtime:

org.apache.camel.CamelExchangeException : No consumers available on endpoint: Endpoint[direct-vm://someMissingEndpoint]