=doc #3689 Make activator templates for camel samples

* @rkuhn found the problems in the scala camel samples
  - HttpSample returns scrambled data
  - CustomRouteSample times out
This commit is contained in:
Patrik Nordwall 2013-11-15 16:28:14 +01:00
parent 362074177a
commit 23dd957ba2
47 changed files with 693 additions and 559 deletions

View file

@ -312,7 +312,7 @@ 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`_.
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 a :ref:`camel-async-example-java` that implements both, an asynchronous
also :ref:`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
@ -469,116 +469,18 @@ __ https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/j
Examples
========
.. _camel-async-example-java:
The `Typesafe Activator <http://typesafe.com/platform/getstarted>`_
tutorial named `Akka Camel Samples with Java <http://typesafe.com/activator/template/akka-sample-camel-java>`_
contains 3 samples:
Asynchronous routing and transformation example
-----------------------------------------------
* 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.
This example demonstrates how to implement consumer and producer actors that
support :ref:`camel-asynchronous-routing-java` with their Camel endpoints. The sample
application transforms the content of the Akka homepage, http://akka.io, by
replacing every occurrence of *Akka* with *AKKA*. To run this example, add
a Boot class that starts the actors. After starting
the :ref:`microkernel-java`, direct the browser to http://localhost:8875 and the
transformed Akka homepage should be displayed. Please note that this example
will probably not work if you're behind an HTTP proxy.
The following figure gives an overview how the example actors interact with
external systems and with each other. A browser sends a GET request to
http://localhost:8875 which is the published endpoint of the ``HttpConsumer``
actor. The ``HttpConsumer`` actor forwards the requests to the ``HttpProducer``
actor which retrieves the Akka homepage from http://akka.io. The retrieved HTML
is then forwarded to the ``HttpTransformer`` actor which replaces all occurrences
of *Akka* with *AKKA*. The transformation result is sent back the HttpConsumer
which finally returns it to the browser.
.. image:: ../images/camel-async-interact.png
Implementing the example actor classes and wiring them together is rather easy
as shown in the following snippet.
.. includecode:: code/docs/camel/sample/http/HttpConsumer.java#HttpExample
.. includecode:: code/docs/camel/sample/http/HttpProducer.java#HttpExample
.. includecode:: code/docs/camel/sample/http/HttpTransformer.java#HttpExample
.. includecode:: code/docs/camel/sample/http/HttpSample.java#HttpExample
The `jetty endpoints`_ of HttpConsumer and HttpProducer support asynchronous
in-out message exchanges and do not allocate threads for the full duration of
the exchange. This is achieved by using `Jetty continuations`_ on the
consumer-side and by using `Jetty's asynchronous HTTP client`_ on the producer
side. The following high-level sequence diagram illustrates that.
.. _jetty endpoints: http://camel.apache.org/jetty.html
.. _Jetty continuations: http://wiki.eclipse.org/Jetty/Feature/Continuations
.. _Jetty's asynchronous HTTP client: http://wiki.eclipse.org/Jetty/Tutorial/HttpClient
.. image:: ../images/camel-async-sequence.png
Custom Camel route example
--------------------------
This section also demonstrates the combined usage of a ``Producer`` and a
``Consumer`` actor as well as the inclusion of a custom Camel route. The
following figure gives an overview.
.. image:: ../images/camel-custom-route.png
* A consumer actor receives a message from an HTTP client
* It forwards the message to another actor that transforms the message (encloses
the original message into hyphens)
* The transformer actor forwards the transformed message to a producer actor
* The producer actor sends the message to a custom Camel route beginning at the
``direct:welcome`` endpoint
* A processor (transformer) in the custom Camel route prepends "Welcome" to the
original message and creates a result message
* The producer actor sends the result back to the consumer actor which returns
it to the HTTP client
The consumer, transformer and
producer actor implementations are as follows.
.. includecode:: code/docs/camel/sample/route/Consumer3.java#CustomRouteExample
.. includecode:: code/docs/camel/sample/route/Transformer.java#CustomRouteExample
.. includecode:: code/docs/camel/sample/route/Producer1.java#CustomRouteExample
.. includecode:: code/docs/camel/sample/route/CustomRouteSample.java#CustomRouteExample
The producer actor knows where to reply the message to because the consumer and
transformer actors have forwarded the original sender reference as well. The
application configuration and the route starting from direct:welcome are done in the code above.
To run the example, add the lines shown in the example to a Boot class and the start the :ref:`microkernel-java` and POST a message to
``http://localhost:8877/camel/welcome``.
.. code-block:: none
curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
The response should be:
.. code-block:: none
Welcome - Anke -
Quartz Scheduler Example
------------------------
Here is an example showing how simple is to implement a cron-style scheduler by
using the Camel Quartz component in Akka.
The following example creates a "timer" actor which fires a message every 2
seconds:
.. includecode:: code/docs/camel/sample/quartz/MyQuartzActor.java#QuartzExample
.. includecode:: code/docs/camel/sample/quartz/QuartzSample.java#QuartzExample
For more information about the Camel Quartz component, see here:
http://camel.apache.org/quartz.html
* Quartz Scheduler Example - Showing how simple is to implement a cron-style scheduler by
using the Camel Quartz component
Additional Resources
====================

View file

@ -1,23 +0,0 @@
package docs.camel.sample.http;
import akka.actor.*;
public class HttpSample {
public static void main(String[] args) {
//#HttpExample
// Create the actors. this can be done in a Boot class so you can
// run the example in the MicroKernel. Just add the three lines below
// to your boot class.
ActorSystem system = ActorSystem.create("some-system");
final ActorRef httpTransformer = system.actorOf(
Props.create(HttpTransformer.class));
final ActorRef httpProducer = system.actorOf(
Props.create(HttpProducer.class, httpTransformer));
final ActorRef httpConsumer = system.actorOf(
Props.create(HttpConsumer.class, httpProducer));
//#HttpExample
}
}

