From c71987f4a7da496df7ccbcbb206aa54c841da3fe Mon Sep 17 00:00:00 2001 From: Thibaut Robert Date: Fri, 14 Feb 2014 16:14:04 +0100 Subject: [PATCH] +cam #3885 Add the ability to use an external camel context --- akka-camel/src/main/resources/reference.conf | 5 ++++ .../src/main/scala/akka/camel/Camel.scala | 15 ++++++++--- .../scala/akka/camel/ContextProvider.scala | 27 +++++++++++++++++++ .../akka/camel/internal/DefaultCamel.scala | 6 ++--- .../scala/akka/camel/CamelConfigSpec.scala | 4 +++ akka-docs/rst/java/camel.rst | 6 +++++ akka-docs/rst/scala/camel.rst | 6 +++++ 7 files changed, 62 insertions(+), 7 deletions(-) create mode 100644 akka-camel/src/main/scala/akka/camel/ContextProvider.scala diff --git a/akka-camel/src/main/resources/reference.conf b/akka-camel/src/main/resources/reference.conf index 12bed5c28b..89cf9c78b8 100644 --- a/akka-camel/src/main/resources/reference.conf +++ b/akka-camel/src/main/resources/reference.conf @@ -7,6 +7,11 @@ akka { camel { + # FQCN of the ContextProvider to be used to create or locate a CamelContext + # it must implement akka.camel.ContextProvider and have a no-arg constructor + # the built-in default create a fresh DefaultCamelContext + context-provider = akka.camel.DefaultContextProvider + # Whether JMX should be enabled or disabled for the Camel Context jmx = off # enable/disable streaming cache on the Camel Context diff --git a/akka-camel/src/main/scala/akka/camel/Camel.scala b/akka-camel/src/main/scala/akka/camel/Camel.scala index 8fbed4ac2c..7f747eb0bc 100644 --- a/akka-camel/src/main/scala/akka/camel/Camel.scala +++ b/akka-camel/src/main/scala/akka/camel/Camel.scala @@ -11,8 +11,8 @@ import org.apache.camel.ProducerTemplate import org.apache.camel.impl.DefaultCamelContext import org.apache.camel.model.RouteDefinition import com.typesafe.config.Config -import scala.concurrent.duration.{ Duration, FiniteDuration } -import java.util.concurrent.TimeUnit._ +import scala.concurrent.duration.FiniteDuration +import scala.collection.immutable /** * Camel trait encapsulates the underlying camel machinery. @@ -105,8 +105,17 @@ class CamelSettings private[camel] (config: Config, dynamicAccess: DynamicAccess (s: String, r: RouteDefinition) ⇒ conversions.get(s).fold(r)(r.convertBodyTo) } - + /** + * Configured setting, determine the class used to load/retrive the instance of the Camel Context + */ + final val ContextProvider: ContextProvider = { + val fqcn = config.getString("akka.camel.context-provider") + dynamicAccess.createInstanceFor[ContextProvider](fqcn, immutable.Seq.empty).recover { + case e ⇒ throw new ConfigurationException("Could not find/load Context Provider class [" + fqcn + "]", e) + }.get + } } + /** * This class can be used to get hold of an instance of the Camel class bound to the actor system. *

