You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 12 Next »

Async

Available as of Camel 2.0

The asynchronous API in Camel have been rewritten for Camel 2.0, and the information on this page applies for Camel 2.0 and later.

A bit of background

The new Async API in Camel 2.0 leverages in much greater detail the Java Concurrency API and its support for executing tasks asynchronous.
Therefore the Camel Async API should be familiar for users with knowledge of the Java Concurrency API.

A few concepts to master

When doing messaging there are a few aspects to keep in mind.

First of all a caller can initiate a message exchange as either:

Request only is when the caller sends a message but do not expect any reply. This is also sometimes known as fire and forget or event message.

The Request Reply is then caller sends a message and then waits for a reply. This is like the Http protocol that we use every day when we surf the web.
We send a request to fetch a web page and wait until the reply message comes with the web content.

In Camel a message is labeled with a Message Exchange Pattern that labels whether its a request only or request reply message. Camel uses the JBI term for this an uses InOnly for the request only, and InOut for the request reply.

For both the request only and the request reply the routing in Camel can happen either:

  • synchronous
  • asynchronous

Synchronous Request Reply

A sync is defined as the caller thread and the remaining routing and processing of the message is happening in the same thread and as sync the caller waits until this thread has done its work before the invocation can return to the caller and continue its work. This is illustrated in the diagram below:

1. The client sends a sync Request Reply message over Http to Camel. The client application will wait for the response that Camel routes and processes.
2. The message invokes an external TCP service using synchronous Request Reply. The client application still waits for the response.
3. The response is send back to the client.

Asynchronous Request Reply

