diff --git a/akka-docs/dev/team.rst b/akka-docs/dev/team.rst index 36e0cd1339..8c70e016d2 100644 --- a/akka-docs/dev/team.rst +++ b/akka-docs/dev/team.rst @@ -1,7 +1,9 @@ + .. _team: -Team -===== +###### + Team +###### =================== ========================== ==================================== Name Role Email diff --git a/akka-docs/java/code/akka/docs/extension/ExtensionDocTest.scala b/akka-docs/java/code/akka/docs/extension/ExtensionDocTest.scala new file mode 100644 index 0000000000..4cd5014863 --- /dev/null +++ b/akka-docs/java/code/akka/docs/extension/ExtensionDocTest.scala @@ -0,0 +1,5 @@ +package akka.docs.extension + +import org.scalatest.junit.JUnitSuite + +class ExtensionDocTest extends ExtensionDocTestBase with JUnitSuite diff --git a/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java b/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java new file mode 100644 index 0000000000..2d8f914902 --- /dev/null +++ b/akka-docs/java/code/akka/docs/extension/ExtensionDocTestBase.java @@ -0,0 +1,70 @@ +package akka.docs.extension; + +//#imports +import akka.actor.*; +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); + + //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(); + } + } + + //This will be the identifier of our CountExtension + public final static CountExtensionId CountExtension = new CountExtensionId(); + //#extensionid + + //#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(); + } + } + //#extension-usage-actor + + + @Test public void demonstrateHowToCreateAndUseAnAkkaExtensionInJava() { + final ActorSystem system = null; + try { + //#extension-usage + CountExtension.get(system).increment(); + //#extension-usage + } catch(Exception e) { + //do nothing + } + } + +} diff --git a/akka-docs/java/extending-akka.rst b/akka-docs/java/extending-akka.rst new file mode 100644 index 0000000000..7cc46cc93d --- /dev/null +++ b/akka-docs/java/extending-akka.rst @@ -0,0 +1,63 @@ +.. _extending-akka: + +Akka Extensions +=============== + +.. sidebar:: Contents + + .. contents:: :local: + +If you want to add features to Akka, there is a very elegant, but powerful mechanism for doing so. +It's called Akka Extensions and is comprised of 2 basic components: an ``Extension`` and an ``ExtensionId``. + +Extensions will only be loaded once per ``ActorSystem``, which will be managed by Akka. +You can choose to have your Extension loaded on-demand or at ``ActorSystem`` creation time through the Akka configuration. +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. + +First, we define what our ``Extension`` should do: + +.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java + :include: imports,extension + +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 + +Wicked! Now all we need to do is to actually use it: + +.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java + :include: extension-usage + +Or from inside of an Akka Actor: + +.. includecode:: code/akka/docs/extension/ExtensionDocTestBase.java + :include: extension-usage-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? \ No newline at end of file diff --git a/akka-docs/java/index.rst b/akka-docs/java/index.rst index 93a975deb8..041dd289a5 100644 --- a/akka-docs/java/index.rst +++ b/akka-docs/java/index.rst @@ -15,3 +15,4 @@ Java API fault-tolerance dispatchers routing + extending-akka diff --git a/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala b/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala new file mode 100644 index 0000000000..58f9639559 --- /dev/null +++ b/akka-docs/scala/code/akka/docs/extension/ExtensionDocSpec.scala @@ -0,0 +1,74 @@ +package akka.docs.extension + +import org.scalatest.WordSpec +import org.scalatest.matchers.MustMatchers + +//#imports +import akka.actor._ +import java.util.concurrent.atomic.AtomicLong + +//#imports + +//#extension +class CountExtensionImpl extends Extension { + //Since this Extension is a shared instance + // per ActorSystem we need to be threadsafe + private val counter = new AtomicLong(0) + + //This is the operation this Extension provides + def increment() = counter.incrementAndGet() +} +//#extension + +//#extensionid +object CountExtension + extends ExtensionId[CountExtensionImpl] + with ExtensionIdProvider { + //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 + override def lookup = CountExtension + + //This method will be called by Akka + // to instantiate our Extension + override def createExtension(system: ActorSystemImpl) = new CountExtensionImpl +} +//#extensionid + +//#extension-usage-actor +import akka.actor.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 + } + } + +} diff --git a/akka-docs/scala/extending-akka.rst b/akka-docs/scala/extending-akka.rst new file mode 100644 index 0000000000..a13326b626 --- /dev/null +++ b/akka-docs/scala/extending-akka.rst @@ -0,0 +1,53 @@ +.. _extending-akka: + +Akka Extensions +=============== + +.. sidebar:: Contents + + .. contents:: :local: + + +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 + +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 + +Wicked! Now all we need to do is to actually use it: + +.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala + :include: extension-usage + +Or from inside of an Akka Actor: + +.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala + :include: extension-usage-actor + +You can also hide extension behind traits: + +.. includecode:: code/akka/docs/extension/ExtensionDocSpec.scala + :include: extension-usage-actor-trait + +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``. + +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? \ No newline at end of file diff --git a/akka-docs/scala/index.rst b/akka-docs/scala/index.rst index 1a8a61a034..742dc04ea9 100644 --- a/akka-docs/scala/index.rst +++ b/akka-docs/scala/index.rst @@ -17,3 +17,4 @@ Scala API routing fsm testing + extending-akka