diff --git a/akka-docs/rst/java/camel.rst b/akka-docs/rst/java/camel.rst index 28fe70e6c2..7be0c5aad4 100644 --- a/akka-docs/rst/java/camel.rst +++ b/akka-docs/rst/java/camel.rst @@ -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 `_ +tutorial named `Akka Camel Samples with 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 ==================== diff --git a/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java b/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java deleted file mode 100644 index 2143c33158..0000000000 --- a/akka-docs/rst/java/code/docs/camel/sample/http/HttpSample.java +++ /dev/null @@ -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 - } -} diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteBuilder.java b/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteBuilder.java deleted file mode 100644 index ad68d38609..0000000000 --- a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteBuilder.java +++ /dev/null @@ -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 diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java b/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java deleted file mode 100644 index f4a3760542..0000000000 --- a/akka-docs/rst/java/code/docs/camel/sample/route/CustomRouteSample.java +++ /dev/null @@ -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(); - } - } -} diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/Producer1.java b/akka-docs/rst/java/code/docs/camel/sample/route/Producer1.java deleted file mode 100644 index 4f937fc95f..0000000000 --- a/akka-docs/rst/java/code/docs/camel/sample/route/Producer1.java +++ /dev/null @@ -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 diff --git a/akka-docs/rst/scala/camel.rst b/akka-docs/rst/scala/camel.rst index 5bce74953a..a3f94baf8b 100644 --- a/akka-docs/rst/scala/camel.rst +++ b/akka-docs/rst/scala/camel.rst @@ -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 `_ +tutorial named `Akka Camel Samples with 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 ==================== diff --git a/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala b/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala deleted file mode 100644 index 49cac853c5..0000000000 --- a/akka-docs/rst/scala/code/docs/camel/CustomRouteExample.scala +++ /dev/null @@ -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 - } - -} diff --git a/akka-docs/rst/scala/code/docs/camel/HttpExample.scala b/akka-docs/rst/scala/code/docs/camel/HttpExample.scala deleted file mode 100644 index a2fd16944b..0000000000 --- a/akka-docs/rst/scala/code/docs/camel/HttpExample.scala +++ /dev/null @@ -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 - - } - -} diff --git a/akka-docs/rst/scala/code/docs/camel/QuartzExample.scala b/akka-docs/rst/scala/code/docs/camel/QuartzExample.scala deleted file mode 100644 index f0ad04be57..0000000000 --- a/akka-docs/rst/scala/code/docs/camel/QuartzExample.scala +++ /dev/null @@ -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 -} diff --git a/akka-samples/akka-sample-camel-java/.gitignore b/akka-samples/akka-sample-camel-java/.gitignore new file mode 100644 index 0000000000..660c959e44 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/.gitignore @@ -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 \ No newline at end of file diff --git a/akka-samples/akka-sample-camel-java/LICENSE b/akka-samples/akka-sample-camel-java/LICENSE new file mode 100644 index 0000000000..a02154466b --- /dev/null +++ b/akka-samples/akka-sample-camel-java/LICENSE @@ -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. diff --git a/akka-samples/akka-sample-camel-java/activator.properties b/akka-samples/akka-sample-camel-java/activator.properties new file mode 100644 index 0000000000..427d9683d4 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/activator.properties @@ -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 diff --git a/akka-samples/akka-sample-camel-java/build.sbt b/akka-samples/akka-sample-camel-java/build.sbt new file mode 100644 index 0000000000..288934017e --- /dev/null +++ b/akka-samples/akka-sample-camel-java/build.sbt @@ -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" +) + diff --git a/akka-samples/akka-sample-camel-java/project/build.properties b/akka-samples/akka-sample-camel-java/project/build.properties new file mode 100644 index 0000000000..0974fce44d --- /dev/null +++ b/akka-samples/akka-sample-camel-java/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.0 diff --git a/akka-docs/rst/java/code/docs/camel/sample/http/HttpConsumer.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpConsumer.java similarity index 66% rename from akka-docs/rst/java/code/docs/camel/sample/http/HttpConsumer.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpConsumer.java index 9ca5fbb886..34e373cecd 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/http/HttpConsumer.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpConsumer.java @@ -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 \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/camel/sample/http/HttpProducer.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpProducer.java similarity index 60% rename from akka-docs/rst/java/code/docs/camel/sample/http/HttpProducer.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpProducer.java index 27e0cb0df3..8c37b50c4d 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/http/HttpProducer.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpProducer.java @@ -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 httpPath = new HashSet(); 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 \ No newline at end of file diff --git a/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpSample.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpSample.java new file mode 100644 index 0000000000..19c1eef98f --- /dev/null +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpSample.java @@ -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)); + } +} diff --git a/akka-docs/rst/java/code/docs/camel/sample/http/HttpTransformer.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpTransformer.java similarity index 67% rename from akka-docs/rst/java/code/docs/camel/sample/http/HttpTransformer.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpTransformer.java index 7aee59293a..6ae1e2bfcc 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/http/HttpTransformer.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/http/HttpTransformer.java @@ -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(){ + CamelMessage replacedMessage = camelMessage.mapBody(new Mapper() { @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 \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/camel/sample/quartz/MyQuartzActor.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/MyQuartzActor.java similarity index 66% rename from akka-docs/rst/java/code/docs/camel/sample/quartz/MyQuartzActor.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/MyQuartzActor.java index 7f38d01943..967abea0c8 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/quartz/MyQuartzActor.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/MyQuartzActor.java @@ -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 \ No newline at end of file diff --git a/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/QuartzSample.java similarity index 79% rename from akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/QuartzSample.java index 59875e77a6..2f4c73d38a 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/quartz/QuartzSample.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/quartz/QuartzSample.java @@ -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 \ No newline at end of file diff --git a/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteBuilder.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteBuilder.java new file mode 100644 index 0000000000..97ace488e5 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteBuilder.java @@ -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())); + } + }); + } +} diff --git a/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteSample.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteSample.java new file mode 100644 index 0000000000..669800b9f6 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/CustomRouteSample.java @@ -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(); + } + } +} diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/Consumer3.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteConsumer.java similarity index 79% rename from akka-docs/rst/java/code/docs/camel/sample/route/Consumer3.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteConsumer.java index 05cd7eb85a..d3067fd8ef 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/route/Consumer3.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteConsumer.java @@ -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 diff --git a/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteProducer.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteProducer.java new file mode 100644 index 0000000000..5a47947087 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteProducer.java @@ -0,0 +1,9 @@ +package sample.camel.route; + +import akka.camel.javaapi.UntypedProducerActor; + +public class RouteProducer extends UntypedProducerActor { + public String getEndpointUri() { + return "direct:welcome"; + } +} diff --git a/akka-docs/rst/java/code/docs/camel/sample/route/Transformer.java b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteTransformer.java similarity index 55% rename from akka-docs/rst/java/code/docs/camel/sample/route/Transformer.java rename to akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteTransformer.java index 97cc8b8f09..5d0ff079c7 100644 --- a/akka-docs/rst/java/code/docs/camel/sample/route/Transformer.java +++ b/akka-samples/akka-sample-camel-java/src/main/java/sample/camel/route/RouteTransformer.java @@ -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(){ - @Override - public String apply(String body) { - return String.format("- %s -",body); - } - }); + CamelMessage transformedMessage = camelMessage.mapBody(new Mapper() { + @Override + public String apply(String body) { + return String.format("- %s -", body); + } + }); producer.forward(transformedMessage, getContext()); } else unhandled(message); } } -//#CustomRouteExample \ No newline at end of file diff --git a/akka-docs/rst/images/camel-async-interact.png b/akka-samples/akka-sample-camel-java/tutorial/camel-async-interact.png similarity index 100% rename from akka-docs/rst/images/camel-async-interact.png rename to akka-samples/akka-sample-camel-java/tutorial/camel-async-interact.png diff --git a/akka-docs/rst/images/camel-async-sequence.png b/akka-samples/akka-sample-camel-java/tutorial/camel-async-sequence.png similarity index 100% rename from akka-docs/rst/images/camel-async-sequence.png rename to akka-samples/akka-sample-camel-java/tutorial/camel-async-sequence.png diff --git a/akka-docs/rst/images/camel-custom-route.png b/akka-samples/akka-sample-camel-java/tutorial/camel-custom-route.png similarity index 100% rename from akka-docs/rst/images/camel-custom-route.png rename to akka-samples/akka-sample-camel-java/tutorial/camel-custom-route.png diff --git a/akka-samples/akka-sample-camel-java/tutorial/index.html b/akka-samples/akka-sample-camel-java/tutorial/index.html new file mode 100644 index 0000000000..9751aa9615 --- /dev/null +++ b/akka-samples/akka-sample-camel-java/tutorial/index.html @@ -0,0 +1,163 @@ + + + Akka Camel Samples with Java + + + + +
+