On the other hand the asynchronous version is where the caller thread initiates the request and leave the further processing of the message in another thread, the asynchronous thread, and then immediately returns to the caller. Then the caller can continue doing other work and at the same time the asynchronous thread is processing the message. If we are using [Request Reply then at a later point in time the original caller can get hold of the response from the asynchronous thread. If we are using request only then there are no response but the caller can still get a kind of response as it can get information whether the asynchronous thread is done or failed due to an exception. This is illustrated in the diagram below:

1. The client sends an Async Request Reply message over Http to Camel. The control is immediately returned to the client application, that can continue and do other work while Camel routes the message.
2. Camel invokes an external TCP service using synchronous Request Reply. The client application can do other work simultaneously.
3. The client wants to get the reply so it uses the Future handle it got as response from step 1. With this handle it retrieves the reply, wait if nessasary if the reply is not ready.

Synchronous Request Only

You can also do synchronous Request only with Camel. The client sends a message to Camel in which a reply is not expected. However the client still waits until the message is processed completely. This is illustrated in the diagram below:

1. The client sends a Request only and we can still use Http despite http being Request Reply by nature.
2. Camel invokes an external TCP service using synchronous Request Reply. The client application is still waiting.
3. The message is processed completely and the control is returned to the client.

So why do you want to use synchronous Request Only? Well if you want to know whether the message was processed successfully or not before continuing. With synchronous it allows you to wait while the message is being processed. In case the processing was succesful the control is returned to the client with no notion of error. In case of failure the client can detect this as an exception is thrown. (and exchange.isFailed() returns true).

Asynchronous Request Only

As opposed to the synchronous Request Only the Async counter part will not wait for the processing of the message to complete. In this case the client can immediately continue doing other work while the message is being routed and processed in Camel. This is illustrated in the diagram below:

TODO: diagram

1. The client sends a Request only and we can still use Http despite http being Request Reply by nature. The control is immediately returned to the client application, that can continue and do other work while Camel routes the message.
2. Camel invokes an external TCP service using synchronous Request Reply. The client application can do other work simultaneously.
3. The message completes but no result is returned to the client.

Notice: As Camel always returns a Future handle for Async messaging to the client. The client can then use this handler or not to get hold of the status of the processing whether the task is complete or an Exception occured during processing.

In case you want to know whether the Async Request Only failed, then you can use the Future handle and invoke get() and if it throws a ExecutionException then the processing failed. The caused exception is wrapped. You can invoke isDone() first to test whether the task is done or still in progress. Otherwise invoking get() will wait until the task is done.

With these diagrams in mind lets turn out attention to the Async API and how to use it with Camel.

The Async API

Camel provides the Async API in the Producer Template where we have added about 10 new methods to Camel 2.0. We have listed the most important in the table below:

Method

Description

setExecutorService

Is used to set the Java ExecutorService. Camel will by default provide a ScheduledExecutorService with 5 thread in the pool.

asyncSend

Is used to send an async exchange to a Camel Endpoint. Camel will imeddiately return control to the caller thread after the task has been submitted to the executor service. This allows you to do other work while Camel processes the exchange in the other async thread.

asyncSendBody

As above but for sending body only. This is a request only messaging style so no reply is expected. Uses the InOnly exchange pattern.

asyncRequestBody

As above but for sending body only. This is a Request Reply messaging style so a reply is expected. Uses the InOut exchange pattern.

extractFutureBody

Is used to get the result from the asynchronous thread using the Java Concurrency Future handle.

The asyncSend and asyncRequest methods return a Future handle. This handle is what the caller must use later to retrieve the asynchronous response. You can do this by using the extractFutureBody method, or just use plain Java but invoke get() on the Future handle.

The Future API

The java.util.concurrent.Future API have among others the following methods:

Method

Description

isDone

Returns a boolean whether the task is done or not. Will even return true if the tasks failed due to an exception thrown.

get()

Gets the response of the task. In case of an exception was thrown the java.util.concurrent.ExecutionException is thrown with the caused exception.

Example: Asynchronous Request Reply

Suppose we want to call a Http service but it is usually slow and thus we do not want to block and wait for the response, as we can do other important computation. So we can initiate an Async exchange to the Http endpoint and then do other stuff while the slow Http service is processing our request. And then a bit later we can use the Future handle to get the response from the Http service. Yeah nice so lets do it:

First we define some routes in Camel. One for the Http service where we simulate a slow server as it takes at least 1 second to reply. And then other route that we want to invoke while the Http service is on route. This allows you to be able to process the two routes simultaneously:

Error formatting macro: snippet: java.lang.NullPointerException

And then we have the client API where we call the two routes and we can get the responses from both of them. As the code is based on unit test there is a bit of mock in there as well:

Error formatting macro: snippet: java.lang.NullPointerException

All together it should give you the basic idea how to use this Async API and what it can do.

Example: Synchronous Request Reply

This example is just to a pure synchronous version of the example from above that was Async based.

The route is the same, so its just how the client initiate and send the messages that differs:

Error formatting macro: snippet: java.lang.NullPointerException

Using the Async DSL

TODO: About the async DSL.

Using the Async API with the Camel classic API

When using the Camel API to create a producer and send an Exchange we do it like this:

Endpoint endpoint = context.getEndpoint("http://slowserver.org/myservice");
Exchange exchange = endpoint.createExchange();
exchange.getIn().setBody("Order ABC");
// create a regular producer
Producer producer = endpoint.createProducer();
// send the exchange and wait for the reply as this is synchronous
producer.process(exchange);

But to do the same with Async we need a little help from a helper class, so the code is:

Endpoint endpoint = context.getEndpoint("http://slowserver.org/myservice");
Exchange exchange = endpoint.createExchange();
exchange.getIn().setBody("Order ABC");
// create a regular producer
Producer producer = endpoint.createProducer();
// normally you will use a shared exectutor service with pools
ExecutorService executor = Executors.newSingleThreadExecutor();
// send it async with the help of this helper
Future<Exchange> future = AsyncProcessorHelper.asyncProcess(executor, producer, exchange);
// here we got the future handle and we can do other stuff while the exchange is being routed in the other asynchronous thread
...
// and to get the response we use regular Java Concurrency API
Exchange response = future.get();
  • No labels