diff --git a/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java b/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java index dfb3e9230e..812e79e287 100644 --- a/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java +++ b/akka-actor-tests/src/test/java/akka/actor/JavaExtension.java @@ -16,15 +16,13 @@ import static org.junit.Assert.*; public class JavaExtension { - static class Provider implements ExtensionIdProvider { + static class TestExtensionId extends AbstractExtensionId implements ExtensionIdProvider { + public final static TestExtensionId TestExtensionProvider = new TestExtensionId(); + public ExtensionId lookup() { - return defaultInstance; + return TestExtensionId.TestExtensionProvider; } - } - public final static TestExtensionId defaultInstance = new TestExtensionId(); - - static class TestExtensionId extends AbstractExtensionId { public TestExtension createExtension(ActorSystemImpl i) { return new TestExtension(i); } @@ -37,11 +35,13 @@ public class JavaExtension { system = i; } } - + static class OtherExtension implements Extension { - static final ExtensionKey key = new ExtensionKey(OtherExtension.class) {}; + static final ExtensionKey key = new ExtensionKey(OtherExtension.class) { + }; public final ActorSystemImpl system; + public OtherExtension(ActorSystemImpl i) { system = i; } @@ -51,8 +51,8 @@ public class JavaExtension { @BeforeClass public static void beforeAll() { - Config c = ConfigFactory.parseString("akka.extensions = [ \"akka.actor.JavaExtension$Provider\" ]").withFallback( - AkkaSpec.testConf()); + Config c = ConfigFactory.parseString("akka.extensions = [ \"akka.actor.JavaExtension$TestExtensionId\" ]") + .withFallback(AkkaSpec.testConf()); system = ActorSystem.create("JavaExtension", c); } @@ -64,10 +64,10 @@ public class JavaExtension { @Test public void mustBeAccessible() { - assertSame(system.extension(defaultInstance).system, system); - assertSame(defaultInstance.apply(system).system, system); + assertSame(system.extension(TestExtensionId.TestExtensionProvider).system, system); + assertSame(TestExtensionId.TestExtensionProvider.apply(system).system, system); } - + @Test public void mustBeAdHoc() { assertSame(OtherExtension.key.apply(system).system, system); diff --git a/akka-docs/general/configuration.rst b/akka-docs/general/configuration.rst index 3cb046d364..8109e7a358 100644 --- a/akka-docs/general/configuration.rst +++ b/akka-docs/general/configuration.rst @@ -189,15 +189,15 @@ before or after using them to construct an actor system: Welcome to Scala version 2.9.1.final (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_27). Type in expressions to have them evaluated. Type :help for more information. - + scala> import com.typesafe.config._ import com.typesafe.config._ - + scala> ConfigFactory.parseString("a.b=12") res0: com.typesafe.config.Config = Config(SimpleConfigObject({"a" : {"b" : 12}})) - + scala> res0.root.render - res1: java.lang.String = + res1: java.lang.String = { # String: 1 "a" : { @@ -217,3 +217,12 @@ and parsed by the actor system can be displayed like this: println(system.settings()); // this is a shortcut for system.settings().config().root().render() + +Application specific settings +----------------------------- + +The configuration can also be used for application specific settings. +A good practice is to place those settings in an Extension, as described in: + + * Scala API: :ref:`extending-akka-scala.settings` + * Java API: :ref:`extending-akka-java.settings` diff --git a/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java b/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java index dbc704a2b2..6d62eb5bb8 100644 --- a/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java +++ b/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java @@ -9,63 +9,65 @@ import java.util.concurrent.atomic.AtomicLong; //#imports -import org.junit.After; -import org.junit.Before; import org.junit.Test; -import static org.junit.Assert.*; public class ExtensionDocTestBase { - //#extension - public static class CountExtensionImpl implements Extension { - //Since this Extension is a shared instance - // per ActorSystem we need to be threadsafe - private final AtomicLong counter = new AtomicLong(0); + //#extension + public static class CountExtensionImpl implements Extension { + //Since this Extension is a shared instance + // per ActorSystem we need to be threadsafe + private final AtomicLong counter = new AtomicLong(0); - //This is the operation this Extension provides - public long increment() { - return counter.incrementAndGet(); - } + //This is the operation this Extension provides + public long increment() { + return counter.incrementAndGet(); } - //#extension + } - //#extensionid - static class CountExtensionId extends AbstractExtensionId { - //This method will be called by Akka - // to instantiate our Extension - public CountExtensionImpl createExtension(ActorSystemImpl i) { - return new CountExtensionImpl(); - } - } + //#extension + //#extensionid + public static class CountExtension extends AbstractExtensionId implements ExtensionIdProvider { //This will be the identifier of our CountExtension - public final static CountExtensionId CountExtension = new CountExtensionId(); - //#extensionid + public final static CountExtension CountExtensionProvider = new CountExtension(); - //#extensionid-provider - static class CountExtensionIdProvider implements ExtensionIdProvider { - public CountExtensionId lookup() { - return CountExtension; //The public static final - } - } - //#extensionid-provider - - //#extension-usage-actor - static class MyActor extends UntypedActor { - public void onReceive(Object msg) { - CountExtension.get(getContext().system()).increment(); - } + //The lookup method is required by ExtensionIdProvider, + // so we return ourselves here, this allows us + // to configure our extension to be loaded when + // the ActorSystem starts up + public CountExtension lookup() { + return CountExtension.CountExtensionProvider; //The public static final } - //#extension-usage-actor + //This method will be called by Akka + // to instantiate our Extension + public CountExtensionImpl createExtension(ActorSystemImpl system) { + return new CountExtensionImpl(); + } + } - @Test public void demonstrateHowToCreateAndUseAnAkkaExtensionInJava() { + //#extensionid + + //#extension-usage-actor + public static class MyActor extends UntypedActor { + public void onReceive(Object msg) { + // typically you would use static import of CountExtension.CountExtensionProvider field + CountExtension.CountExtensionProvider.get(getContext().system()).increment(); + } + } + + //#extension-usage-actor + + @Test + public void demonstrateHowToCreateAndUseAnAkkaExtensionInJava() { final ActorSystem system = null; try { //#extension-usage - CountExtension.get(system).increment(); + // typically you would use static import of CountExtension.CountExtensionProvider field + CountExtension.CountExtensionProvider.get(system).increment(); //#extension-usage - } catch(Exception e) { + } catch (Exception e) { //do nothing } } diff --git a/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTest.scala b/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTest.scala new file mode 100644 index 0000000000..0979c00d4f --- /dev/null +++ b/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTest.scala @@ -0,0 +1,8 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ +package akka.docs.extension + +import org.scalatest.junit.JUnitSuite + +class SettingsExtensionDocTest extends SettingsExtensionDocTestBase with JUnitSuite diff --git a/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTestBase.java b/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTestBase.java new file mode 100644 index 0000000000..6ca1c371d9 --- /dev/null +++ b/akka-docs/java/code/akka/docs/extension/SettingsExtensionDocTestBase.java @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ +package akka.docs.extension; + +//#imports +import akka.actor.Extension; +import akka.actor.AbstractExtensionId; +import akka.actor.ExtensionIdProvider; +import akka.actor.ActorSystem; +import akka.actor.ActorSystemImpl; +import akka.util.Duration; +import com.typesafe.config.Config; +import java.util.concurrent.TimeUnit; + +//#imports + +import akka.actor.UntypedActor; +import org.junit.Test; + +public class SettingsExtensionDocTestBase { + + //#extension + public static class SettingsImpl implements Extension { + + public final String DB_URI; + public final Duration CIRCUIT_BREAKER_TIMEOUT; + + public SettingsImpl(Config config) { + DB_URI = config.getString(config.getString("myapp.db.uri")); + CIRCUIT_BREAKER_TIMEOUT = Duration.create(config.getMilliseconds("myapp.circuit-breaker.timeout"), + TimeUnit.MILLISECONDS); + } + + } + + //#extension + + //#extensionid + public static class Settings extends AbstractExtensionId implements ExtensionIdProvider { + public final static Settings SettingsProvider = new Settings(); + + public Settings lookup() { + return Settings.SettingsProvider; + } + + public SettingsImpl createExtension(ActorSystemImpl system) { + return new SettingsImpl(system.settings().config()); + } + } + + //#extensionid + + //#extension-usage-actor + public static class MyActor extends UntypedActor { + // typically you would use static import of CountExtension.CountExtensionProvider field + final SettingsImpl settings = Settings.SettingsProvider.get(getContext().system()); + Connection connection = connect(settings.DB_URI, settings.CIRCUIT_BREAKER_TIMEOUT); + + //#extension-usage-actor + + public Connection connect(String dbUri, Duration circuitBreakerTimeout) { + return new Connection(); + } + + public void onReceive(Object msg) { + } + + } + + public static class Connection { + } + + @Test + public void demonstrateHowToCreateAndUseAnAkkaExtensionInJava() { + final ActorSystem system = null; + try { + //#extension-usage + // typically you would use static import of CountExtension.CountExtensionProvider field + String dbUri = Settings.SettingsProvider.get(system).DB_URI; + //#extension-usage + } catch (Exception e) { + //do nothing + } + } + +} diff --git a/akka-docs/java/extending-akka.rst b/akka-docs/java/extending-akka.rst index edbea859b1..ac60147881 100644 --- a/akka-docs/java/extending-akka.rst +++ b/akka-docs/java/extending-akka.rst @@ -1,7 +1,8 @@ .. _extending-akka-java: -Akka Extensions -=============== +######################## + Akka Extensions (Java) +######################## .. sidebar:: Contents @@ -15,13 +16,13 @@ You can choose to have your Extension loaded on-demand or at ``ActorSystem`` cre Details on how to make that happens are below, in the "Loading from Configuration" section. .. warning:: - + Since an extension is a way to hook into Akka itself, the implementor of the extension needs to ensure the thread safety of his/her extension. Building an Extension ---------------------- +===================== So let's create a sample extension that just lets us count the number of times something has happened. @@ -33,7 +34,7 @@ First, we define what our ``Extension`` should do: Then we need to create an ``ExtensionId`` for our extension so we can grab ahold of it. .. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java - :include: imports,extensionid + :include: imports,extensionid Wicked! Now all we need to do is to actually use it: @@ -48,16 +49,37 @@ Or from inside of an Akka Actor: That's all there is to it! Loading from Configuration --------------------------- +========================== To be able to load extensions from your Akka configuration you must add FQCNs of implementations of either ``ExtensionId`` or ``ExtensionIdProvider`` in the "akka.extensions" section of the config you provide to your ``ActorSystem``. -.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java - :include: extensionid-provider - Applicability -------------- +============= The sky is the limit! By the way, did you know that Akka's ``Typed Actors``, ``Serialization`` and other features are implemented as Akka Extensions? + +.. _extending-akka-java.settings: + +Application specific settings +----------------------------- + +The :ref:`configuration` can be used for application specific settings. A good practice is to place those settings in an Extension. + +Sample configuration: + +.. includecode:: ../scala/code/akka/docs/extension/SettingsExtensionDocSpec.scala + :include: config + +The ``Extension``: + +.. includecode:: code/akka/docs/extension/SettingsExtensionDocTestBase.java + :include: imports,extension,extensionid + + +Use it: + +.. includecode:: code/akka/docs/extension/SettingsExtensionDocTestBase.java + :include: extension-usage-actor + diff --git a/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala b/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala index e9ab9ac8e1..1f4d777ad9 100644 --- a/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala +++ b/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala @@ -3,16 +3,13 @@ */ package akka.docs.extension -import org.scalatest.WordSpec -import org.scalatest.matchers.MustMatchers - -//#imports -import akka.actor._ import java.util.concurrent.atomic.AtomicLong - -//#imports +import akka.actor.Actor +import akka.testkit.AkkaSpec //#extension +import akka.actor.Extension + class CountExtensionImpl extends Extension { //Since this Extension is a shared instance // per ActorSystem we need to be threadsafe @@ -24,6 +21,10 @@ class CountExtensionImpl extends Extension { //#extension //#extensionid +import akka.actor.ExtensionId +import akka.actor.ExtensionIdProvider +import akka.actor.ActorSystemImpl + object CountExtension extends ExtensionId[CountExtensionImpl] with ExtensionIdProvider { @@ -39,39 +40,37 @@ object CountExtension } //#extensionid -//#extension-usage-actor -import akka.actor.Actor +object ExtensionDocSpec { + //#extension-usage-actor -class MyActor extends Actor { - def receive = { - case someMessage ⇒ - CountExtension(context.system).increment() - } -} -//#extension-usage-actor - -//#extension-usage-actor-trait -import akka.actor.Actor - -trait Counting { self: Actor ⇒ - def increment() = CountExtension(context.system).increment() -} -class MyCounterActor extends Actor with Counting { - def receive = { - case someMessage ⇒ increment() - } -} -//#extension-usage-actor-trait - -class ExtensionDocSpec extends WordSpec with MustMatchers { - - "demonstrate how to create an extension in Scala" in { - val system: ActorSystem = null - intercept[Exception] { - //#extension-usage - CountExtension(system).increment - //#extension-usage + class MyActor extends Actor { + def receive = { + case someMessage ⇒ + CountExtension(context.system).increment() } } + //#extension-usage-actor + + //#extension-usage-actor-trait + + trait Counting { self: Actor ⇒ + def increment() = CountExtension(context.system).increment() + } + class MyCounterActor extends Actor with Counting { + def receive = { + case someMessage ⇒ increment() + } + } + //#extension-usage-actor-trait +} + +class ExtensionDocSpec extends AkkaSpec { + import ExtensionDocSpec._ + + "demonstrate how to create an extension in Scala" in { + //#extension-usage + CountExtension(system).increment + //#extension-usage + } } diff --git a/akka-docs/scala/code/akka/docs/extension/SettingsExtensionDocSpec.scala b/akka-docs/scala/code/akka/docs/extension/SettingsExtensionDocSpec.scala new file mode 100644 index 0000000000..ed5ec66517 --- /dev/null +++ b/akka-docs/scala/code/akka/docs/extension/SettingsExtensionDocSpec.scala @@ -0,0 +1,78 @@ +/** + * Copyright (C) 2009-2012 Typesafe Inc. + */ +package akka.docs.extension + +//#imports +import akka.actor.Extension +import akka.actor.ExtensionId +import akka.actor.ExtensionIdProvider +import akka.actor.ActorSystemImpl +import akka.util.Duration +import com.typesafe.config.Config +import java.util.concurrent.TimeUnit + +//#imports + +import akka.actor.Actor +import akka.testkit.AkkaSpec + +//#extension +class SettingsImpl(config: Config) extends Extension { + val DbUri: String = config.getString("myapp.db.uri") + val CircuitBreakerTimeout: Duration = Duration(config.getMilliseconds("myapp.circuit-breaker.timeout"), TimeUnit.MILLISECONDS) +} +//#extension + +//#extensionid +object Settings extends ExtensionId[SettingsImpl] with ExtensionIdProvider { + + override def lookup = Settings + + override def createExtension(system: ActorSystemImpl) = new SettingsImpl(system.settings.config) +} +//#extensionid + +object SettingsExtensionDocSpec { + + val config = """ + //#config + myapp { + db { + uri = "mongodb://example1.com:27017,example2.com:27017" + } + circuit-breaker { + timeout = 30 seconds + } + } + //#config + """ + + //#extension-usage-actor + + class MyActor extends Actor { + val settings = Settings(context.system) + val connection = connect(settings.DbUri, settings.CircuitBreakerTimeout) + + //#extension-usage-actor + def receive = { + case someMessage ⇒ + } + + def connect(dbUri: String, circuitBreakerTimeout: Duration) = { + "dummy" + } + } + +} + +class SettingsExtensionDocSpec extends AkkaSpec(SettingsExtensionDocSpec.config) { + + "demonstrate how to create application specific settings extension in Scala" in { + //#extension-usage + val dbUri = Settings(system).DbUri + val circuitBreakerTimeout = Settings(system).CircuitBreakerTimeout + //#extension-usage + } + +} diff --git a/akka-docs/scala/extending-akka.rst b/akka-docs/scala/extending-akka.rst index 6a1655db01..0fe149e0f2 100644 --- a/akka-docs/scala/extending-akka.rst +++ b/akka-docs/scala/extending-akka.rst @@ -1,7 +1,9 @@ .. _extending-akka-scala: -Akka Extensions -=============== +######################### + Akka Extensions (Scala) +######################### + .. sidebar:: Contents @@ -9,19 +11,19 @@ Akka Extensions Building an Extension ---------------------- +===================== So let's create a sample extension that just lets us count the number of times something has happened. First, we define what our ``Extension`` should do: .. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala - :include: imports,extension + :include: extension Then we need to create an ``ExtensionId`` for our extension so we can grab ahold of it. .. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala - :include: imports,extensionid + :include: extensionid Wicked! Now all we need to do is to actually use it: @@ -41,13 +43,37 @@ You can also hide extension behind traits: That's all there is to it! Loading from Configuration --------------------------- +========================== To be able to load extensions from your Akka configuration you must add FQCNs of implementations of either ``ExtensionId`` or ``ExtensionIdProvider`` -in the "akka.extensions" section of the config you provide to your ``ActorSystem``. +in the ``akka.extensions`` section of the config you provide to your ``ActorSystem``. Applicability -------------- +============= The sky is the limit! By the way, did you know that Akka's ``Typed Actors``, ``Serialization`` and other features are implemented as Akka Extensions? + +.. _extending-akka-scala.settings: + +Application specific settings +----------------------------- + +The :ref:`configuration` can be used for application specific settings. A good practice is to place those settings in an Extension. + +Sample configuration: + +.. includecode:: code/akka/docs/extension/SettingsExtensionDocSpec.scala + :include: config + +The ``Extension``: + +.. includecode:: code/akka/docs/extension/SettingsExtensionDocSpec.scala + :include: imports,extension,extensionid + + +Use it: + +.. includecode:: code/akka/docs/extension/SettingsExtensionDocSpec.scala + :include: extension-usage-actor + diff --git a/akka-docs/scala/testing.rst b/akka-docs/scala/testing.rst index 0f80342bc4..fb1513dea4 100644 --- a/akka-docs/scala/testing.rst +++ b/akka-docs/scala/testing.rst @@ -1,8 +1,8 @@ .. _akka-testkit: -##################### -Testing Actor Systems -##################### +############################## +Testing Actor Systems (Scala) +############################## .. toctree:: diff --git a/akka-docs/scala/testkit-example.rst b/akka-docs/scala/testkit-example.rst index 2290cc84af..a87e8fc311 100644 --- a/akka-docs/scala/testkit-example.rst +++ b/akka-docs/scala/testkit-example.rst @@ -1,8 +1,8 @@ .. _testkit-example: -############### -TestKit Example -############### +######################## +TestKit Example (Scala) +######################## Ray Roestenburg's example code from `his blog `_ adapted to work with Akka 1.1.