+This tutorial contains 3 samples of +Akka Camel. +

+ +
    +
  • Asynchronous routing and transformation
  • +
  • Custom Camel route
  • +
  • Quartz scheduler
  • +
+ +
+ +
+ +

Asynchronous routing and transformation

+ +

+This example demonstrates how to implement consumer and producer actors that +support + +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, go to the Run +tab, and start the application main class sample.camel.http.HttpExample if it's not already started. +Then 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 HttpConsumeractor forwards the requests to the +HttpProducer.java +actor which retrieves the Akka homepage from http://akka.io. The retrieved HTML +is then forwarded to the +HttpTransformer.java +actor which replaces all occurrences of *Akka* with *AKKA*. The transformation result is sent back the HttpConsumer +which finally returns it to the browser. +

+ + + +

+Implementing the example actor classes and wiring them together is rather easy +as shown in HttpConsumer.java, +HttpProducer.java and +HttpTransformer.java. +

+ + +

+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. +

+ + + +
+
+ +

Custom Camel route example

+ +

+This section also demonstrates the combined usage of a +RouteProducer and a +RouteConsumer +actor as well as the inclusion of a +custom Camel route. +The following figure gives an overview. +

+ + + +
    +
  • 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 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 this example, go to the Run +tab, and start the application main class sample.camel.route.CustomRouteExample +

