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

Using Camel in a Java application


Camel is a framework that is composed of a set of JARs, much as any other library that lives alongside your code. If you wanted to run Camel from the command line, you would define the libraries used within as a list of JARs to be considered by the java and javac command-line tools.

Note

The supporting code for this book uses Camel within the context of Maven projects that build standalone JARs. The JARs are not meant to be executed themselves, rather the Maven project structure is used as a convenient harness for driving JUnit tests that demonstrate the behavior being described.

The Camel libraries are broken up into two categories:

  • Core set of artifacts containing the runtime, test support classes, and build tools.

  • Optional libraries that abstract away the details of dealing with a given technology (for example, messaging via JMS or SOAP services via CXF). At the time of writing, Camel integrates with over 140 technologies (http://camel.apache.org/components.html), and each is encapsulated within its own library with its own dependencies.

This recipe will show you the basic steps to start and stop Camel routes from within your Java application.

Getting ready

The minimal set of libraries typically required to use Camel within a Maven build are:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-core</artifactId>
  <version>${camel-version}</version>
</dependency>
<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-test</artifactId>
  <version>${camel-version}</version>
  <scope>test</scope>
</dependency>

The Camel version is usually defined in a properties block within the Maven POM file once, as follows, so as to not need to be repeated over and over:

<properties>
  <camel-version>2.12.2</camel-version>
</properties>

Note

A note on versions

Camel is a very mature framework that can be considered as being "core-complete". It has become the core library for integration in a number of commercial ESBs, and at this stage the underlying architecture is very stable and unlikely to be radically changed.

This book has been written against what will most certainly be an outdated version by the time you read this. Any changes made to Camel since the time of writing are likely to have been additive. There will be more components, and more options around the various integration patterns as further use cases require them. For the very latest detailed documentation, refer to the Camel website.

The Java code for this recipe is located in the org.camelcookbook.structuringroutes.simple package.

How to do it...

  1. Define a route using the Camel Java DSL, by extending the org.apache.camel.builder.RouteBuilder abstract class:

    public class LogMessageOnTimerEventRouteBuilder
        extends RouteBuilder {
      @Override
      public void configure() throws Exception {
        from("timer:logMessageTimer?period=1s")
          .log("Event triggered by ${property.CamelTimerName}"
             + " at ${header.CamelTimerFiredTime}");
      }
    };
  2. The following steps occur in your application's main method. See SimpleCamelApplication from this example. Create a CamelContext implementation:

    CamelContext context = new DefaultCamelContext();
  3. Add the route definition to the context; this can be invoked as many times as you have routes:

    context.addRoutes(
        new LogMessageOnTimerEventRouteBuilder());
  4. Start the context. This loads the route definitions that you have added, and processes messages through them in the background:

    context.start();

    Note

    The CamelContext.start method is non-blocking. It will start up associated Components on internal threads, and return to the caller.

  5. When the Camel application is ready to be shut down, call:

    context.stop();

How it works...

The CamelContext interface is the heart of the Camel framework. It is responsible for processing messages along routes.

The from(...) statement at the start of a route defines an endpoint, or a technology-specific location, that the Camel routing engine uses to fetch messages. Endpoints are defined using URIs, such as in the preceding example, timer:logMessageTimer. The first part of the URI specifies the component that is being used to consume the message, and the remaining is a set of instructions for that specific component. See the Using Camel components recipe in this chapter for more details.

The Camel routing engine consumes exchanges from these endpoints and processes them sequentially through each of the steps defined in the route. The engine is responsible for threading, transactions, error handling, copying messages where required, and many other details.

The Camel context is a long-running object; it is intended to live for as long as the application does, and therefore its initialization and shutdown is usually tied to the lifecycle of the application. Typical deployments of Camel define the context within:

  • The main() method of a standalone command-line application; here it waits indefinitely until the user terminates the process

  • As an instance variable within a javax.servlet.ServletContextListener in a web app, starting up and shutting down along with the application

  • An object tied to an OSGi bundle's lifecycle

  • An object within a Spring or OSGi Blueprint context that is itself tied to the application's lifecycle

Routes, which are definitions of the steps that messages should be processed through, are typically added to the newly created context, though they can be added, removed, and modified at runtime. Route definitions can only be added to a context before the context is started, though they can be stopped and restarted while the context is running.

Extending the RouteBuilder abstract class gives access to Camel's Java route definition DSL, or simply the Java DSL. What this means in practice is that within the mandatory configure() method, after typing the first from(...) statement that defines the start of a route, you get context-specific code completion of whichever integration patterns you might be using.

A RouteBuilder implementation may implement one or many routes. That is, within the configure() method, you can specify multiple from(...) statement that Camel will translate into multiple runtime route instances, one per from(...) statement.

There's more...

Camel is a highly configurable framework, in which most behaviors can be customized through service provider interfaces (SPIs). An SPI encapsulates a single behavior, such as a route naming strategy (Camel gives your routes sensible names if you do not do so explicitly). To override the default behavior, you provide your own implementation of the SPI class and set it on the CamelContext object. The context allows you to define the following, amongst others:

  • Listeners that are notified of Camel lifecycle events

  • Naming strategies for routes, route nodes, and JMX

  • Strategies for shutting down the application gracefully

  • Mechanisms for managing thread pools

It is therefore worthwhile getting familiar with the options that this class gives you by going over the Javadocs.

The CamelContext interface makes use of an internal object registry that allows it to look up objects by name. When using a DefaultCamelContext, a JNDI-aware registry is used.

This feature is used extensively throughout the framework for finding components, thread pools, named processor beans, data formats, and the like.

Occasionally, it is necessary to add objects directly to the registry, as in the case of beans that you want to execute, as one of the processing steps in a route. To do this, instantiate an implementation of org.apache.camel.spi.Repository, usually org.apache.camel.impl.SimpleRegistry, and pass it into the constructor of the DefaultCamelContext:

SimpleRegistry registry = new SimpleRegistry();
registry.put("payloadTransformer", new MyPayloadTransformer());
CamelContext context = new DefaultCamelContext(registry);

The CamelContext interface defines type-safe utility methods for setting certain object types, such as components, that allow you to set them without worrying about the registry internals.

Consider the following manual step:

registry.put("mylogger", new LogComponent());

This can be written in a type-safe way as follows:

context.addComponent("mylogger", new LogComponent());

The Registry in Camel can hold any named Java instance, and these instances can be referenced by name from the Camel DSL. The addComponent method of the CamelContext is specifically used for registering Camel components by name. Both approaches do effectively the same thing, though there are some subtle differences, and we would recommend using the addComponent method for components, and adding all your POJOs and custom processors into the registry.