For example: diff --git a/akka-camel/src/main/scala/akka/camel/ContextProvider.scala b/akka-camel/src/main/scala/akka/camel/ContextProvider.scala new file mode 100644 index 0000000000..fe648d1000 --- /dev/null +++ b/akka-camel/src/main/scala/akka/camel/ContextProvider.scala @@ -0,0 +1,27 @@ +/** + * Copyright (C) 2009-2014 Typesafe Inc. + */ +package akka.camel + +import akka.actor.ExtendedActorSystem +import org.apache.camel.impl.DefaultCamelContext + +/** + * Implement this interface in order to inject a specific CamelContext in a system + * An instance of this class must be instantiable using a no-arg constructor. + */ +trait ContextProvider { + /** + * Retrieve or create a Camel Context for the given actor system + * Called once per actor system + */ + def getContext(system: ExtendedActorSystem): DefaultCamelContext +} + +/** + * Default implementation of [[akka.camel.ContextProvider]] + * Provides a new DefaultCamelContext per actor system + */ +final class DefaultContextProvider extends ContextProvider { + override def getContext(system: ExtendedActorSystem) = new DefaultCamelContext +} \ No newline at end of file diff --git a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala b/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala index 12b35710b9..22d4b88d66 100644 --- a/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala +++ b/akka-camel/src/main/scala/akka/camel/internal/DefaultCamel.scala @@ -15,9 +15,7 @@ import org.apache.camel.ProducerTemplate import scala.concurrent.{ Future, ExecutionContext } import akka.util.Timeout import akka.pattern.ask -import java.io.InputStream -import org.apache.camel.model.RouteDefinition -import akka.actor.{ ExtendedActorSystem, ActorRef, Props, ActorSystem } +import akka.actor.{ ExtendedActorSystem, ActorRef, Props } /** * INTERNAL API @@ -33,7 +31,7 @@ private[camel] class DefaultCamel(val system: ExtendedActorSystem) extends Camel private[camel] implicit val log = Logging(system, "Camel") lazy val context: DefaultCamelContext = { - val ctx = new DefaultCamelContext + val ctx = settings.ContextProvider.getContext(system) if (!settings.JmxStatistics) ctx.disableJMX() ctx.setName(system.name) ctx.setStreamCaching(settings.StreamingCache) diff --git a/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala b/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala index be3a360c09..139a6594d6 100644 --- a/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala +++ b/akka-camel/src/test/scala/akka/camel/CamelConfigSpec.scala @@ -46,6 +46,10 @@ class CamelConfigSpec extends WordSpec with Matchers { conversions.getString("file") should be("java.io.InputStream") conversions.entrySet.size should be(1) } + + "have correct Context Provider" in { + settings.ContextProvider.isInstanceOf[DefaultContextProvider] should be(true) + } } } diff --git a/akka-docs/rst/java/camel.rst b/akka-docs/rst/java/camel.rst index 7be0c5aad4..d4167dc3cb 100644 --- a/akka-docs/rst/java/camel.rst +++ b/akka-docs/rst/java/camel.rst @@ -89,6 +89,12 @@ Below you can see how you can get access to these Apache Camel objects. One ``CamelExtension`` is only loaded once for every one ``ActorSystem``, which makes it safe to call the ``CamelExtension`` at any point in your code to get to the Apache Camel objects associated with it. There is one `CamelContext`_ and one `ProducerTemplate`_ for every one ``ActorSystem`` that uses a ``CamelExtension``. +By Default, a new `CamelContext`_ is created when the ``CamelExtension`` starts. If you want to inject your own context instead, +you can implement the `ContextProvider`_ interface and add the FQCN of your implementation in the config, as the value of the "akka.camel.context-provider". +This interface define a single method ``getContext()`` used to load the `CamelContext`_. + +.. _ContextProvider: @github@/akka-camel/src/main/scala/akka/camel/ContextProvider.scala + Below an example on how to add the ActiveMQ component to the `CamelContext`_, which is required when you would like to use the ActiveMQ component. .. includecode:: code/docs/camel/CamelExtensionTest.java#CamelExtensionAddComponent diff --git a/akka-docs/rst/scala/camel.rst b/akka-docs/rst/scala/camel.rst index a3f94baf8b..4c15c93b95 100644 --- a/akka-docs/rst/scala/camel.rst +++ b/akka-docs/rst/scala/camel.rst @@ -88,6 +88,12 @@ Below you can see how you can get access to these Apache Camel objects. One ``CamelExtension`` is only loaded once for every one ``ActorSystem``, which makes it safe to call the ``CamelExtension`` at any point in your code to get to the Apache Camel objects associated with it. There is one `CamelContext`_ and one `ProducerTemplate`_ for every one ``ActorSystem`` that uses a ``CamelExtension``. +By Default, a new `CamelContext`_ is created when the ``CamelExtension`` starts. If you want to inject your own context instead, +you can extend the `ContextProvider`_ trait and add the FQCN of your implementation in the config, as the value of the "akka.camel.context-provider". +This interface define a single method ``getContext`` used to load the `CamelContext`_. + +.. _ContextProvider: @github@/akka-camel/src/main/scala/akka/camel/ContextProvider.scala + Below an example on how to add the ActiveMQ component to the `CamelContext`_, which is required when you would like to use the ActiveMQ component. .. includecode:: code/docs/camel/Introduction.scala#CamelExtensionAddComponent