+ +

+POST a message to http://localhost:8877/camel/welcome. +

+ +

+   curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
+
+ +

+The response should be: +

+ +

+   Welcome - Anke -
+
+ +
+
+ +

Quartz Scheduler Example

+ +

+Here is an example showing how simple it is to implement a cron-style scheduler by +using the Camel Quartz component in Akka. +

+

+Open MyQuartzActor.java. +

+

+The example creates a "timer" actor which fires a message every 2 +seconds. +

+ +

+For more information about the Camel Quartz component, see here: +http://camel.apache.org/quartz.html +

+ +
+ + + diff --git a/akka-samples/akka-sample-camel-scala/.gitignore b/akka-samples/akka-sample-camel-scala/.gitignore new file mode 100644 index 0000000000..660c959e44 --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/.gitignore @@ -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 \ No newline at end of file diff --git a/akka-samples/akka-sample-camel-scala/LICENSE b/akka-samples/akka-sample-camel-scala/LICENSE new file mode 100644 index 0000000000..a02154466b --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/LICENSE @@ -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. diff --git a/akka-samples/akka-sample-camel-scala/activator.properties b/akka-samples/akka-sample-camel-scala/activator.properties new file mode 100644 index 0000000000..be391d3dce --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/activator.properties @@ -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 diff --git a/akka-samples/akka-sample-camel-scala/build.sbt b/akka-samples/akka-sample-camel-scala/build.sbt new file mode 100644 index 0000000000..161a8588ee --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/build.sbt @@ -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" +) + diff --git a/akka-samples/akka-sample-camel-scala/project/build.properties b/akka-samples/akka-sample-camel-scala/project/build.properties new file mode 100644 index 0000000000..0974fce44d --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/project/build.properties @@ -0,0 +1 @@ +sbt.version=0.13.0 diff --git a/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/CustomRouteExample.scala b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/CustomRouteExample.scala new file mode 100644 index 0000000000..c606f7832f --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/CustomRouteExample.scala @@ -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) + } + }) + } + } + +} diff --git a/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/HttpExample.scala b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/HttpExample.scala new file mode 100644 index 0000000000..f2ced742b5 --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/HttpExample.scala @@ -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 + } + } + +} diff --git a/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/QuartzExample.scala b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/QuartzExample.scala new file mode 100644 index 0000000000..3a02a5be08 --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/src/main/scala/sample/camel/QuartzExample.scala @@ -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) + + } + + } + +} diff --git a/akka-samples/akka-sample-camel-scala/tutorial/camel-async-interact.png b/akka-samples/akka-sample-camel-scala/tutorial/camel-async-interact.png new file mode 100644 index 0000000000..55a2a4505b Binary files /dev/null and b/akka-samples/akka-sample-camel-scala/tutorial/camel-async-interact.png differ diff --git a/akka-samples/akka-sample-camel-scala/tutorial/camel-async-sequence.png b/akka-samples/akka-sample-camel-scala/tutorial/camel-async-sequence.png new file mode 100644 index 0000000000..416c5a181b Binary files /dev/null and b/akka-samples/akka-sample-camel-scala/tutorial/camel-async-sequence.png differ diff --git a/akka-samples/akka-sample-camel-scala/tutorial/camel-custom-route.png b/akka-samples/akka-sample-camel-scala/tutorial/camel-custom-route.png new file mode 100644 index 0000000000..efacdb8f82 Binary files /dev/null and b/akka-samples/akka-sample-camel-scala/tutorial/camel-custom-route.png differ diff --git a/akka-samples/akka-sample-camel-scala/tutorial/index.html b/akka-samples/akka-sample-camel-scala/tutorial/index.html new file mode 100644 index 0000000000..c396ffa4ad --- /dev/null +++ b/akka-samples/akka-sample-camel-scala/tutorial/index.html @@ -0,0 +1,161 @@ + + + Akka Camel Samples with Scala + + + + +
+

