Run rst to md conversion
Based on the slightly modified rst source in the convertedReference branch As documented in https://docs.google.com/document/d/1dfN7ds-kKPKSokZZTbyXdNjMzZyUkwuOd8V5JXWd6wY/edit
This commit is contained in:
parent
2933c449b6
commit
8fbaa1054c
180 changed files with 19267 additions and 21243 deletions
|
|
@ -1,17 +1,12 @@
|
|||
# Camel
|
||||
|
||||
.. _camel-java:
|
||||
@@@ warning
|
||||
|
||||
Camel
|
||||
#####
|
||||
Akka Camel is deprecated in favour of [Alpakka](https://github.com/akka/alpakka) , the Akka Streams based collection of integrations to various endpoints (including Camel).
|
||||
|
||||
.. warning::
|
||||
Akka Camel is deprecated in favour of `Alpakka`_ , the Akka Streams based collection of integrations to various endpoints (including Camel).
|
||||
@@@
|
||||
|
||||
.. _Alpakka: https://github.com/akka/alpakka
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
## Introduction
|
||||
|
||||
The akka-camel module allows Untyped Actors to receive
|
||||
and send messages over a great variety of protocols and APIs.
|
||||
|
|
@ -19,59 +14,51 @@ In addition to the native Scala and Java actor API, actors can now exchange mess
|
|||
of protocols and APIs such as HTTP, SOAP, TCP, FTP, SMTP or JMS, to mention a
|
||||
few. At the moment, approximately 80 protocols and APIs are supported.
|
||||
|
||||
Apache Camel
|
||||
------------
|
||||
The akka-camel module is based on `Apache Camel`_, a powerful and light-weight
|
||||
### Apache Camel
|
||||
|
||||
The akka-camel module is based on [Apache Camel](http://camel.apache.org/), a powerful and light-weight
|
||||
integration framework for the JVM. For an introduction to Apache Camel you may
|
||||
want to read this `Apache Camel article`_. Camel comes with a
|
||||
large number of `components`_ that provide bindings to different protocols and
|
||||
APIs. The `camel-extra`_ project provides further components.
|
||||
want to read this [Apache Camel article](http://architects.dzone.com/articles/apache-camel-integration). Camel comes with a
|
||||
large number of [components](http://camel.apache.org/components.html) that provide bindings to different protocols and
|
||||
APIs. The [camel-extra](http://code.google.com/p/camel-extra/) project provides further components.
|
||||
|
||||
.. _Apache Camel: http://camel.apache.org/
|
||||
.. _Apache Camel article: http://architects.dzone.com/articles/apache-camel-integration
|
||||
.. _components: http://camel.apache.org/components.html
|
||||
.. _camel-extra: http://code.google.com/p/camel-extra/
|
||||
### Consumer
|
||||
|
||||
Consumer
|
||||
--------
|
||||
Here's an example of using Camel's integration components in Akka.
|
||||
|
||||
.. includecode:: code/jdocs/camel/MyEndpoint.java#Consumer-mina
|
||||
@@snip [MyEndpoint.java](code/jdocs/camel/MyEndpoint.java) { #Consumer-mina }
|
||||
|
||||
The above example exposes an actor over a TCP endpoint via Apache
|
||||
Camel's `Mina component`_. The actor implements the `getEndpointUri` method to define
|
||||
Camel's [Mina component](http://camel.apache.org/mina2.html). The actor implements the *getEndpointUri* method to define
|
||||
an endpoint from which it can receive messages. After starting the actor, TCP
|
||||
clients can immediately send messages to and receive responses from that
|
||||
actor. If the message exchange should go over HTTP (via Camel's `Jetty
|
||||
component`_), the actor's `getEndpointUri` method should return a different URI, for instance "jetty:http://localhost:8877/example".
|
||||
actor. If the message exchange should go over HTTP (via Camel's <!-- FIXME: duplicate target id: jetty component --> `Jetty
|
||||
component`_), the actor's *getEndpointUri* method should return a different URI, for instance "jetty:[http://localhost:8877/example](http://localhost:8877/example)".
|
||||
In the above case an extra constructor is added that can set the endpoint URI, which would result in
|
||||
the `getEndpointUri` returning the URI that was set using this constructor.
|
||||
the *getEndpointUri* returning the URI that was set using this constructor.
|
||||
|
||||
.. _Mina component: http://camel.apache.org/mina2.html
|
||||
.. _Jetty component: http://camel.apache.org/jetty.html
|
||||
### Producer
|
||||
|
||||
Producer
|
||||
--------
|
||||
Actors can also trigger message exchanges with external systems i.e. produce to
|
||||
Camel endpoints.
|
||||
|
||||
.. includecode:: code/jdocs/camel/Orders.java#Producer
|
||||
@@snip [Orders.java](code/jdocs/camel/Orders.java) { #Producer }
|
||||
|
||||
In the above example, any message sent to this actor will be sent to
|
||||
the JMS queue ``Orders``. Producer actors may choose from the same set of Camel
|
||||
the JMS queue `Orders`. Producer actors may choose from the same set of Camel
|
||||
components as Consumer actors do.
|
||||
Below an example of how to send a message to the Orders producer.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ProducerTestBase.java#TellProducer
|
||||
@@snip [ProducerTestBase.java](code/jdocs/camel/ProducerTestBase.java) { #TellProducer }
|
||||
|
||||
### CamelMessage
|
||||
|
||||
CamelMessage
|
||||
------------
|
||||
The number of Camel components is constantly increasing. The akka-camel module
|
||||
can support these in a plug-and-play manner. Just add them to your application's
|
||||
classpath, define a component-specific endpoint URI and use it to exchange
|
||||
messages over the component-specific protocols or APIs. This is possible because
|
||||
Camel components bind protocol-specific message formats to a Camel-specific
|
||||
`normalized message format`__. The normalized message format hides
|
||||
[normalized message format](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Message.java). The normalized message format hides
|
||||
protocol-specific details from Akka and makes it therefore very easy to support
|
||||
a large number of protocols through a uniform Camel component interface. The
|
||||
akka-camel module further converts mutable Camel messages into immutable
|
||||
|
|
@ -80,103 +67,79 @@ matching, transformation, serialization or storage. In the above example of the
|
|||
the XML message is put in the body of a newly created Camel Message with an empty set of headers.
|
||||
You can also create a CamelMessage yourself with the appropriate body and headers as you see fit.
|
||||
|
||||
__ https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Message.java
|
||||
### CamelExtension
|
||||
|
||||
CamelExtension
|
||||
--------------
|
||||
The akka-camel module is implemented as an Akka Extension, the ``CamelExtension`` object.
|
||||
Extensions will only be loaded once per ``ActorSystem``, which will be managed by Akka.
|
||||
The ``CamelExtension`` object provides access to the `Camel`_ interface.
|
||||
The `Camel`_ interface in turn provides access to two important Apache Camel objects, the `CamelContext`_ and the `ProducerTemplate`_.
|
||||
The akka-camel module is implemented as an Akka Extension, the `CamelExtension` object.
|
||||
Extensions will only be loaded once per `ActorSystem`, which will be managed by Akka.
|
||||
The `CamelExtension` object provides access to the [Camel](@github@/akka-camel/src/main/scala/akka/camel/Camel.scala) interface.
|
||||
The [Camel](@github@/akka-camel/src/main/scala/akka/camel/Camel.scala) interface in turn provides access to two important Apache Camel objects, the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) and the <!-- FIXME: duplicate target id: producertemplate --> `ProducerTemplate`_.
|
||||
Below you can see how you can get access to these Apache Camel objects.
|
||||
|
||||
.. includecode:: code/jdocs/camel/CamelExtensionTest.java#CamelExtension
|
||||
@@snip [CamelExtensionTest.java](code/jdocs/camel/CamelExtensionTest.java) { #CamelExtension }
|
||||
|
||||
One ``CamelExtension`` is only loaded once for every one ``ActorSystem``, which makes it safe to call the ``CamelExtension`` at any point in your code to get to the
|
||||
Apache Camel objects associated with it. There is one `CamelContext`_ and one `ProducerTemplate`_ for every one ``ActorSystem`` that uses a ``CamelExtension``.
|
||||
By Default, a new `CamelContext`_ is created when the ``CamelExtension`` starts. If you want to inject your own context instead,
|
||||
you can implement the `ContextProvider`_ interface and add the FQCN of your implementation in the config, as the value of the "akka.camel.context-provider".
|
||||
This interface define a single method ``getContext()`` used to load the `CamelContext`_.
|
||||
One `CamelExtension` is only loaded once for every one `ActorSystem`, which makes it safe to call the `CamelExtension` at any point in your code to get to the
|
||||
Apache Camel objects associated with it. There is one [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) and one <!-- FIXME: duplicate target id: producertemplate --> `ProducerTemplate`_ for every one `ActorSystem` that uses a `CamelExtension`.
|
||||
By Default, a new [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) is created when the `CamelExtension` starts. If you want to inject your own context instead,
|
||||
you can implement the [ContextProvider](@github@/akka-camel/src/main/scala/akka/camel/ContextProvider.scala) interface and add the FQCN of your implementation in the config, as the value of the "akka.camel.context-provider".
|
||||
This interface define a single method `getContext()` used to load the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java).
|
||||
|
||||
.. _ContextProvider: @github@/akka-camel/src/main/scala/akka/camel/ContextProvider.scala
|
||||
Below an example on how to add the ActiveMQ component to the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java), which is required when you would like to use the ActiveMQ component.
|
||||
|
||||
Below an example on how to add the ActiveMQ component to the `CamelContext`_, which is required when you would like to use the ActiveMQ component.
|
||||
@@snip [CamelExtensionTest.java](code/jdocs/camel/CamelExtensionTest.java) { #CamelExtensionAddComponent }
|
||||
|
||||
.. includecode:: code/jdocs/camel/CamelExtensionTest.java#CamelExtensionAddComponent
|
||||
The [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) joins the lifecycle of the `ActorSystem` and `CamelExtension` it is associated with; the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) is started when
|
||||
the `CamelExtension` is created, and it is shut down when the associated `ActorSystem` is shut down. The same is true for the <!-- FIXME: unresolved link reference: producertemplate --> `ProducerTemplate`_.
|
||||
|
||||
The `CamelContext`_ joins the lifecycle of the ``ActorSystem`` and ``CamelExtension`` it is associated with; the `CamelContext`_ is started when
|
||||
the ``CamelExtension`` is created, and it is shut down when the associated ``ActorSystem`` is shut down. The same is true for the `ProducerTemplate`_.
|
||||
|
||||
The ``CamelExtension`` is used by both `Producer` and `Consumer` actors to interact with Apache Camel internally.
|
||||
You can access the ``CamelExtension`` inside a `Producer` or a `Consumer` using the ``camel`` method, or get straight at the `CamelContext`
|
||||
using the ``getCamelContext`` method or to the `ProducerTemplate` using the `getProducerTemplate` method.
|
||||
Actors are created and started asynchronously. When a `Consumer` actor is created, the `Consumer` is published at its Camel endpoint
|
||||
(more precisely, the route is added to the `CamelContext`_ from the `Endpoint`_ to the actor).
|
||||
When a `Producer` actor is created, a `SendProcessor`_ and `Endpoint`_ are created so that the Producer can send messages to it.
|
||||
The `CamelExtension` is used by both *Producer* and *Consumer* actors to interact with Apache Camel internally.
|
||||
You can access the `CamelExtension` inside a *Producer* or a *Consumer* using the `camel` method, or get straight at the *CamelContext*
|
||||
using the `getCamelContext` method or to the *ProducerTemplate* using the *getProducerTemplate* method.
|
||||
Actors are created and started asynchronously. When a *Consumer* actor is created, the *Consumer* is published at its Camel endpoint
|
||||
(more precisely, the route is added to the [CamelContext](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java) from the [Endpoint](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Endpoint.java) to the actor).
|
||||
When a *Producer* actor is created, a [SendProcessor](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java) and [Endpoint](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Endpoint.java) are created so that the Producer can send messages to it.
|
||||
Publication is done asynchronously; setting up an endpoint may still be in progress after you have
|
||||
requested the actor to be created. Some Camel components can take a while to startup, and in some cases you might want to know when the endpoints are activated and ready to be used.
|
||||
The `Camel`_ interface allows you to find out when the endpoint is activated or deactivated.
|
||||
The [Camel](@github@/akka-camel/src/main/scala/akka/camel/Camel.scala) interface allows you to find out when the endpoint is activated or deactivated.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ActivationTestBase.java#CamelActivation
|
||||
@@snip [ActivationTestBase.java](code/jdocs/camel/ActivationTestBase.java) { #CamelActivation }
|
||||
|
||||
The above code shows that you can get a ``Future`` to the activation of the route from the endpoint to the actor, or you can wait in a blocking fashion on the activation of the route.
|
||||
An ``ActivationTimeoutException`` is thrown if the endpoint could not be activated within the specified timeout. Deactivation works in a similar fashion:
|
||||
The above code shows that you can get a `Future` to the activation of the route from the endpoint to the actor, or you can wait in a blocking fashion on the activation of the route.
|
||||
An `ActivationTimeoutException` is thrown if the endpoint could not be activated within the specified timeout. Deactivation works in a similar fashion:
|
||||
|
||||
.. includecode:: code/jdocs/camel/ActivationTestBase.java#CamelDeactivation
|
||||
@@snip [ActivationTestBase.java](code/jdocs/camel/ActivationTestBase.java) { #CamelDeactivation }
|
||||
|
||||
Deactivation of a Consumer or a Producer actor happens when the actor is terminated. For a Consumer, the route to the actor is stopped. For a Producer, the `SendProcessor`_ is stopped.
|
||||
A ``DeActivationTimeoutException`` is thrown if the associated camel objects could not be deactivated within the specified timeout.
|
||||
Deactivation of a Consumer or a Producer actor happens when the actor is terminated. For a Consumer, the route to the actor is stopped. For a Producer, the [SendProcessor](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java) is stopped.
|
||||
A `DeActivationTimeoutException` is thrown if the associated camel objects could not be deactivated within the specified timeout.
|
||||
|
||||
.. _Camel: @github@/akka-camel/src/main/scala/akka/camel/Camel.scala
|
||||
.. _CamelContext: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/CamelContext.java
|
||||
.. _ProducerTemplate: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/ProducerTemplate.java
|
||||
.. _SendProcessor: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/processor/SendProcessor.java
|
||||
.. _Endpoint: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Endpoint.java
|
||||
## Consumer Actors
|
||||
|
||||
Consumer Actors
|
||||
================
|
||||
|
||||
For objects to receive messages, they must inherit from the `UntypedConsumerActor`_
|
||||
For objects to receive messages, they must inherit from the [UntypedConsumerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala)
|
||||
class. For example, the following actor class (Consumer1) implements the
|
||||
`getEndpointUri` method, which is declared in the `UntypedConsumerActor`_ class, in order to receive
|
||||
messages from the ``file:data/input/actor`` Camel endpoint.
|
||||
*getEndpointUri* method, which is declared in the [UntypedConsumerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala) class, in order to receive
|
||||
messages from the `file:data/input/actor` Camel endpoint.
|
||||
|
||||
.. _UntypedConsumerActor: @github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedConsumer.scala
|
||||
|
||||
.. includecode:: code/jdocs/camel/Consumer1.java#Consumer1
|
||||
@@snip [Consumer1.java](code/jdocs/camel/Consumer1.java) { #Consumer1 }
|
||||
|
||||
Whenever a file is put into the data/input/actor directory, its content is
|
||||
picked up by the Camel `file component`_ and sent as message to the
|
||||
picked up by the Camel [file component](http://camel.apache.org/file2.html) and sent as message to the
|
||||
actor. Messages consumed by actors from Camel endpoints are of type
|
||||
`CamelMessage`_. These are immutable representations of Camel messages.
|
||||
|
||||
.. _file component: http://camel.apache.org/file2.html
|
||||
.. _Message: @github@/akka-camel/src/main/scala/akka/camel/CamelMessage.scala
|
||||
|
||||
[CamelMessage](#camelmessage). These are immutable representations of Camel messages.
|
||||
|
||||
Here's another example that sets the endpointUri to
|
||||
``jetty:http://localhost:8877/camel/default``. It causes Camel's `Jetty
|
||||
component`_ to start an embedded `Jetty`_ server, accepting HTTP connections
|
||||
`jetty:http://localhost:8877/camel/default`. It causes Camel's <!-- FIXME: duplicate target id: jetty component --> `Jetty
|
||||
component`_ to start an embedded [Jetty](http://www.eclipse.org/jetty/) server, accepting HTTP connections
|
||||
from localhost on port 8877.
|
||||
|
||||
.. _Jetty component: http://camel.apache.org/jetty.html
|
||||
.. _Jetty: http://www.eclipse.org/jetty/
|
||||
|
||||
.. includecode:: code/jdocs/camel/Consumer2.java#Consumer2
|
||||
@@snip [Consumer2.java](code/jdocs/camel/Consumer2.java) { #Consumer2 }
|
||||
|
||||
After starting the actor, clients can send messages to that actor by POSTing to
|
||||
``http://localhost:8877/camel/default``. The actor sends a response by using the
|
||||
``getSender().tell`` method. For returning a message body and headers to the HTTP
|
||||
client the response type should be `CamelMessage`_. For any other response type, a
|
||||
`http://localhost:8877/camel/default`. The actor sends a response by using the
|
||||
`getSender().tell` method. For returning a message body and headers to the HTTP
|
||||
client the response type should be [CamelMessage](#camelmessage). For any other response type, a
|
||||
new CamelMessage object is created by akka-camel with the actor response as message
|
||||
body.
|
||||
|
||||
.. _Message: @github@/akka-camel/src/main/scala/akka/camel/CamelMessage.scala
|
||||
|
||||
.. _camel-acknowledgements-java:
|
||||
|
||||
Delivery acknowledgements
|
||||
-------------------------
|
||||
<a id="camel-acknowledgements-java"></a>
|
||||
### Delivery acknowledgements
|
||||
|
||||
With in-out message exchanges, clients usually know that a message exchange is
|
||||
done when they receive a reply from a consumer actor. The reply message can be a
|
||||
|
|
@ -188,163 +151,144 @@ is added to the consumer actor's mailbox. Any failure or exception that occurs
|
|||
during processing of that message by the consumer actor cannot be reported back
|
||||
to the endpoint in this case. To allow consumer actors to positively or
|
||||
negatively acknowledge the receipt of a message from an in-only message
|
||||
exchange, they need to override the ``autoAck`` method to return false.
|
||||
exchange, they need to override the `autoAck` method to return false.
|
||||
In this case, consumer actors must reply either with a
|
||||
special akka.camel.Ack message (positive acknowledgement) or a akka.actor.Status.Failure (negative
|
||||
acknowledgement).
|
||||
|
||||
.. includecode:: code/jdocs/camel/Consumer3.java#Consumer3
|
||||
@@snip [Consumer3.java](code/jdocs/camel/Consumer3.java) { #Consumer3 }
|
||||
|
||||
.. _camel-timeout-java:
|
||||
|
||||
Consumer timeout
|
||||
----------------
|
||||
<a id="camel-timeout-java"></a>
|
||||
### Consumer timeout
|
||||
|
||||
Camel Exchanges (and their corresponding endpoints) that support two-way communications need to wait for a response from
|
||||
an actor before returning it to the initiating client.
|
||||
For some endpoint types, timeout values can be defined in an endpoint-specific
|
||||
way which is described in the documentation of the individual `Camel
|
||||
way which is described in the documentation of the individual <!-- FIXME: duplicate target id: camel components --> `Camel
|
||||
components`_. Another option is to configure timeouts on the level of consumer actors.
|
||||
|
||||
.. _Camel components: http://camel.apache.org/components.html
|
||||
|
||||
Two-way communications between a Camel endpoint and an actor are
|
||||
initiated by sending the request message to the actor with the `ask`_ pattern
|
||||
initiated by sending the request message to the actor with the [ask](@github@/akka-actor/src/main/scala/akka/pattern/Patterns.scala) pattern
|
||||
and the actor replies to the endpoint when the response is ready. The ask request to the actor can timeout, which will
|
||||
result in the `Exchange`_ failing with a TimeoutException set on the failure of the `Exchange`_.
|
||||
The timeout on the consumer actor can be overridden with the ``replyTimeout``, as shown below.
|
||||
result in the [Exchange](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Exchange.java) failing with a TimeoutException set on the failure of the [Exchange](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Exchange.java).
|
||||
The timeout on the consumer actor can be overridden with the `replyTimeout`, as shown below.
|
||||
|
||||
.. includecode:: code/jdocs/camel/Consumer4.java#Consumer4
|
||||
.. _Exchange: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/Exchange.java
|
||||
.. _ask: @github@/akka-actor/src/main/scala/akka/pattern/Patterns.scala
|
||||
@@snip [Consumer4.java](code/jdocs/camel/Consumer4.java) { #Consumer4 }
|
||||
|
||||
Producer Actors
|
||||
===============
|
||||
## Producer Actors
|
||||
|
||||
For sending messages to Camel endpoints, actors need to inherit from the `UntypedProducerActor`_ class and implement the getEndpointUri method.
|
||||
For sending messages to Camel endpoints, actors need to inherit from the [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) class and implement the getEndpointUri method.
|
||||
|
||||
.. includecode:: code/jdocs/camel/Producer1.java#Producer1
|
||||
@@snip [Producer1.java](code/jdocs/camel/Producer1.java) { #Producer1 }
|
||||
|
||||
Producer1 inherits a default implementation of the onReceive method from the
|
||||
`UntypedProducerActor`_ class. To customize a producer actor's default behavior you must override the `UntypedProducerActor`_.onTransformResponse and
|
||||
`UntypedProducerActor`_.onTransformOutgoingMessage methods. This is explained later in more detail.
|
||||
Producer Actors cannot override the `UntypedProducerActor`_.onReceive method.
|
||||
[UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) class. To customize a producer actor's default behavior you must override the [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformResponse and
|
||||
[UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformOutgoingMessage methods. This is explained later in more detail.
|
||||
Producer Actors cannot override the [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onReceive method.
|
||||
|
||||
Any message sent to a Producer actor will be sent to
|
||||
the associated Camel endpoint, in the above example to
|
||||
``http://localhost:8080/news``. The `UntypedProducerActor`_ always sends messages asynchronously. Response messages (if supported by the
|
||||
`http://localhost:8080/news`. The [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) always sends messages asynchronously. Response messages (if supported by the
|
||||
configured endpoint) will, by default, be returned to the original sender. The
|
||||
following example uses the ask pattern to send a message to a
|
||||
Producer actor and waits for a response.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ProducerTestBase.java#AskProducer
|
||||
@@snip [ProducerTestBase.java](code/jdocs/camel/ProducerTestBase.java) { #AskProducer }
|
||||
|
||||
The future contains the response CamelMessage, or an ``AkkaCamelException`` when an error occurred, which contains the headers of the response.
|
||||
The future contains the response CamelMessage, or an `AkkaCamelException` when an error occurred, which contains the headers of the response.
|
||||
|
||||
.. _camel-custom-processing-java:
|
||||
|
||||
Custom Processing
|
||||
-----------------
|
||||
<a id="camel-custom-processing-java"></a>
|
||||
### Custom Processing
|
||||
|
||||
Instead of replying to the initial sender, producer actors can implement custom
|
||||
response processing by overriding the onRouteResponse method. In the following example, the response
|
||||
message is forwarded to a target actor instead of being replied to the original
|
||||
sender.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ResponseReceiver.java#RouteResponse
|
||||
.. includecode:: code/jdocs/camel/Forwarder.java#RouteResponse
|
||||
.. includecode:: code/jdocs/camel/OnRouteResponseTestBase.java#RouteResponse
|
||||
@@snip [ResponseReceiver.java](code/jdocs/camel/ResponseReceiver.java) { #RouteResponse }
|
||||
|
||||
@@snip [Forwarder.java](code/jdocs/camel/Forwarder.java) { #RouteResponse }
|
||||
|
||||
@@snip [OnRouteResponseTestBase.java](code/jdocs/camel/OnRouteResponseTestBase.java) { #RouteResponse }
|
||||
|
||||
Before producing messages to endpoints, producer actors can pre-process them by
|
||||
overriding the `UntypedProducerActor`_.onTransformOutgoingMessage method.
|
||||
overriding the [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala).onTransformOutgoingMessage method.
|
||||
|
||||
.. includecode:: code/jdocs/camel/Transformer.java#TransformOutgoingMessage
|
||||
@@snip [Transformer.java](code/jdocs/camel/Transformer.java) { #TransformOutgoingMessage }
|
||||
|
||||
Producer configuration options
|
||||
------------------------------
|
||||
### Producer configuration options
|
||||
|
||||
The interaction of producer actors with Camel endpoints can be configured to be
|
||||
one-way or two-way (by initiating in-only or in-out message exchanges,
|
||||
respectively). By default, the producer initiates an in-out message exchange
|
||||
with the endpoint. For initiating an in-only exchange, producer actors have to override the isOneway method to return true.
|
||||
|
||||
.. includecode:: code/jdocs/camel/OnewaySender.java#Oneway
|
||||
@@snip [OnewaySender.java](code/jdocs/camel/OnewaySender.java) { #Oneway }
|
||||
|
||||
Message correlation
|
||||
-------------------
|
||||
### Message correlation
|
||||
|
||||
To correlate request with response messages, applications can set the
|
||||
`Message.MessageExchangeId` message header.
|
||||
*Message.MessageExchangeId* message header.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ProducerTestBase.java#Correlate
|
||||
@@snip [ProducerTestBase.java](code/jdocs/camel/ProducerTestBase.java) { #Correlate }
|
||||
|
||||
ProducerTemplate
|
||||
----------------
|
||||
### ProducerTemplate
|
||||
|
||||
The `UntypedProducerActor`_ class is a very convenient way for actors to produce messages to Camel endpoints.
|
||||
Actors may also use a Camel `ProducerTemplate`_ for producing messages to endpoints.
|
||||
The [UntypedProducerActor](@github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala) class is a very convenient way for actors to produce messages to Camel endpoints.
|
||||
Actors may also use a Camel <!-- FIXME: unresolved link reference: producertemplate --> `ProducerTemplate`_ for producing messages to endpoints.
|
||||
|
||||
.. includecode:: code/jdocs/camel/MyActor.java#ProducerTemplate
|
||||
@@snip [MyActor.java](code/jdocs/camel/MyActor.java) { #ProducerTemplate }
|
||||
|
||||
For initiating a two-way message exchange, one of the
|
||||
``ProducerTemplate.request*`` methods must be used.
|
||||
`ProducerTemplate.request*` methods must be used.
|
||||
|
||||
.. includecode:: code/jdocs/camel/RequestBodyActor.java#RequestProducerTemplate
|
||||
@@snip [RequestBodyActor.java](code/jdocs/camel/RequestBodyActor.java) { #RequestProducerTemplate }
|
||||
|
||||
.. _UntypedProducerActor: @github@/akka-camel/src/main/scala/akka/camel/javaapi/UntypedProducerActor.scala
|
||||
.. _ProducerTemplate: https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/ProducerTemplate.java
|
||||
|
||||
.. _camel-asynchronous-routing-java:
|
||||
|
||||
Asynchronous routing
|
||||
====================
|
||||
<a id="camel-asynchronous-routing-java"></a>
|
||||
## Asynchronous routing
|
||||
|
||||
In-out message exchanges between endpoints and actors are
|
||||
designed to be asynchronous. This is the case for both, consumer and producer
|
||||
actors.
|
||||
|
||||
* A consumer endpoint sends request messages to its consumer actor using the ``tell``
|
||||
method and the actor returns responses with ``getSender().tell`` once they are
|
||||
ready.
|
||||
|
||||
* A producer actor sends request messages to its endpoint using Camel's
|
||||
asynchronous routing engine. Asynchronous responses are wrapped and added to the
|
||||
producer actor's mailbox for later processing. By default, response messages are
|
||||
returned to the initial sender but this can be overridden by Producer
|
||||
implementations (see also description of the ``onRouteResponse`` method
|
||||
in :ref:`camel-custom-processing-java`).
|
||||
* A consumer endpoint sends request messages to its consumer actor using the `tell`
|
||||
method and the actor returns responses with `getSender().tell` once they are
|
||||
ready.
|
||||
* A producer actor sends request messages to its endpoint using Camel's
|
||||
asynchronous routing engine. Asynchronous responses are wrapped and added to the
|
||||
producer actor's mailbox for later processing. By default, response messages are
|
||||
returned to the initial sender but this can be overridden by Producer
|
||||
implementations (see also description of the `onRouteResponse` method
|
||||
in [Custom Processing](#camel-custom-processing-java)).
|
||||
|
||||
However, asynchronous two-way message exchanges, without allocating a thread for
|
||||
the full duration of exchange, cannot be generically supported by Camel's
|
||||
asynchronous routing engine alone. This must be supported by the individual
|
||||
`Camel components`_ (from which endpoints are created) as well. They must be
|
||||
<!-- FIXME: duplicate target id: camel components --> `Camel components`_ (from which endpoints are created) as well. They must be
|
||||
able to suspend any work started for request processing (thereby freeing threads
|
||||
to do other work) and resume processing when the response is ready. This is
|
||||
currently the case for a `subset of components`_ such as the `Jetty component`_.
|
||||
currently the case for a [subset of components](http://camel.apache.org/asynchronous-routing-engine.html) such as the <!-- FIXME: duplicate target id: jetty component --> `Jetty component`_.
|
||||
All other Camel components can still be used, of course, but they will cause
|
||||
allocation of a thread for the duration of an in-out message exchange. There's
|
||||
also :ref:`camel-examples-java` that implements both, an asynchronous
|
||||
also [Examples](#camel-examples-java) that implements both, an asynchronous
|
||||
consumer and an asynchronous producer, with the jetty component.
|
||||
|
||||
If the used Camel component is blocking it might be necessary to use a separate
|
||||
:ref:`dispatcher <dispatchers-java>` for the producer. The Camel processor is
|
||||
@ref:[dispatcher](dispatchers.md) for the producer. The Camel processor is
|
||||
invoked by a child actor of the producer and the dispatcher can be defined in
|
||||
the deployment section of the configuration. For example, if your producer actor
|
||||
has path ``/user/integration/output`` the dispatcher of the child actor can be
|
||||
defined with::
|
||||
has path `/user/integration/output` the dispatcher of the child actor can be
|
||||
defined with:
|
||||
|
||||
akka.actor.deployment {
|
||||
/integration/output/* {
|
||||
dispatcher = my-dispatcher
|
||||
}
|
||||
```
|
||||
akka.actor.deployment {
|
||||
/integration/output/* {
|
||||
dispatcher = my-dispatcher
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
.. _Camel components: http://camel.apache.org/components.html
|
||||
.. _subset of components: http://camel.apache.org/asynchronous-routing-engine.html
|
||||
.. _Jetty component: http://camel.apache.org/jetty.html
|
||||
|
||||
Custom Camel routes
|
||||
===================
|
||||
## Custom Camel routes
|
||||
|
||||
In all the examples so far, routes to consumer actors have been automatically
|
||||
constructed by akka-camel, when the actor was started. Although the default
|
||||
|
|
@ -353,107 +297,87 @@ most use cases, some applications may require more specialized routes to actors.
|
|||
The akka-camel module provides two mechanisms for customizing routes to actors,
|
||||
which will be explained in this section. These are:
|
||||
|
||||
* Usage of :ref:`camel-components-java` to access actors.
|
||||
Any Camel route can use these components to access Akka actors.
|
||||
* Usage of [Akka Camel components](#camel-components-java) to access actors.
|
||||
Any Camel route can use these components to access Akka actors.
|
||||
* [Intercepting route construction](#camel-intercepting-route-construction-java) to actors.
|
||||
This option gives you the ability to change routes that have already been added to Camel.
|
||||
Consumer actors have a hook into the route definition process which can be used to change the route.
|
||||
|
||||
* :ref:`camel-intercepting-route-construction-java` to actors.
|
||||
This option gives you the ability to change routes that have already been added to Camel.
|
||||
Consumer actors have a hook into the route definition process which can be used to change the route.
|
||||
<a id="camel-components-java"></a>
|
||||
### Akka Camel components
|
||||
|
||||
|
||||
.. _camel-components-java:
|
||||
|
||||
Akka Camel components
|
||||
---------------------
|
||||
|
||||
Akka actors can be accessed from Camel routes using the `actor`_ Camel component. This component can be used to
|
||||
Akka actors can be accessed from Camel routes using the <!-- FIXME: duplicate target id: actor --> `actor`_ Camel component. This component can be used to
|
||||
access any Akka actor (not only consumer actors) from Camel routes, as described in the following sections.
|
||||
|
||||
.. _actor: @github@/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala
|
||||
<a id="access-to-actors-java"></a>
|
||||
### Access to actors
|
||||
|
||||
.. _access-to-actors-java:
|
||||
|
||||
Access to actors
|
||||
----------------
|
||||
|
||||
To access actors from custom Camel routes, the `actor`_ Camel
|
||||
component should be used. It fully supports Camel's `asynchronous routing
|
||||
engine`_.
|
||||
|
||||
.. _actor: @github@/akka-camel/src/main/scala/akka/camel/internal/component/ActorComponent.scala
|
||||
.. _asynchronous routing engine: http://camel.apache.org/asynchronous-routing-engine.html
|
||||
To access actors from custom Camel routes, the <!-- FIXME: duplicate target id: actor --> `actor`_ Camel
|
||||
component should be used. It fully supports Camel's [asynchronous routing
|
||||
engine](http://camel.apache.org/asynchronous-routing-engine.html).
|
||||
|
||||
This component accepts the following endpoint URI format:
|
||||
|
||||
* ``[<actor-path>]?<options>``
|
||||
* `[<actor-path>]?<options>`
|
||||
|
||||
where ``<actor-path>`` is the ``ActorPath`` to the actor. The ``<options>`` are
|
||||
name-value pairs separated by ``&`` (i.e. ``name1=value1&name2=value2&...``).
|
||||
where `<actor-path>` is the `ActorPath` to the actor. The `<options>` are
|
||||
name-value pairs separated by `&` (i.e. `name1=value1&name2=value2&...`).
|
||||
|
||||
|
||||
URI options
|
||||
^^^^^^^^^^^
|
||||
#### URI options
|
||||
|
||||
The following URI options are supported:
|
||||
|
||||
.. tabularcolumns:: |l|l|l|L|
|
||||
|Name | Type | Default | Description |
|
||||
|-------------|----------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
|replyTimeout | Duration | false |
|
||||
The reply timeout, specified in the same
|
||||
way that you use the duration in akka,
|
||||
for instance `10 seconds` except that
|
||||
in the url it is handy to use a +
|
||||
between the amount and the unit, like
|
||||
for example `200+millis`
|
||||
See also [Consumer timeout](#camel-timeout-java).|
|
||||
|autoAck | Boolean | true |
|
||||
If set to true, in-only message exchanges
|
||||
are auto-acknowledged when the message is
|
||||
added to the actor's mailbox. If set to
|
||||
false, actors must acknowledge the
|
||||
receipt of the message.
|
||||
See also [Delivery acknowledgements](#camel-acknowledgements-java). |
|
||||
|
||||
+--------------+----------+---------+------------------------------------------------+
|
||||
| Name | Type | Default | Description |
|
||||
+==============+==========+=========+================================================+
|
||||
| replyTimeout | Duration | false | The reply timeout, specified in the same |
|
||||
| | | | way that you use the duration in akka, |
|
||||
| | | | for instance ``10 seconds`` except that |
|
||||
| | | | in the url it is handy to use a + |
|
||||
| | | | between the amount and the unit, like |
|
||||
| | | | for example ``200+millis`` |
|
||||
| | | | |
|
||||
| | | | See also :ref:`camel-timeout-java`. |
|
||||
+--------------+----------+---------+------------------------------------------------+
|
||||
| autoAck | Boolean | true | If set to true, in-only message exchanges |
|
||||
| | | | are auto-acknowledged when the message is |
|
||||
| | | | added to the actor's mailbox. If set to |
|
||||
| | | | false, actors must acknowledge the |
|
||||
| | | | receipt of the message. |
|
||||
| | | | |
|
||||
| | | | See also :ref:`camel-acknowledgements-java`. |
|
||||
+--------------+----------+---------+------------------------------------------------+
|
||||
Here's an actor endpoint URI example containing an actor path:
|
||||
|
||||
Here's an actor endpoint URI example containing an actor path::
|
||||
|
||||
akka://some-system/user/myconsumer?autoAck=false&replyTimeout=100+millis
|
||||
```
|
||||
akka://some-system/user/myconsumer?autoAck=false&replyTimeout=100+millis
|
||||
```
|
||||
|
||||
In the following example, a custom route to an actor is created, using the
|
||||
actor's path.
|
||||
|
||||
.. includecode:: code/jdocs/camel/Responder.java#CustomRoute
|
||||
.. includecode:: code/jdocs/camel/CustomRouteBuilder.java#CustomRoute
|
||||
.. includecode:: code/jdocs/camel/CustomRouteTestBase.java#CustomRoute
|
||||
@@snip [Responder.java](code/jdocs/camel/Responder.java) { #CustomRoute }
|
||||
|
||||
The `CamelPath.toCamelUri` converts the `ActorRef` to the Camel actor component URI format which points to the actor endpoint as described above.
|
||||
@@snip [CustomRouteBuilder.java](code/jdocs/camel/CustomRouteBuilder.java) { #CustomRoute }
|
||||
|
||||
@@snip [CustomRouteTestBase.java](code/jdocs/camel/CustomRouteTestBase.java) { #CustomRoute }
|
||||
|
||||
The *CamelPath.toCamelUri* converts the *ActorRef* to the Camel actor component URI format which points to the actor endpoint as described above.
|
||||
When a message is received on the jetty endpoint, it is routed to the Responder actor, which in return replies back to the client of
|
||||
the HTTP request.
|
||||
|
||||
<a id="camel-intercepting-route-construction-java"></a>
|
||||
### Intercepting route construction
|
||||
|
||||
.. _camel-intercepting-route-construction-java:
|
||||
|
||||
Intercepting route construction
|
||||
-------------------------------
|
||||
|
||||
The previous section, :ref:`camel-components-java`, explained how to setup a route to
|
||||
The previous section, [Akka Camel components](#camel-components-java), explained how to setup a route to
|
||||
an actor manually.
|
||||
It was the application's responsibility to define the route and add it to the current CamelContext.
|
||||
This section explains a more convenient way to define custom routes: akka-camel is still setting up the routes to consumer actors
|
||||
(and adds these routes to the current CamelContext) but applications can define extensions to these routes.
|
||||
Extensions can be defined with Camel's `Java DSL`_ or `Scala DSL`_. For example, an extension could be a custom error handler that redelivers messages from an endpoint to an actor's bounded mailbox when the mailbox was full.
|
||||
|
||||
.. _Java DSL: http://camel.apache.org/dsl.html
|
||||
.. _Scala DSL: http://camel.apache.org/scala-dsl.html
|
||||
Extensions can be defined with Camel's [Java DSL](http://camel.apache.org/dsl.html) or [Scala DSL](http://camel.apache.org/scala-dsl.html). For example, an extension could be a custom error handler that redelivers messages from an endpoint to an actor's bounded mailbox when the mailbox was full.
|
||||
|
||||
The following examples demonstrate how to extend a route to a consumer actor for
|
||||
handling exceptions thrown by that actor.
|
||||
|
||||
.. includecode:: code/jdocs/camel/ErrorThrowingConsumer.java#ErrorThrowingConsumer
|
||||
@@snip [ErrorThrowingConsumer.java](code/jdocs/camel/ErrorThrowingConsumer.java) { #ErrorThrowingConsumer }
|
||||
|
||||
The above ErrorThrowingConsumer sends the Failure back to the sender in preRestart
|
||||
because the Exception that is thrown in the actor would
|
||||
|
|
@ -462,54 +386,44 @@ otherwise just crash the actor, by default the actor would be restarted, and the
|
|||
The akka-camel module creates a RouteDefinition instance by calling
|
||||
from(endpointUri) on a Camel RouteBuilder (where endpointUri is the endpoint URI
|
||||
of the consumer actor) and passes that instance as argument to the route
|
||||
definition handler \*). The route definition handler then extends the route and
|
||||
definition handler *). The route definition handler then extends the route and
|
||||
returns a ProcessorDefinition (in the above example, the ProcessorDefinition
|
||||
returned by the end method. See the `org.apache.camel.model`__ package for
|
||||
returned by the end method. See the [org.apache.camel.model](https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/model/) package for
|
||||
details). After executing the route definition handler, akka-camel finally calls
|
||||
a to(targetActorUri) on the returned ProcessorDefinition to complete the
|
||||
route to the consumer actor (where targetActorUri is the actor component URI as described in :ref:`access-to-actors-java`).
|
||||
If the actor cannot be found, a `ActorNotRegisteredException` is thrown.
|
||||
route to the consumer actor (where targetActorUri is the actor component URI as described in [Access to actors](#access-to-actors-java)).
|
||||
If the actor cannot be found, a *ActorNotRegisteredException* is thrown.
|
||||
|
||||
\*) Before passing the RouteDefinition instance to the route definition handler,
|
||||
*) Before passing the RouteDefinition instance to the route definition handler,
|
||||
akka-camel may make some further modifications to it.
|
||||
|
||||
__ https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/java/org/apache/camel/model/
|
||||
<a id="camel-examples-java"></a>
|
||||
## Examples
|
||||
|
||||
.. _camel-examples-java:
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
The sample named `Akka Camel Samples with Java <@exampleCodeService@/akka-samples-camel-java>`_ (`source code <@samples@/akka-sample-camel-java>`_)
|
||||
The sample named [Akka Camel Samples with Java](@exampleCodeService@/akka-samples-camel-java) ([source code](@samples@/akka-sample-camel-java))
|
||||
contains 3 samples:
|
||||
|
||||
>
|
||||
* Asynchronous routing and transformation - This example demonstrates how to implement consumer and
|
||||
producer actors that support :ref:`camel-asynchronous-routing-java` with their Camel endpoints.
|
||||
|
||||
* Custom Camel route - Demonstrates the combined usage of a ``Producer`` and a
|
||||
``Consumer`` actor as well as the inclusion of a custom Camel route.
|
||||
|
||||
producer actors that support [Asynchronous routing](#camel-asynchronous-routing-java) with their Camel endpoints.
|
||||
* Custom Camel route - Demonstrates the combined usage of a `Producer` and a
|
||||
`Consumer` actor as well as the inclusion of a custom Camel route.
|
||||
* Quartz Scheduler Example - Showing how simple is to implement a cron-style scheduler by
|
||||
using the Camel Quartz component
|
||||
using the Camel Quartz component
|
||||
|
||||
Configuration
|
||||
=============
|
||||
## Configuration
|
||||
|
||||
There are several configuration properties for the Camel module, please refer
|
||||
to the :ref:`reference configuration <config-akka-camel>`.
|
||||
to the @ref:[reference configuration](../general/configuration.md#config-akka-camel).
|
||||
|
||||
Additional Resources
|
||||
====================
|
||||
For an introduction to akka-camel 2, see also the Peter Gabryanczyk's talk `Migrating akka-camel module to Akka 2.x`_.
|
||||
## Additional Resources
|
||||
|
||||
For an introduction to akka-camel 1, see also the `Appendix E - Akka and Camel`_
|
||||
(pdf) of the book `Camel in Action`_.
|
||||
For an introduction to akka-camel 2, see also the Peter Gabryanczyk's talk [Migrating akka-camel module to Akka 2.x](http://skillsmatter.com/podcast/scala/akka-2-x).
|
||||
|
||||
.. _Appendix E - Akka and Camel: http://www.manning.com/ibsen/appEsample.pdf
|
||||
.. _Camel in Action: http://www.manning.com/ibsen/
|
||||
.. _Migrating akka-camel module to Akka 2.x: http://skillsmatter.com/podcast/scala/akka-2-x
|
||||
For an introduction to akka-camel 1, see also the [Appendix E - Akka and Camel](http://www.manning.com/ibsen/appEsample.pdf)
|
||||
(pdf) of the book [Camel in Action](http://www.manning.com/ibsen/).
|
||||
|
||||
Other, more advanced external articles (for version 1) are:
|
||||
|
||||
* `Akka Consumer Actors: New Features and Best Practices <http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html>`_
|
||||
* `Akka Producer Actors: New Features and Best Practices <http://krasserm.blogspot.com/2011/02/akka-producer-actor-new-features-and.html>`_
|
||||
* [Akka Consumer Actors: New Features and Best Practices](http://krasserm.blogspot.com/2011/02/akka-consumer-actors-new-features-and.html)
|
||||
* [Akka Producer Actors: New Features and Best Practices](http://krasserm.blogspot.com/2011/02/akka-producer-actor-new-features-and.html)
|
||||
Loading…
Add table
Add a link
Reference in a new issue