View file

@ -1,18 +0,0 @@
package docs.camel.sample.route;
//#CustomRouteExample
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
public class CustomRouteBuilder extends RouteBuilder{
public void configure() throws Exception {
from("direct:welcome").process(new Processor(){
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(String.format("Welcome %s",
exchange.getIn().getBody()));
}
});
}
}
//#CustomRouteExample

View file

@ -1,23 +0,0 @@
package docs.camel.sample.route;
import akka.actor.*;
import akka.camel.CamelExtension;
public class CustomRouteSample {
@SuppressWarnings("unused")
public static void main(String[] args) {
try {
//#CustomRouteExample
// the below lines can be added to a Boot class, so that you can run the
// example from a MicroKernel
ActorSystem system = ActorSystem.create("some-system");
final ActorRef producer = system.actorOf(Props.create(Producer1.class));
final ActorRef mediator = system.actorOf(Props.create(Transformer.class, producer));
final ActorRef consumer = system.actorOf(Props.create(Consumer3.class, mediator));
CamelExtension.get(system).context().addRoutes(new CustomRouteBuilder());
//#CustomRouteExample
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -1,10 +0,0 @@
package docs.camel.sample.route;
//#CustomRouteExample
import akka.camel.javaapi.UntypedProducerActor;
public class Producer1 extends UntypedProducerActor{
public String getEndpointUri() {
return "direct:welcome";
}
}
//#CustomRouteExample

View file

@ -308,7 +308,7 @@ 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`_.
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 a :ref:`camel-async-example` that implements both, an asynchronous
also :ref:`camel-examples` 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
@ -463,110 +463,19 @@ __ https://svn.apache.org/repos/asf/camel/tags/camel-2.8.0/camel-core/src/main/j
Examples
========
.. _camel-async-example:
The `Typesafe Activator <http://typesafe.com/platform/getstarted>`_
tutorial named `Akka Camel Samples with Scala <http://typesafe.com/activator/template/akka-sample-camel-scala>`_
contains 3 samples:
Asynchronous routing and transformation example
-----------------------------------------------
* Asynchronous routing and transformation - This example demonstrates how to implement consumer and
producer actors that support :ref:`camel-asynchronous-routing` 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.
This example demonstrates how to implement consumer and producer actors that
support :ref:`camel-asynchronous-routing` with their Camel endpoints. The sample
application transforms the content of the Akka homepage, http://akka.io, by
replacing every occurrence of *Akka* with *AKKA*. To run this example, add
a Boot class that starts the actors. After starting
the :ref:`microkernel-scala`, direct the browser to http://localhost:8875 and the
transformed Akka homepage should be displayed. Please note that this example
will probably not work if you're behind an HTTP proxy.
* Quartz Scheduler Example - Showing how simple is to implement a cron-style scheduler by
using the Camel Quartz component
The following figure gives an overview how the example actors interact with
external systems and with each other. A browser sends a GET request to
http://localhost:8875 which is the published endpoint of the ``HttpConsumer``
actor. The ``HttpConsumer`` actor forwards the requests to the ``HttpProducer``
actor which retrieves the Akka homepage from http://akka.io. The retrieved HTML
is then forwarded to the ``HttpTransformer`` actor which replaces all occurrences
of *Akka* with *AKKA*. The transformation result is sent back the HttpConsumer
which finally returns it to the browser.
.. image:: ../images/camel-async-interact.png
Implementing the example actor classes and wiring them together is rather easy
as shown in the following snippet.
.. includecode:: code/docs/camel/HttpExample.scala#HttpExample
The `jetty endpoints`_ of HttpConsumer and HttpProducer support asynchronous
in-out message exchanges and do not allocate threads for the full duration of
the exchange. This is achieved by using `Jetty continuations`_ on the
consumer-side and by using `Jetty's asynchronous HTTP client`_ on the producer
side. The following high-level sequence diagram illustrates that.
.. _jetty endpoints: http://camel.apache.org/jetty.html
.. _Jetty continuations: http://wiki.eclipse.org/Jetty/Feature/Continuations
.. _Jetty's asynchronous HTTP client: http://wiki.eclipse.org/Jetty/Tutorial/HttpClient
.. image:: ../images/camel-async-sequence.png
Custom Camel route example
--------------------------
This section also demonstrates the combined usage of a ``Producer`` and a
``Consumer`` actor as well as the inclusion of a custom Camel route. The
following figure gives an overview.
.. image:: ../images/camel-custom-route.png
* A consumer actor receives a message from an HTTP client
* It forwards the message to another actor that transforms the message (encloses
the original message into hyphens)
* The transformer actor forwards the transformed message to a producer actor
* The producer actor sends the message to a custom Camel route beginning at the
``direct:welcome`` endpoint
* A processor (transformer) in the custom Camel route prepends "Welcome" to the
original message and creates a result message
* The producer actor sends the result back to the consumer actor which returns
it to the HTTP client
The consumer, transformer and
producer actor implementations are as follows.
.. includecode:: code/docs/camel/CustomRouteExample.scala#CustomRouteExample
The producer actor knows where to reply the message to because the consumer and
transformer actors have forwarded the original sender reference as well. The
application configuration and the route starting from direct:welcome are done in the code above.
To run the example, add the lines shown in the example to a Boot class and the start the :ref:`microkernel-scala` and POST a message to
``http://localhost:8877/camel/welcome``.
.. code-block:: none
curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
The response should be:
.. code-block:: none
Welcome - Anke -
Quartz Scheduler Example
------------------------
Here is an example showing how simple is to implement a cron-style scheduler by
using the Camel Quartz component in Akka.
The following example creates a "timer" actor which fires a message every 2
seconds:
.. includecode:: code/docs/camel/QuartzExample.scala#Quartz
For more information about the Camel Quartz component, see here:
http://camel.apache.org/quartz.html
Additional Resources
====================

View file

@ -1,53 +0,0 @@
package docs.camel
object CustomRouteExample {
{
//#CustomRouteExample
import akka.actor.{ Actor, ActorRef, Props, ActorSystem }
import akka.camel.{ CamelMessage, Consumer, Producer, CamelExtension }
import org.apache.camel.builder.RouteBuilder
import org.apache.camel.{ Exchange, Processor }
class Consumer3(transformer: ActorRef) extends Actor with Consumer {
def endpointUri = "jetty:http://0.0.0.0:8877/camel/welcome"
def receive = {
// Forward a string representation of the message body to transformer
case msg: CamelMessage transformer.forward(msg.bodyAs[String])
}
}
class Transformer(producer: ActorRef) extends Actor {
def receive = {
// example: transform message body "foo" to "- foo -" and forward result
// to producer
case msg: CamelMessage
producer.forward(msg.mapBody((body: String) "- %s -" format body))
}
}
class Producer1 extends Actor with Producer {
def endpointUri = "direct:welcome"
}
class CustomRouteBuilder extends RouteBuilder {
def configure {
from("direct:welcome").process(new Processor() {
def process(exchange: Exchange) {
// Create a 'welcome' message from the input message
exchange.getOut.setBody("Welcome %s" format exchange.getIn.getBody)
}
})
}
}
// the below lines can be added to a Boot class, so that you can run the
// example from a MicroKernel
val system = ActorSystem("some-system")
val producer = system.actorOf(Props[Producer1])
val mediator = system.actorOf(Props(classOf[Transformer], producer))
val consumer = system.actorOf(Props(classOf[Consumer3], mediator))
CamelExtension(system).context.addRoutes(new CustomRouteBuilder)
//#CustomRouteExample
}
}

View file

@ -1,52 +0,0 @@
package docs.camel
object HttpExample {
{
//#HttpExample
import org.apache.camel.Exchange
import akka.actor.{ Actor, ActorRef, Props, ActorSystem }
import akka.camel.{ Producer, CamelMessage, Consumer }
import akka.actor.Status.Failure
class HttpConsumer(producer: ActorRef) extends Consumer {
def endpointUri = "jetty:http://0.0.0.0:8875/"
def receive = {
case msg producer forward msg
}
}
class HttpProducer(transformer: ActorRef) extends Actor with Producer {
def endpointUri = "jetty://http://akka.io/?bridgeEndpoint=true"
override def transformOutgoingMessage(msg: Any) = msg match {
case msg: CamelMessage msg.copy(headers = msg.headers ++
msg.headers(Set(Exchange.HTTP_PATH)))
}
override def routeResponse(msg: Any) { transformer forward msg }
}
class HttpTransformer extends Actor {
def receive = {
case msg: CamelMessage
sender ! (msg.mapBody { body: Array[Byte]
new String(body).replaceAll("Akka ", "AKKA ")
})
case msg: Failure sender ! msg
}
}
// Create the actors. this can be done in a Boot class so you can
// run the example in the MicroKernel. Just add the three lines below
// to your boot class.
val system = ActorSystem("some-system")
val httpTransformer = system.actorOf(Props[HttpTransformer])
val httpProducer = system.actorOf(Props(classOf[HttpProducer], httpTransformer))
val httpConsumer = system.actorOf(Props(classOf[HttpConsumer], httpProducer))
//#HttpExample
}
}

View file

@ -1,30 +0,0 @@
package docs.camel
object QuartzExample {
//#Quartz
import akka.actor.{ ActorSystem, Props }
import akka.camel.{ Consumer }
class MyQuartzActor extends Consumer {
def endpointUri = "quartz://example?cron=0/2+*+*+*+*+?"
def receive = {
case msg println("==============> received %s " format msg)
} // end receive
} // end MyQuartzActor
object MyQuartzActor {
def main(str: Array[String]) {
val system = ActorSystem("my-quartz-system")
system.actorOf(Props[MyQuartzActor])
} // end main
} // end MyQuartzActor
//#Quartz
}

View file

@ -0,0 +1,17 @@
*#
*.iml
*.ipr
*.iws
*.pyc
*.tm.epoch
*.vim
*-shim.sbt
.idea/
/project/plugins/project
project/boot
target/
/logs
.cache
.classpath
.project
.settings

View file

@ -0,0 +1,13 @@
Copyright 2013 Typesafe, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,4 @@
name=akka-sample-camel-java
title=Akka Camel Samples with Java
description=Akka Camel Samples with Java
tags=akka,camel,java,sample

View file

@ -0,0 +1,14 @@
name := "akka-sample-camel-java"
version := "1.0"
scalaVersion := "2.10.3"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-camel" % "2.3-SNAPSHOT",
"org.apache.camel" % "camel-jetty" % "2.10.3",
"org.apache.camel" % "camel-quartz" % "2.10.3",
"org.slf4j" % "slf4j-api" % "1.7.2",
"ch.qos.logback" % "logback-classic" % "1.0.7"
)

View file

@ -0,0 +1 @@
sbt.version=0.13.0

View file

@ -1,14 +1,13 @@
package docs.camel.sample.http;
package sample.camel.http;
import akka.actor.ActorRef;
import akka.camel.javaapi.UntypedConsumerActor;
//#HttpExample
public class HttpConsumer extends UntypedConsumerActor{
public class HttpConsumer extends UntypedConsumerActor {
private ActorRef producer;
public HttpConsumer(ActorRef producer){
public HttpConsumer(ActorRef producer) {
this.producer = producer;
}
@ -20,4 +19,3 @@ public class HttpConsumer extends UntypedConsumerActor{
producer.forward(message, getContext());
}
}
//#HttpExample

View file

@ -1,4 +1,4 @@
package docs.camel.sample.http;
package sample.camel.http;
import akka.actor.ActorRef;
import akka.camel.CamelMessage;
@ -8,8 +8,7 @@ import org.apache.camel.Exchange;
import java.util.HashSet;
import java.util.Set;
//#HttpExample
public class HttpProducer extends UntypedProducerActor{
public class HttpProducer extends UntypedProducerActor {
private ActorRef transformer;
public HttpProducer(ActorRef transformer) {
@ -17,9 +16,13 @@ public class HttpProducer extends UntypedProducerActor{
}
public String getEndpointUri() {
// bridgeEndpoint=true makes the producer ignore the Exchange.HTTP_URI header,
// and use the endpoint's URI for request
return "jetty://http://akka.io/?bridgeEndpoint=true";
}
// before producing messages to endpoints, producer actors can pre-process
// them by overriding the onTransformOutgoingMessage method
@Override
public Object onTransformOutgoingMessage(Object message) {
if (message instanceof CamelMessage) {
@ -27,12 +30,14 @@ public class HttpProducer extends UntypedProducerActor{
Set<String> httpPath = new HashSet<String>();
httpPath.add(Exchange.HTTP_PATH);
return camelMessage.withHeaders(camelMessage.getHeaders(httpPath));
} else return super.onTransformOutgoingMessage(message);
} else
return super.onTransformOutgoingMessage(message);
}
// instead of replying to the initial sender, producer actors can implement custom
// response processing by overriding the onRouteResponse method
@Override
public void onRouteResponse(Object message) {
transformer.forward(message, getContext());
}
}
//#HttpExample

View file

@ -0,0 +1,15 @@
package sample.camel.http;
import akka.actor.*;
public class HttpSample {
public static void main(String[] args) {
ActorSystem system = ActorSystem.create("some-system");
final ActorRef httpTransformer = system.actorOf(Props.create(HttpTransformer.class));
final ActorRef httpProducer = system.actorOf(Props.create(HttpProducer.class, httpTransformer));
final ActorRef httpConsumer = system.actorOf(Props.create(HttpConsumer.class, httpProducer));
}
}

View file

@ -1,21 +1,18 @@
package docs.camel.sample.http;
package sample.camel.http;
import akka.actor.Status;
import akka.actor.UntypedActor;
import akka.camel.CamelMessage;
import akka.dispatch.Mapper;
import akka.japi.Function;
//#HttpExample
public class HttpTransformer extends UntypedActor{
public class HttpTransformer extends UntypedActor {
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
CamelMessage camelMessage = (CamelMessage) message;
CamelMessage replacedMessage =
camelMessage.mapBody(new Mapper<Object, String>(){
CamelMessage replacedMessage = camelMessage.mapBody(new Mapper<Object, String>() {
@Override
public String apply(Object body) {
String text = new String((byte[])body);
String text = new String((byte[]) body);
return text.replaceAll("Akka ", "AKKA ");
}
});
@ -26,4 +23,3 @@ public class HttpTransformer extends UntypedActor{
unhandled(message);
}
}
//#HttpExample

View file

@ -1,9 +1,9 @@
package docs.camel.sample.quartz;
//#QuartzExample
package sample.camel.quartz;
import akka.camel.CamelMessage;
import akka.camel.javaapi.UntypedConsumerActor;
public class MyQuartzActor extends UntypedConsumerActor{
public class MyQuartzActor extends UntypedConsumerActor {
public String getEndpointUri() {
return "quartz://example?cron=0/2+*+*+*+*+?";
}
@ -11,10 +11,8 @@ public class MyQuartzActor extends UntypedConsumerActor{
public void onReceive(Object message) {
if (message instanceof CamelMessage) {
CamelMessage camelMessage = (CamelMessage) message;
String body = camelMessage.getBodyAs(String.class, getCamelContext());
System.out.println(String.format("==============> received %s ", body));
System.out.println(String.format("==============> received %s ", camelMessage));
} else
unhandled(message);
}
}
//#QuartzExample

View file

@ -1,5 +1,5 @@
package docs.camel.sample.quartz;
//#QuartzExample
package sample.camel.quartz;
import akka.actor.ActorSystem;
import akka.actor.Props;
@ -9,4 +9,3 @@ public class QuartzSample {
system.actorOf(Props.create(MyQuartzActor.class));
}
}
//#QuartzExample

View file

@ -0,0 +1,15 @@
package sample.camel.route;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
public class CustomRouteBuilder extends RouteBuilder {
public void configure() throws Exception {
from("direct:welcome").process(new Processor() {
public void process(Exchange exchange) throws Exception {
exchange.getOut().setBody(String.format("Welcome %s", exchange.getIn().getBody()));
}
});
}
}

View file

@ -0,0 +1,19 @@
package sample.camel.route;
import akka.actor.*;
import akka.camel.CamelExtension;
public class CustomRouteSample {
@SuppressWarnings("unused")
public static void main(String[] args) {
try {
ActorSystem system = ActorSystem.create("some-system");
final ActorRef producer = system.actorOf(Props.create(RouteProducer.class));
final ActorRef mediator = system.actorOf(Props.create(RouteTransformer.class, producer));
final ActorRef consumer = system.actorOf(Props.create(RouteConsumer.class, mediator));
CamelExtension.get(system).context().addRoutes(new CustomRouteBuilder());
} catch (Exception e) {
e.printStackTrace();
}
}
}

View file

@ -1,14 +1,13 @@
package docs.camel.sample.route;
package sample.camel.route;
//#CustomRouteExample
import akka.actor.ActorRef;
import akka.camel.CamelMessage;
import akka.camel.javaapi.UntypedConsumerActor;
public class Consumer3 extends UntypedConsumerActor{
public class RouteConsumer extends UntypedConsumerActor {
private ActorRef transformer;
public Consumer3(ActorRef transformer){
public RouteConsumer(ActorRef transformer) {
this.transformer = transformer;
}
@ -26,4 +25,3 @@ public class Consumer3 extends UntypedConsumerActor{
unhandled(message);
}
}
//#CustomRouteExample

View file

@ -0,0 +1,9 @@
package sample.camel.route;
import akka.camel.javaapi.UntypedProducerActor;
public class RouteProducer extends UntypedProducerActor {
public String getEndpointUri() {
return "direct:welcome";
}
}

View file

@ -1,15 +1,14 @@
package docs.camel.sample.route;
//#CustomRouteExample
package sample.camel.route;
import akka.actor.ActorRef;
import akka.actor.UntypedActor;
import akka.camel.CamelMessage;
import akka.dispatch.Mapper;
import akka.japi.Function;
public class Transformer extends UntypedActor {
public class RouteTransformer extends UntypedActor {
private ActorRef producer;
public Transformer(ActorRef producer) {
public RouteTransformer(ActorRef producer) {
this.producer = producer;
}
@ -18,16 +17,14 @@ public class Transformer extends UntypedActor {
// example: transform message body "foo" to "- foo -" and forward result
// to producer
CamelMessage camelMessage = (CamelMessage) message;
CamelMessage transformedMessage =
camelMessage.mapBody(new Mapper<String, String>(){
@Override
public String apply(String body) {
return String.format("- %s -",body);
}
});
CamelMessage transformedMessage = camelMessage.mapBody(new Mapper<String, String>() {
@Override
public String apply(String body) {
return String.format("- %s -", body);
}
});
producer.forward(transformedMessage, getContext());
} else
unhandled(message);
}
}
//#CustomRouteExample

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Before After
Before After

View file

@ -0,0 +1,163 @@
<!-- <html> -->
<head>
<title>Akka Camel Samples with Java</title>
</head>
<body>
<div>
<p>
This tutorial contains 3 samples of
<a href="http://doc.akka.io/docs/akka/2.3-SNAPSHOT/java/camel.html" target="_blank">Akka Camel</a>.
</p>
<ul>
<li>Asynchronous routing and transformation</li>
<li>Custom Camel route</li>
<li>Quartz scheduler</li>
</ul>
</div>
<div>
<h2>Asynchronous routing and transformation</h2>
<p>
This example demonstrates how to implement consumer and producer actors that
support
<a href="http://doc.akka.io/docs/akka/2.3-SNAPSHOT/java/camel.html#Asynchronous_routing" target="_blank">
Asynchronous routing</a> with their Camel endpoints. The sample
application transforms the content of the Akka homepage, <a href="http://akka.io" target="_blank">http://akka.io</a>,
by replacing every occurrence of *Akka* with *AKKA*.
</p>
<p>
To run this example, go to the <a href="#run" class="shortcut">Run</a>
tab, and start the application main class <code>sample.camel.http.HttpExample</code> if it's not already started.
Then direct the browser to <a href="http://localhost:8875" target="_blank">http://localhost:8875</a> and the
transformed Akka homepage should be displayed. Please note that this example will probably not work if you're
behind an HTTP proxy.
</p>
<p>
The following figure gives an overview how the example actors interact with
external systems and with each other. A browser sends a GET request to
http://localhost:8875 which is the published endpoint of the
<a href="#code/src/main/java/sample/camel/http/HttpConsumer.java" class="shortcut">HttpConsumer</a>
actor. The <code>HttpConsumer</code>actor forwards the requests to the
<a href="#code/src/main/java/sample/camel/http/HttpProducer.java" class="shortcut">HttpProducer.java</a>
actor which retrieves the Akka homepage from http://akka.io. The retrieved HTML
is then forwarded to the
<a href="#code/src/main/java/sample/camel/http/HttpTransformer.java" class="shortcut">HttpTransformer.java</a>
actor which replaces all occurrences of *Akka* with *AKKA*. The transformation result is sent back the HttpConsumer
which finally returns it to the browser.
</p>
<img src="tutorial/camel-async-interact.png" width="400" />
<p>
Implementing the example actor classes and wiring them together is rather easy
as shown in <a href="#code/src/main/java/sample/camel/http/HttpConsumer.java" class="shortcut">HttpConsumer.java</a>,
<a href="#code/src/main/java/sample/camel/http/HttpProducer.java" class="shortcut">HttpProducer.java</a> and
<a href="#code/src/main/java/sample/camel/http/HttpTransformer.java" class="shortcut">HttpTransformer.java</a>.
</p>
<p>
The <a href="http://camel.apache.org/jetty.html" target="_blank">jetty endpoints</a> of HttpConsumer and
HttpProducer support asynchronous in-out message exchanges and do not allocate threads for the full duration of
the exchange. This is achieved by using <a href="http://wiki.eclipse.org/Jetty/Feature/Continuations" target="_blank">Jetty continuations</a>
on the consumer-side and by using <a href="http://wiki.eclipse.org/Jetty/Tutorial/HttpClient" target="_blank">Jetty's asynchronous HTTP client</a>
on the producer side. The following high-level sequence diagram illustrates that.
</p>
<img src="tutorial/camel-async-sequence.png" width="400" />
</div>
<div>
<h2>Custom Camel route example</h2>
<p>
This section also demonstrates the combined usage of a
<a href="#code/src/main/java/sample/camel/route/RouteProducer.java" class="shortcut">RouteProducer</a> and a
<a href="#code/src/main/java/sample/camel/route/RouteConsumer.java" class="shortcut">RouteConsumer</a>
actor as well as the inclusion of a
<a href="#code/src/main/java/sample/camel/route/CustomRouteSample.java" class="shortcut">custom Camel route</a>.
The following figure gives an overview.
</p>
<img src="tutorial/camel-custom-route.png" width="400" />
<ul>
<li>A consumer actor receives a message from an HTTP client</li>
<li>It forwards the message to another actor that transforms the message (encloses
the original message into hyphens)</li>
<li>The transformer actor forwards the transformed message to a producer actor</li>
<li>The producer actor sends the message to a custom Camel route beginning at the
<code>direct:welcome</code> endpoint</li>
<li>A processor (transformer) in the custom Camel route prepends "Welcome" to the
original message and creates a result message</li>
<li>The producer actor sends the result back to the consumer actor which returns
it to the HTTP client</li>
</ul>
<p>
The producer actor knows where to reply the message to because the consumer and
transformer actors have forwarded the original sender reference as well. The
application configuration and the route starting from direct:welcome are done in the code above.
</p>
<p>
To run this example, go to the <a href="#run" class="shortcut">Run</a>
tab, and start the application main class <code>sample.camel.route.CustomRouteExample</code>
</p>
<p>
POST a message to <code>http://localhost:8877/camel/welcome</code>.
</p>
<pre><code>
curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
</code></pre>
<p>
The response should be:
</p>
<pre><code>
Welcome - Anke -
</code></pre>
</div>
<div>
<h2>Quartz Scheduler Example</h2>
<p>
Here is an example showing how simple it is to implement a cron-style scheduler by
using the Camel Quartz component in Akka.
</p>
<p>
Open <a href="#code/src/main/java/sample/camel/quartz/MyQuartzActor.java" class="shortcut">MyQuartzActor.java</a>.
</p>
<p>
The example creates a "timer" actor which fires a message every 2
seconds.
</p>
<p>
For more information about the Camel Quartz component, see here:
<a href="http://camel.apache.org/quartz.html" target="_blank">http://camel.apache.org/quartz.html</a>
</p>
</div>
</body>
</html>

View file

@ -0,0 +1,17 @@
*#
*.iml
*.ipr
*.iws
*.pyc
*.tm.epoch
*.vim
*-shim.sbt
.idea/
/project/plugins/project
project/boot
target/
/logs
.cache
.classpath
.project
.settings

View file

@ -0,0 +1,13 @@
Copyright 2013 Typesafe, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,4 @@
name=akka-sample-camel-scala
title=Akka Camel Samples with Scala
description=Akka Camel Samples with Scala
tags=akka,camel,scala,sample

View file

@ -0,0 +1,14 @@
name := "akka-sample-camel-scala"
version := "1.0"
scalaVersion := "2.10.3"
libraryDependencies ++= Seq(
"com.typesafe.akka" %% "akka-camel" % "2.3-SNAPSHOT",
"org.apache.camel" % "camel-jetty" % "2.10.3",
"org.apache.camel" % "camel-quartz" % "2.10.3",
"org.slf4j" % "slf4j-api" % "1.7.2",
"ch.qos.logback" % "logback-classic" % "1.0.7"
)

View file

@ -0,0 +1 @@
sbt.version=0.13.0

View file

@ -0,0 +1,58 @@
package sample.camel
import org.apache.camel.Exchange
import org.apache.camel.Processor
import org.apache.camel.builder.RouteBuilder
import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.camel.CamelExtension
import akka.camel.CamelMessage
import akka.camel.Consumer
import akka.camel.Producer
object CustomRouteExample {
def main(args: Array[String]): Unit = {
val system = ActorSystem("some-system")
val producer = system.actorOf(Props[RouteProducer])
val mediator = system.actorOf(Props(classOf[RouteTransformer], producer))
val consumer = system.actorOf(Props(classOf[RouteConsumer], mediator))
CamelExtension(system).context.addRoutes(new CustomRouteBuilder)
}
class RouteConsumer(transformer: ActorRef) extends Actor with Consumer {
def endpointUri = "jetty:http://0.0.0.0:8877/camel/welcome"
def receive = {
// Forward a string representation of the message body to transformer
case msg: CamelMessage => transformer.forward(msg.withBodyAs[String])
}
}
class RouteTransformer(producer: ActorRef) extends Actor {
def receive = {
// example: transform message body "foo" to "- foo -" and forward result
// to producer
case msg: CamelMessage =>
producer.forward(msg.mapBody((body: String) => "- %s -" format body))
}
}
class RouteProducer extends Actor with Producer {
def endpointUri = "direct:welcome"
}
class CustomRouteBuilder extends RouteBuilder {
def configure {
from("direct:welcome").process(new Processor() {
def process(exchange: Exchange) {
// Create a 'welcome' message from the input message
exchange.getOut.setBody("Welcome %s" format exchange.getIn.getBody)
}
})
}
}
}

View file

@ -0,0 +1,58 @@
package sample.camel
import org.apache.camel.Exchange
import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.Status.Failure
import akka.actor.actorRef2Scala
import akka.camel.CamelMessage
import akka.camel.Consumer
import akka.camel.Producer
object HttpExample {
def main(args: Array[String]): Unit = {
val system = ActorSystem("some-system")
val httpTransformer = system.actorOf(Props[HttpTransformer])
val httpProducer = system.actorOf(Props(classOf[HttpProducer], httpTransformer))
val httpConsumer = system.actorOf(Props(classOf[HttpConsumer], httpProducer))
}
class HttpConsumer(producer: ActorRef) extends Consumer {
def endpointUri = "jetty:http://0.0.0.0:8875/"
def receive = {
case msg => producer forward msg
}
}
class HttpProducer(transformer: ActorRef) extends Actor with Producer {
// bridgeEndpoint=true makes the producer ignore the Exchange.HTTP_URI header,
// and use the endpoint's URI for request
def endpointUri = "jetty://http://akka.io/?bridgeEndpoint=true"
// before producing messages to endpoints, producer actors can pre-process
// them by overriding the transformOutgoingMessage method
override def transformOutgoingMessage(msg: Any) = msg match {
case camelMsg: CamelMessage => camelMsg.copy(headers =
camelMsg.headers(Set(Exchange.HTTP_PATH)))
}
// instead of replying to the initial sender, producer actors can implement custom
// response processing by overriding the routeResponse method
override def routeResponse(msg: Any) { transformer forward msg }
}
class HttpTransformer extends Actor {
def receive = {
case msg: CamelMessage =>
sender ! (msg.mapBody { body: Array[Byte] =>
new String(body).replaceAll("Akka ", "AKKA ")
})
case msg: Failure => sender ! msg
}
}
}

View file

@ -0,0 +1,26 @@
package sample.camel
import akka.actor.ActorSystem
import akka.actor.Props
import akka.camel.Consumer
object QuartzExample {
def main(args: Array[String]): Unit = {
val system = ActorSystem("my-quartz-system")
system.actorOf(Props[MyQuartzActor])
}
class MyQuartzActor extends Consumer {
def endpointUri = "quartz://example?cron=0/2+*+*+*+*+?"
def receive = {
case msg => println("==============> received %s " format msg)
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View file

@ -0,0 +1,161 @@
<!-- <html> -->
<head>
<title>Akka Camel Samples with Scala</title>
</head>
<body>
<div>
<p>
This tutorial contains 3 samples of
<a href="http://doc.akka.io/docs/akka/2.3-SNAPSHOT/scala/camel.html" target="_blank">Akka Camel</a>.
</p>
<ul>
<li>Asynchronous routing and transformation</li>
<li>Custom Camel route</li>
<li>Quartz scheduler</li>
</ul>
</div>
<div>
<h2>Asynchronous routing and transformation</h2>
<p>
This example demonstrates how to implement consumer and producer actors that
support
<a href="http://doc.akka.io/docs/akka/2.3-SNAPSHOT/scala/camel.html#Asynchronous_routing" target="_blank">
Asynchronous routing</a> with their Camel endpoints. The sample
application transforms the content of the Akka homepage, <a href="http://akka.io" target="_blank">http://akka.io</a>,
by replacing every occurrence of *Akka* with *AKKA*.
</p>
<p>
To run this example, go to the <a href="#run" class="shortcut">Run</a>
tab, and start the application main class <code>sample.camel.HttpExample</code> if it's not already started.
Then direct the browser to <a href="http://localhost:8875" target="_blank">http://localhost:8875</a> and the
transformed Akka homepage should be displayed. Please note that this example will probably not work if you're
behind an HTTP proxy.
</p>
<p>
The following figure gives an overview how the example actors interact with
external systems and with each other. A browser sends a GET request to
http://localhost:8875 which is the published endpoint of the
<a href="#code/src/main/scala/sample/camel/HttpExample.scala" class="shortcut">HttpConsumer</a>
actor. The <code>HttpConsumer</code> actor forwards the requests to the
<a href="#code/src/main/scala/sample/camel/HttpExample.scala" class="shortcut">HttpProducer</a>
actor which retrieves the Akka homepage from http://akka.io. The retrieved HTML
is then forwarded to the
<a href="#code/src/main/scala/sample/camel/HttpExample.scala" class="shortcut">HttpTransformer</a>
actor which replaces all occurrences of *Akka* with *AKKA*. The transformation result is sent back the HttpConsumer
which finally returns it to the browser.
</p>
<img src="tutorial/camel-async-interact.png" width="400" />
<p>
Implementing the example actor classes and wiring them together is rather easy
as shown in <a href="#code/src/main/scala/sample/camel/HttpExample.scala" class="shortcut">HttpExample.scala</a>.
</p>
<p>
The <a href="http://camel.apache.org/jetty.html" target="_blank">jetty endpoints</a> of HttpConsumer and
HttpProducer support asynchronous in-out message exchanges and do not allocate threads for the full duration of
the exchange. This is achieved by using <a href="http://wiki.eclipse.org/Jetty/Feature/Continuations" target="_blank">Jetty continuations</a>
on the consumer-side and by using <a href="http://wiki.eclipse.org/Jetty/Tutorial/HttpClient" target="_blank">Jetty's asynchronous HTTP client</a>
on the producer side. The following high-level sequence diagram illustrates that.
</p>
<img src="tutorial/camel-async-sequence.png" width="400" />
</div>
<div>
<h2>Custom Camel route example</h2>
<p>
This section also demonstrates the combined usage of a
<a href="#code/src/main/scala/sample/camel/CustomRouteExample.scala" class="shortcut">RouteProducer</a>
and a <a href="#code/src/main/scala/sample/camel/CustomRouteExample.scala" class="shortcut">RouteConsumer</a>
actor as well as the inclusion of a
<a href="#code/src/main/scala/sample/camel/CustomRouteExample.scala" class="shortcut">custom Camel route</a>.
The following figure gives an overview.
</p>
<img src="tutorial/camel-custom-route.png" width="400" />
<ul>
<li>A consumer actor receives a message from an HTTP client</li>
<li>It forwards the message to another actor that transforms the message (encloses
the original message into hyphens)</li>
<li>The transformer actor forwards the transformed message to a producer actor</li>
<li>The producer actor sends the message to a custom Camel route beginning at the
<code>direct:welcome</code> endpoint</li>
<li>A processor (transformer) in the custom Camel route prepends "Welcome" to the
original message and creates a result message</li>
<li>The producer actor sends the result back to the consumer actor which returns
it to the HTTP client</li>
</ul>
<p>
The producer actor knows where to reply the message to because the consumer and
transformer actors have forwarded the original sender reference as well. The
application configuration and the route starting from direct:welcome are done in the code above.
</p>
<p>
To run this example, go to the <a href="#run" class="shortcut">Run</a>
tab, and start the application main class <code>sample.camel.CustomRouteExample</code>
</p>
<p>
POST a message to <code>http://localhost:8877/camel/welcome</code>.
</p>
<pre><code>
curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
</code></pre>
<p>
The response should be:
</p>
<pre><code>
Welcome - Anke -
</code></pre>
</div>
<div>
<h2>Quartz Scheduler Example</h2>
<p>
Here is an example showing how simple it is to implement a cron-style scheduler by
using the Camel Quartz component in Akka.
</p>
<p>
Open <a href="#code/src/main/scala/sample/camel/QuartzExample.scala" class="shortcut">QuartzExample.scala</a>.
</p>
<p>
The example creates a "timer" actor which fires a message every 2
seconds.
</p>
<p>
For more information about the Camel Quartz component, see here:
<a href="http://camel.apache.org/quartz.html" target="_blank">http://camel.apache.org/quartz.html</a>
</p>
</div>
</body>
</html>

View file

@ -1,15 +0,0 @@
Camel Sample
============
This sample is meant to be used by studying the code; it does not perform any
astounding functions when running it. If you want to run it, check out the akka
sources on your local hard drive, follow the [instructions for setting up Akka
with SBT](http://doc.akka.io/docs/akka/current/intro/getting-started.html).
When you start SBT within the checked-out akka source directory, you can run
this sample by typing
akka-sample-camel/run
and then choose which of the demonstrations you would like to run.
You can read more in the [Akka docs](http://akka.io/docs).

View file

@ -1,49 +0,0 @@
import akka.actor.Status.Failure
import akka.actor.{ Actor, ActorRef, Props, ActorSystem }
import akka.camel.{ Producer, CamelMessage, Consumer }
import org.apache.camel.{ Exchange }
/**
* Asynchronous routing and transformation example
*/
object AsyncRouteAndTransform extends App {
val system = ActorSystem("rewriteAkkaToAKKA")
val httpTransformer = system.actorOf(Props[HttpTransformer], "transformer")
val httpProducer = system.actorOf(Props(classOf[HttpProducer], httpTransformer), "producer")
val httpConsumer = system.actorOf(Props(classOf[HttpConsumer], httpProducer), "consumer")
}
class HttpConsumer(producer: ActorRef) extends Consumer {
def endpointUri = "jetty:http://0.0.0.0:8875/"
def receive = {
case msg producer forward msg
}
}
class HttpProducer(transformer: ActorRef) extends Actor with Producer {
def endpointUri = "jetty://http://akka.io/?bridgeEndpoint=true"
override def transformOutgoingMessage(msg: Any) = msg match {
case msg: CamelMessage msg.copy(headers = msg.headers(Set(Exchange.HTTP_PATH)))
}
override def routeResponse(msg: Any) {
transformer forward msg
}
}
class HttpTransformer extends Actor {
def receive = {
case msg: CamelMessage
val transformedMsg = msg.mapBody {
(body: Array[Byte])
new String(body).replaceAll("Akka", "<b>AKKA</b>")
// just to make the result look a bit better.
.replaceAll("href=\"/resources", "href=\"http://akka.io/resources")
.replaceAll("src=\"/resources", "src=\"http://akka.io/resources")
}
sender ! transformedMsg
case msg: Failure sender ! msg
}
}

View file

@ -1,24 +0,0 @@
import akka.actor.{ Props, ActorSystem }
import akka.camel.{ CamelMessage, Consumer }
import java.io.File
import org.apache.camel.Exchange
object SimpleFileConsumer extends App {
val subDir = "consume-files"
val tmpDir = System.getProperty("java.io.tmpdir")
val consumeDir = new File(tmpDir, subDir)
consumeDir.mkdirs()
val tmpDirUri = "file://%s/%s" format (tmpDir, subDir)
val system = ActorSystem("consume-files")
val fileConsumer = system.actorOf(Props(classOf[FileConsumer], tmpDirUri), "fileConsumer")
println(String.format("Put a text file in '%s', the consumer will pick it up!", consumeDir))
}
class FileConsumer(uri: String) extends Consumer {
def endpointUri = uri
def receive = {
case msg: CamelMessage
println("Received file %s with content:\n%s".format(msg.headers(Exchange.FILE_NAME), msg.bodyAs[String]))
}
}

View file

@ -1,4 +1,4 @@
name=akka-sample-main-java
title=Akka Main in Java
description=Actor based version of obligatory Hello World program using the generic launcher class akka.Main.
tags=Basics,akka,java,java,starter
tags=Basics,akka,java,starter

View file

@ -1,4 +1,4 @@
name=akka-sample-main-scala
title=Akka Main in Scala
description=Actor based version of obligatory Hello World program using the generic launcher class akka.Main.
tags=Basics,akka,java,scala,starter
tags=Basics,akka,scala,starter

View file

@ -446,12 +446,19 @@ object AkkaBuild extends Build {
id = "akka-samples",
base = file("akka-samples"),
settings = parentSettings,
aggregate = Seq(camelSample, fsmSample, mainSampleJava, mainSampleScala, helloKernelSample, remoteSample, persistenceSample, clusterSample, multiNodeSample, osgiDiningHakkersSample)
aggregate = Seq(camelSampleJava, camelSampleScala, fsmSample, mainSampleJava, mainSampleScala, helloKernelSample, remoteSample, persistenceSample, clusterSample, multiNodeSample, osgiDiningHakkersSample)
)
lazy val camelSample = Project(
id = "akka-sample-camel",
base = file("akka-samples/akka-sample-camel"),
lazy val camelSampleJava = Project(
id = "akka-sample-camel-java",
base = file("akka-samples/akka-sample-camel-java"),
dependencies = Seq(actor, camel),
settings = sampleSettings ++ Seq(libraryDependencies ++= Dependencies.camelSample)
)
lazy val camelSampleScala = Project(
id = "akka-sample-camel-scala",
base = file("akka-samples/akka-sample-camel-scala"),
dependencies = Seq(actor, camel),
settings = sampleSettings ++ Seq(libraryDependencies ++= Dependencies.camelSample)
)