+This tutorial contains 3 samples of +Akka Camel. +

+ +
    +
  • Asynchronous routing and transformation
  • +
  • Custom Camel route
  • +
  • Quartz scheduler
  • +
+ +
+ +
+ +

Asynchronous routing and transformation

+ +

+This example demonstrates how to implement consumer and producer actors that +support + +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, go to the Run +tab, and start the application main class sample.camel.HttpExample if it's not already started. +Then 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. +

+ + + +

+Implementing the example actor classes and wiring them together is rather easy +as shown in HttpExample.scala. +

+ + +

+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. +

+ + + +
+
+ +

Custom Camel route example

+ +

+This section also demonstrates the combined usage of a +RouteProducer +and a RouteConsumer +actor as well as the inclusion of a +custom Camel route. +The following figure gives an overview. +

+ + + +
    +
  • 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 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 this example, go to the Run +tab, and start the application main class sample.camel.CustomRouteExample +

+ +

+POST a message to http://localhost:8877/camel/welcome. +

+ +

+   curl -H "Content-Type: text/plain" -d "Anke" http://localhost:8877/camel/welcome
+
+ +

+The response should be: +

+ +

+   Welcome - Anke -
+
+ +
+
+ +

Quartz Scheduler Example

+ +

+Here is an example showing how simple it is to implement a cron-style scheduler by +using the Camel Quartz component in Akka. +

+

+Open QuartzExample.scala. +

+

+The example creates a "timer" actor which fires a message every 2 +seconds. +

+ +

+For more information about the Camel Quartz component, see here: +http://camel.apache.org/quartz.html +

+ +
+ + + diff --git a/akka-samples/akka-sample-camel/README.md b/akka-samples/akka-sample-camel/README.md deleted file mode 100644 index d71806b0f9..0000000000 --- a/akka-samples/akka-sample-camel/README.md +++ /dev/null @@ -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). diff --git a/akka-samples/akka-sample-camel/src/main/scala/AsyncRouteAndTransform.scala b/akka-samples/akka-sample-camel/src/main/scala/AsyncRouteAndTransform.scala deleted file mode 100644 index 85dff9f064..0000000000 --- a/akka-samples/akka-sample-camel/src/main/scala/AsyncRouteAndTransform.scala +++ /dev/null @@ -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", "AKKA") - // 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 - } -} - diff --git a/akka-samples/akka-sample-camel/src/main/scala/SimpleFileConsumer.scala b/akka-samples/akka-sample-camel/src/main/scala/SimpleFileConsumer.scala deleted file mode 100644 index 5b96afed2c..0000000000 --- a/akka-samples/akka-sample-camel/src/main/scala/SimpleFileConsumer.scala +++ /dev/null @@ -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])) - } -} diff --git a/akka-samples/akka-sample-main-java/activator.properties b/akka-samples/akka-sample-main-java/activator.properties index 26d450b5b1..c980185eb2 100644 --- a/akka-samples/akka-sample-main-java/activator.properties +++ b/akka-samples/akka-sample-main-java/activator.properties @@ -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 diff --git a/akka-samples/akka-sample-main-scala/activator.properties b/akka-samples/akka-sample-main-scala/activator.properties index e15e7c3dc9..733461e341 100644 --- a/akka-samples/akka-sample-main-scala/activator.properties +++ b/akka-samples/akka-sample-main-scala/activator.properties @@ -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 diff --git a/project/AkkaBuild.scala b/project/AkkaBuild.scala index 5303027f20..86df5e9518 100644 --- a/project/AkkaBuild.scala +++ b/project/AkkaBuild.scala @@ -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) )