Merge akka-docs/paradox/scala/actors.md and java/actors.md (#23079)
* Identical contents in scala/actors.md and java/actors.md * Replace java/actors.md with a symlink to scala/actors.md
This commit is contained in:
parent
fb3e42f2e8
commit
c569bdbc7c
5 changed files with 489 additions and 1188 deletions
File diff suppressed because it is too large
Load diff
1
akka-docs/src/main/paradox/java/actors.md
Symbolic link
1
akka-docs/src/main/paradox/java/actors.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../scala/actors.md
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
# Java 8 and Scala Compatibility
|
|
||||||
|
|
||||||
Akka requires that you have [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) or
|
|
||||||
later installed on your machine.
|
|
||||||
|
|
||||||
## Java 8 types
|
|
||||||
|
|
||||||
Starting with Akka 2.4.2 we have begun to introduce Java 8 types (most
|
|
||||||
prominently `java.util.concurrent.CompletionStage` and
|
|
||||||
`java.util.Optional`) where that was possible without breaking binary or
|
|
||||||
source compatibility. Where this was not possible (for example in the return
|
|
||||||
type of `ActorSystem.terminate()`) please refer to the
|
|
||||||
`scala-java8-compat` library that allows easy conversion between the Scala
|
|
||||||
and Java counterparts. The artifact can be included in Maven builds using:
|
|
||||||
|
|
||||||
```
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.scala-lang.modules</groupId>
|
|
||||||
<artifactId>scala-java8-compat_2.11</artifactId>
|
|
||||||
<version>0.7.0</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
We will only be able to seamlessly integrate all functional interfaces once
|
|
||||||
we can rely on Scala 2.12 to provide full interoperability—this will mean that
|
|
||||||
Scala users can directly implement Java Functional Interfaces using lambda syntax
|
|
||||||
as well as that Java users can directly implement Scala functions using lambda
|
|
||||||
syntax.
|
|
||||||
|
|
||||||
## Do not use -optimize Scala compiler flag
|
|
||||||
|
|
||||||
@@@ warning
|
|
||||||
|
|
||||||
Akka has not been compiled or tested with -optimize Scala compiler flag.
|
|
||||||
Strange behavior has been reported by users that have tried it.
|
|
||||||
|
|
||||||
@@@
|
|
||||||
1
akka-docs/src/main/paradox/java/scala-compat.md
Symbolic link
1
akka-docs/src/main/paradox/java/scala-compat.md
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
../scala/scala-compat.md
|
||||||
|
|
@ -24,15 +24,38 @@ and it may also help to read @ref:[Actor References, Paths and Addresses](genera
|
||||||
|
|
||||||
### Defining an Actor class
|
### Defining an Actor class
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
Actors are implemented by extending the `Actor` base trait and implementing the
|
Actors are implemented by extending the `Actor` base trait and implementing the
|
||||||
`receive` method. The `receive` method should define a series of case
|
`receive` method. The `receive` method should define a series of case
|
||||||
statements (which has the type `PartialFunction[Any, Unit]`) that defines
|
statements (which has the type `PartialFunction[Any, Unit]`) that defines
|
||||||
which messages your Actor can handle, using standard Scala pattern matching,
|
which messages your Actor can handle, using standard Scala pattern matching,
|
||||||
along with the implementation of how the messages should be processed.
|
along with the implementation of how the messages should be processed.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
Actor classes are implemented by extending the `AbstractActor` class and setting
|
||||||
|
the “initial behavior” in the constructor by calling the `receive` method in
|
||||||
|
the `AbstractActor`.
|
||||||
|
|
||||||
|
The argument to the `receive` method is a `PartialFunction<Object,BoxedUnit>`
|
||||||
|
that defines which messages your Actor can handle, along with the implementation of
|
||||||
|
how the messages should be processed.
|
||||||
|
|
||||||
|
Don't let the type signature scare you. To allow you to easily build up a partial
|
||||||
|
function there is a builder named `ReceiveBuilder` that you can use.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
Here is an example:
|
Here is an example:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #imports1 #my-actor }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #imports1 #my-actor }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [MyActor.java]($code$/java/jdocs/actor/MyActor.java) { #imports #my-actor }
|
||||||
|
|
||||||
Please note that the Akka Actor `receive` message loop is exhaustive, which
|
Please note that the Akka Actor `receive` message loop is exhaustive, which
|
||||||
is different compared to Erlang and the late Scala Actors. This means that you
|
is different compared to Erlang and the late Scala Actors. This means that you
|
||||||
|
|
@ -46,16 +69,18 @@ Note further that the return type of the behavior defined above is `Unit`; if
|
||||||
the actor shall reply to the received message then this must be done explicitly
|
the actor shall reply to the received message then this must be done explicitly
|
||||||
as explained below.
|
as explained below.
|
||||||
|
|
||||||
The result of the `receive` method is a partial function object, which is
|
The @scala[result of] @java[argument to] the `receive` method is a partial function object, which is
|
||||||
stored within the actor as its “initial behavior”, see [Become/Unbecome](#become-unbecome) for
|
stored within the actor as its “initial behavior”, see [Become/Unbecome](#become-unbecome) for
|
||||||
further information on changing the behavior of an actor after its
|
further information on changing the behavior of an actor after its
|
||||||
construction.
|
construction.
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
#### Here is another example that you can edit and run in the browser:
|
#### Here is another example that you can edit and run in the browser:
|
||||||
|
|
||||||
@@fiddle [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #fiddle_code height=400px extraParams=theme=light&layout=v75 cssStyle=width:100%; }
|
@@fiddle [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #fiddle_code height=400px extraParams=theme=light&layout=v75 cssStyle=width:100%; }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
### Props
|
### Props
|
||||||
|
|
||||||
|
|
@ -65,7 +90,12 @@ creating an actor including associated deployment information (e.g. which
|
||||||
dispatcher to use, see more below). Here are some examples of how to create a
|
dispatcher to use, see more below). Here are some examples of how to create a
|
||||||
`Props` instance.
|
`Props` instance.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-props }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-props }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-props #creating-props }
|
||||||
|
|
||||||
|
|
||||||
The second variant shows how to pass constructor arguments to the
|
The second variant shows how to pass constructor arguments to the
|
||||||
`Actor` being created, but it should only be used outside of actors as
|
`Actor` being created, but it should only be used outside of actors as
|
||||||
|
|
@ -77,7 +107,7 @@ verified during construction of the `Props` object, resulting in an
|
||||||
`IllegalArgumentException` if no or multiple matching constructors are
|
`IllegalArgumentException` if no or multiple matching constructors are
|
||||||
found.
|
found.
|
||||||
|
|
||||||
@@@ note
|
@@@ note { .group-scala }
|
||||||
|
|
||||||
The recommended approach to create the actor `Props` is not supported
|
The recommended approach to create the actor `Props` is not supported
|
||||||
for cases when the actor constructor takes value classes as arguments.
|
for cases when the actor constructor takes value classes as arguments.
|
||||||
|
|
@ -85,8 +115,11 @@ for cases when the actor constructor takes value classes as arguments.
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
#### Dangerous Variants
|
#### Dangerous Variants
|
||||||
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-props-deprecated }
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-props-deprecated }
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #creating-props-deprecated }
|
||||||
|
|
||||||
This method is not recommended to be used within another actor because it
|
This method is not recommended to be used within another actor because it
|
||||||
encourages to close over the enclosing scope, resulting in non-serializable
|
encourages to close over the enclosing scope, resulting in non-serializable
|
||||||
|
|
@ -97,7 +130,7 @@ is completely fine.
|
||||||
|
|
||||||
There were two use-cases for these methods: passing constructor arguments to
|
There were two use-cases for these methods: passing constructor arguments to
|
||||||
the actor—which is solved by the newly introduced
|
the actor—which is solved by the newly introduced
|
||||||
`Props.apply(clazz, args)` method above or the recommended practice
|
@scala[`Props.apply(clazz, args)`] @java[`Props.create(clazz, args)`] method above or the recommended practice
|
||||||
below—and creating actors “on the spot” as anonymous classes. The latter should
|
below—and creating actors “on the spot” as anonymous classes. The latter should
|
||||||
be solved by making these actors named classes instead (if they are not
|
be solved by making these actors named classes instead (if they are not
|
||||||
declared within a top-level `object` then the enclosing instance’s `this`
|
declared within a top-level `object` then the enclosing instance’s `this`
|
||||||
|
|
@ -110,6 +143,8 @@ encapsulation. Never pass an actor’s `this` reference into `Props`!
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
#### Edge cases
|
#### Edge cases
|
||||||
|
|
||||||
There are two edge cases in actor creation with `Props`:
|
There are two edge cases in actor creation with `Props`:
|
||||||
|
|
@ -130,22 +165,33 @@ no matching constructor could be found.
|
||||||
The next section explains the recommended ways to create `Actor` props in a way,
|
The next section explains the recommended ways to create `Actor` props in a way,
|
||||||
which simultaneously safe-guards against these edge cases.
|
which simultaneously safe-guards against these edge cases.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
#### Recommended Practices
|
#### Recommended Practices
|
||||||
|
|
||||||
It is a good idea to provide factory methods on the companion object of each
|
It is a good idea to provide factory methods on the companion object of each
|
||||||
`Actor` which help keeping the creation of suitable `Props` as
|
`Actor` which help keeping the creation of suitable `Props` as
|
||||||
close to the actor definition as possible. This also avoids the pitfalls
|
close to the actor definition as possible. This also avoids the pitfalls
|
||||||
associated with using the `Props.apply(...)` method which takes a by-name
|
associated with using the @scala[`Props.apply(...)`] @java[ `Props.create(...)`] method which takes a by-name
|
||||||
argument, since within a companion object the given code block will not retain
|
argument, since within a companion object the given code block will not retain
|
||||||
a reference to its enclosing scope:
|
a reference to its enclosing scope:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #props-factory }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #props-factory }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #props-factory }
|
||||||
|
|
||||||
Another good practice is to declare what messages an Actor can receive
|
Another good practice is to declare what messages an Actor can receive
|
||||||
in the companion object of the Actor, which makes easier
|
@scala[in the companion object of the Actor]
|
||||||
to know what it can receive:
|
@java[as close to the actor definition as possible (e.g. as static classes inside the Actor or using other suitable class)],
|
||||||
|
which makes easier to know what it can receive:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #messages-in-companion }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #messages-in-companion }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #messages-in-companion }
|
||||||
|
|
||||||
### Creating Actors with Props
|
### Creating Actors with Props
|
||||||
|
|
||||||
|
|
@ -153,13 +199,21 @@ Actors are created by passing a `Props` instance into the
|
||||||
`actorOf` factory method which is available on `ActorSystem` and
|
`actorOf` factory method which is available on `ActorSystem` and
|
||||||
`ActorContext`.
|
`ActorContext`.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #system-actorOf }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #system-actorOf }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-actorRef }
|
||||||
|
|
||||||
Using the `ActorSystem` will create top-level actors, supervised by the
|
Using the `ActorSystem` will create top-level actors, supervised by the
|
||||||
actor system’s provided guardian actor, while using an actor’s context will
|
actor system’s provided guardian actor, while using an actor’s context will
|
||||||
create a child actor.
|
create a child actor.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #context-actorOf }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #context-actorOf }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #context-actorOf }
|
||||||
|
|
||||||
It is recommended to create a hierarchy of children, grand-children and so on
|
It is recommended to create a hierarchy of children, grand-children and so on
|
||||||
such that it fits the logical failure-handling structure of the application,
|
such that it fits the logical failure-handling structure of the application,
|
||||||
|
|
@ -181,6 +235,8 @@ another child to the same parent an `InvalidActorNameException` is thrown.
|
||||||
|
|
||||||
Actors are automatically started asynchronously when created.
|
Actors are automatically started asynchronously when created.
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
#### Value classes as constructor arguments
|
#### Value classes as constructor arguments
|
||||||
|
|
||||||
The recommended way to instantiate actor props uses reflection at runtime
|
The recommended way to instantiate actor props uses reflection at runtime
|
||||||
|
|
@ -192,19 +248,25 @@ calling the constructor manually:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #actor-with-value-class-argument }
|
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #actor-with-value-class-argument }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
### Dependency Injection
|
### Dependency Injection
|
||||||
|
|
||||||
If your Actor has a constructor that takes parameters then those need to
|
If your `Actor` has a constructor that takes parameters then those need to
|
||||||
be part of the `Props` as well, as described [above](Props_). But there
|
be part of the `Props` as well, as described [above](Props_). But there
|
||||||
are cases when a factory method must be used, for example when the actual
|
are cases when a factory method must be used, for example when the actual
|
||||||
constructor arguments are determined by a dependency injection framework.
|
constructor arguments are determined by a dependency injection framework.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-indirectly }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #creating-indirectly }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [DependencyInjectionDocTest.java]($code$/java/jdocs/actor/DependencyInjectionDocTest.java) { #import #creating-indirectly }
|
||||||
|
|
||||||
@@@ warning
|
@@@ warning
|
||||||
|
|
||||||
You might be tempted at times to offer an `IndirectActorProducer`
|
You might be tempted at times to offer an `IndirectActorProducer`
|
||||||
which always returns the same instance, e.g. by using a `lazy val`. This is
|
which always returns the same instance, e.g. by using a @scala[`lazy val`.] @java[static field.] This is
|
||||||
not supported, as it goes against the meaning of an actor restart, which is
|
not supported, as it goes against the meaning of an actor restart, which is
|
||||||
described here: @ref:[What Restarting Means](general/supervision.md#supervision-restart).
|
described here: @ref:[What Restarting Means](general/supervision.md#supervision-restart).
|
||||||
|
|
||||||
|
|
@ -226,7 +288,14 @@ cannot do: receiving multiple replies (e.g. by subscribing an `ActorRef`
|
||||||
to a notification service) and watching other actors’ lifecycle. For these
|
to a notification service) and watching other actors’ lifecycle. For these
|
||||||
purposes there is the `Inbox` class:
|
purposes there is the `Inbox` class:
|
||||||
|
|
||||||
@@snip [ActorDSLSpec.scala]($akka$/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala) { #inbox }
|
Scala
|
||||||
|
: @@snip [ActorDSLSpec.scala]($akka$/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala) { #inbox }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [InboxDocTest.java]($code$/java/jdocs/actor/InboxDocTest.java) { #inbox }
|
||||||
|
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
There is an implicit conversion from inbox to actor reference which means that
|
There is an implicit conversion from inbox to actor reference which means that
|
||||||
in this example the sender reference will be that of the actor hidden away
|
in this example the sender reference will be that of the actor hidden away
|
||||||
|
|
@ -235,10 +304,24 @@ Watching an actor is quite simple as well:
|
||||||
|
|
||||||
@@snip [ActorDSLSpec.scala]($akka$/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala) { #watch }
|
@@snip [ActorDSLSpec.scala]($akka$/akka-actor-tests/src/test/scala/akka/actor/ActorDSLSpec.scala) { #watch }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
The `send` method wraps a normal `tell` and supplies the internal
|
||||||
|
actor’s reference as the sender. This allows the reply to be received on the
|
||||||
|
last line. Watching an actor is quite simple as well:
|
||||||
|
|
||||||
|
@@snip [InboxDocTest.java]($code$/java/jdocs/actor/InboxDocTest.java) { #watch }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
## Actor API
|
## Actor API
|
||||||
|
|
||||||
The `Actor` trait defines only one abstract method, the above mentioned
|
@scala[The `Actor` trait defines only one abstract method, the above mentioned
|
||||||
`receive`, which implements the behavior of the actor.
|
`receive`, which implements the behavior of the actor.]
|
||||||
|
@java[The `AbstractActor` class defines a method called `receive`,
|
||||||
|
that is used to set the “initial behavior” of the actor.]
|
||||||
|
|
||||||
If the current actor behavior does not match a received message,
|
If the current actor behavior does not match a received message,
|
||||||
`unhandled` is called, which by default publishes an
|
`unhandled` is called, which by default publishes an
|
||||||
|
|
@ -249,10 +332,12 @@ actual Debug messages).
|
||||||
|
|
||||||
In addition, it offers:
|
In addition, it offers:
|
||||||
|
|
||||||
* `self` reference to the `ActorRef` of the actor
|
* @scala[`self`] @java[`getSelf()`] reference to the `ActorRef` of the actor
|
||||||
* `sender` reference sender Actor of the last received message, typically used as described in [Actor.Reply](#actor-reply)
|
* @scala[`sender`] @java[`getSender()`] reference sender Actor of the last received message, typically used as described in
|
||||||
*
|
@scala[[Actor.Reply](#actor-reply)]
|
||||||
`supervisorStrategy` user overridable definition the strategy to use for supervising child actors
|
@java[[LambdaActor.Reply](#lambdaactor-reply)]
|
||||||
|
* @scala[`supervisorStrategy`] @java[`supervisorStrategy()`] user overridable definition the strategy to use for supervising child actors
|
||||||
|
|
||||||
This strategy is typically declared inside the actor in order to have access
|
This strategy is typically declared inside the actor in order to have access
|
||||||
to the actor’s internal state within the decider function: since failure is
|
to the actor’s internal state within the decider function: since failure is
|
||||||
communicated as a message sent to the supervisor and processed like other
|
communicated as a message sent to the supervisor and processed like other
|
||||||
|
|
@ -261,26 +346,33 @@ within the actor are available, as is the `sender` reference (which will
|
||||||
be the immediate child reporting the failure; if the original failure
|
be the immediate child reporting the failure; if the original failure
|
||||||
occurred within a distant descendant it is still reported one level up at a
|
occurred within a distant descendant it is still reported one level up at a
|
||||||
time).
|
time).
|
||||||
*
|
|
||||||
`context` exposes contextual information for the actor and the current message, such as:
|
* @scala[`context`] @java[`getContext()`] exposes contextual information for the actor and the current message, such as:
|
||||||
* factory methods to create child actors (`actorOf`)
|
* factory methods to create child actors (`actorOf`)
|
||||||
* system that the actor belongs to
|
* system that the actor belongs to
|
||||||
* parent supervisor
|
* parent supervisor
|
||||||
* supervised children
|
* supervised children
|
||||||
* lifecycle monitoring
|
* lifecycle monitoring
|
||||||
* hotswap behavior stack as described in [Actor.HotSwap](#actor-hotswap)
|
* hotswap behavior stack as described in @scala[[Actor.HotSwap](#actor-hotswap)] @java[[Become/Unbecome](#actor-hotswap)]
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
You can import the members in the `context` to avoid prefixing access with `context.`
|
You can import the members in the `context` to avoid prefixing access with `context.`
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #import-context }
|
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #import-context }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
The remaining visible methods are user-overridable life-cycle hooks which are
|
The remaining visible methods are user-overridable life-cycle hooks which are
|
||||||
described in the following:
|
described in the following:
|
||||||
|
|
||||||
@@snip [Actor.scala]($akka$/akka-actor/src/main/scala/akka/actor/Actor.scala) { #lifecycle-hooks }
|
Scala
|
||||||
|
: @@snip [Actor.scala]($akka$/akka-actor/src/main/scala/akka/actor/Actor.scala) { #lifecycle-hooks }
|
||||||
|
|
||||||
The implementations shown above are the defaults provided by the `Actor`
|
Java
|
||||||
trait.
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #lifecycle-callbacks }
|
||||||
|
|
||||||
|
The implementations shown above are the defaults provided by the @scala[`Actor` trait.] @java[`AbstractActor` class.]
|
||||||
|
|
||||||
<a id="actor-lifecycle"></a>
|
<a id="actor-lifecycle"></a>
|
||||||
### Actor Lifecycle
|
### Actor Lifecycle
|
||||||
|
|
@ -338,7 +430,11 @@ termination (see [Stopping Actors](#stopping-actors)). This service is provided
|
||||||
|
|
||||||
Registering a monitor is easy:
|
Registering a monitor is easy:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #watch }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #watch }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-terminated #watch }
|
||||||
|
|
||||||
It should be noted that the `Terminated` message is generated
|
It should be noted that the `Terminated` message is generated
|
||||||
independent of the order in which registration and termination occur.
|
independent of the order in which registration and termination occur.
|
||||||
|
|
@ -363,7 +459,11 @@ no `Terminated` message for that actor will be processed anymore.
|
||||||
|
|
||||||
Right after starting the actor, its `preStart` method is invoked.
|
Right after starting the actor, its `preStart` method is invoked.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #preStart }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #preStart }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #preStart }
|
||||||
|
|
||||||
This method is called when the actor is first created. During restarts it is
|
This method is called when the actor is first created. During restarts it is
|
||||||
called by the default implementation of `postRestart`, which means that
|
called by the default implementation of `postRestart`, which means that
|
||||||
|
|
@ -436,7 +536,11 @@ actors may look up other actors by specifying absolute or relative
|
||||||
paths—logical or physical—and receive back an `ActorSelection` with the
|
paths—logical or physical—and receive back an `ActorSelection` with the
|
||||||
result:
|
result:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-local }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-local }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #selection-local }
|
||||||
|
|
||||||
@@@ note
|
@@@ note
|
||||||
|
|
||||||
|
|
@ -464,14 +568,18 @@ structure, i.e. the supervisor.
|
||||||
The path elements of an actor selection may contain wildcard patterns allowing for
|
The path elements of an actor selection may contain wildcard patterns allowing for
|
||||||
broadcasting of messages to that section:
|
broadcasting of messages to that section:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-wildcard }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-wildcard }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #selection-wildcard }
|
||||||
|
|
||||||
Messages can be sent via the `ActorSelection` and the path of the
|
Messages can be sent via the `ActorSelection` and the path of the
|
||||||
`ActorSelection` is looked up when delivering each message. If the selection
|
`ActorSelection` is looked up when delivering each message. If the selection
|
||||||
does not match any actors the message will be dropped.
|
does not match any actors the message will be dropped.
|
||||||
|
|
||||||
To acquire an `ActorRef` for an `ActorSelection` you need to send
|
To acquire an `ActorRef` for an `ActorSelection` you need to send
|
||||||
a message to the selection and use the `sender()` reference of the reply from
|
a message to the selection and use the @scala[`sender()`] @java[`getSender()`] reference of the reply from
|
||||||
the actor. There is a built-in `Identify` message that all Actors will
|
the actor. There is a built-in `Identify` message that all Actors will
|
||||||
understand and automatically reply to with a `ActorIdentity` message
|
understand and automatically reply to with a `ActorIdentity` message
|
||||||
containing the `ActorRef`. This message is handled specially by the
|
containing the `ActorRef`. This message is handled specially by the
|
||||||
|
|
@ -480,17 +588,26 @@ actors which are traversed in the sense that if a concrete name lookup fails
|
||||||
negative result is generated. Please note that this does not mean that delivery
|
negative result is generated. Please note that this does not mean that delivery
|
||||||
of that reply is guaranteed, it still is a normal message.
|
of that reply is guaranteed, it still is a normal message.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #identify }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #identify }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-identify #identify }
|
||||||
|
|
||||||
You can also acquire an `ActorRef` for an `ActorSelection` with
|
You can also acquire an `ActorRef` for an `ActorSelection` with
|
||||||
the `resolveOne` method of the `ActorSelection`. It returns a `Future`
|
the `resolveOne` method of the `ActorSelection`. It returns a `Future`
|
||||||
of the matching `ActorRef` if such an actor exists. It is completed with
|
of the matching `ActorRef` if such an actor exists. @java[(see also
|
||||||
|
@ref:[Java 8 and Scala Compatibility](scala-compat.md) for Java compatibility).] It is completed with
|
||||||
failure [[akka.actor.ActorNotFound]] if no such actor exists or the identification
|
failure [[akka.actor.ActorNotFound]] if no such actor exists or the identification
|
||||||
didn't complete within the supplied *timeout*.
|
didn't complete within the supplied `timeout`.
|
||||||
|
|
||||||
Remote actor addresses may also be looked up, if @ref:[remoting](remoting.md) is enabled:
|
Remote actor addresses may also be looked up, if @ref:[remoting](remoting.md) is enabled:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-remote }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #selection-remote }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #selection-remote }
|
||||||
|
|
||||||
An example demonstrating actor look-up is given in @ref:[Remoting Sample](remoting.md#remote-sample).
|
An example demonstrating actor look-up is given in @ref:[Remoting Sample](remoting.md#remote-sample).
|
||||||
|
|
||||||
|
|
@ -498,32 +615,31 @@ An example demonstrating actor look-up is given in @ref:[Remoting Sample](remoti
|
||||||
|
|
||||||
@@@ warning { title=IMPORTANT }
|
@@@ warning { title=IMPORTANT }
|
||||||
|
|
||||||
Messages can be any kind of object but have to be immutable. Scala can’t enforce
|
Messages can be any kind of object but have to be immutable. @scala[Scala] @java[Akka] can’t enforce
|
||||||
immutability (yet) so this has to be by convention. Primitives like String, Int,
|
immutability (yet) so this has to be by convention. @scala[Primitives like String, Int,
|
||||||
Boolean are always immutable. Apart from these the recommended approach is to
|
Boolean are always immutable. Apart from these the recommended approach is to
|
||||||
use Scala case classes which are immutable (if you don’t explicitly expose the
|
use Scala case classes which are immutable (if you don’t explicitly expose the
|
||||||
state) and works great with pattern matching at the receiver side.
|
state) and works great with pattern matching at the receiver side.]
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
Here is an example:
|
Here is an @scala[example:] @java[example of an immutable message:]
|
||||||
|
|
||||||
```scala
|
Scala
|
||||||
// define the case class
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #immutable-message-definition #immutable-message-instantiation }
|
||||||
case class Register(user: User)
|
|
||||||
|
Java
|
||||||
|
: @@snip [ImmutableMessage.java]($code$/java/jdocs/actor/ImmutableMessage.java) { #immutable-message }
|
||||||
|
|
||||||
// create a new case class message
|
|
||||||
val message = Register(user)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Send messages
|
## Send messages
|
||||||
|
|
||||||
Messages are sent to an Actor through one of the following methods.
|
Messages are sent to an Actor through one of the following methods.
|
||||||
|
|
||||||
* `!` means “fire-and-forget”, e.g. send a message asynchronously and return
|
* @scala[`!`] @java[`tell` ] means “fire-and-forget”, e.g. send a message asynchronously and return
|
||||||
immediately. Also known as `tell`.
|
immediately. @scala[Also known as `tell`.]
|
||||||
* `?` sends a message asynchronously and returns a `Future`
|
* @scala[`?`] @java[`ask`] sends a message asynchronously and returns a `Future`
|
||||||
representing a possible reply. Also known as `ask`.
|
representing a possible reply. @scala[Also known as `ask`].
|
||||||
|
|
||||||
Message ordering is guaranteed on a per-sender basis.
|
Message ordering is guaranteed on a per-sender basis.
|
||||||
|
|
||||||
|
|
@ -536,13 +652,27 @@ remoting. So always prefer `tell` for performance, and only `ask` if you must.
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
In all these methods you have the option of passing along your own `ActorRef`.
|
||||||
|
Make it a practice of doing so because it will allow the receiver actors to be able to respond
|
||||||
|
to your message, since the sender reference is sent along with the message.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
<a id="actors-tell-sender"></a>
|
<a id="actors-tell-sender"></a>
|
||||||
### Tell: Fire-forget
|
### Tell: Fire-forget
|
||||||
|
|
||||||
This is the preferred way of sending messages. No blocking waiting for a
|
This is the preferred way of sending messages. No blocking waiting for a
|
||||||
message. This gives the best concurrency and scalability characteristics.
|
message. This gives the best concurrency and scalability characteristics.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #tell }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #tell }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #tell }
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
If invoked from within an Actor, then the sending actor reference will be
|
If invoked from within an Actor, then the sending actor reference will be
|
||||||
implicitly passed along with the message and available to the receiving Actor
|
implicitly passed along with the message and available to the receiving Actor
|
||||||
|
|
@ -552,28 +682,55 @@ to reply to the original sender, by using `sender() ! replyMsg`.
|
||||||
If invoked from an instance that is **not** an Actor the sender will be
|
If invoked from an instance that is **not** an Actor the sender will be
|
||||||
`deadLetters` actor reference by default.
|
`deadLetters` actor reference by default.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
The sender reference is passed along with the message and available within the
|
||||||
|
receiving actor via its `getSender()` method while processing this
|
||||||
|
message. Inside of an actor it is usually `getSelf()` who shall be the
|
||||||
|
sender, but there can be cases where replies shall be routed to some other
|
||||||
|
actor—e.g. the parent—in which the second argument to `tell` would be a
|
||||||
|
different one. Outside of an actor and if no reply is needed the second
|
||||||
|
argument can be `null`; if a reply is needed outside of an actor you can use
|
||||||
|
the ask-pattern described next..
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
<a id="actors-ask"></a>
|
<a id="actors-ask"></a>
|
||||||
### Ask: Send-And-Receive-Future
|
### Ask: Send-And-Receive-Future
|
||||||
|
|
||||||
The `ask` pattern involves actors as well as futures, hence it is offered as
|
The `ask` pattern involves actors as well as futures, hence it is offered as
|
||||||
a use pattern rather than a method on `ActorRef`:
|
a use pattern rather than a method on `ActorRef`:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #ask-pipeTo }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #ask-pipeTo }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-ask #ask-pipe }
|
||||||
|
|
||||||
|
|
||||||
This example demonstrates `ask` together with the `pipeTo` pattern on
|
This example demonstrates `ask` together with the `pipeTo` pattern on
|
||||||
futures, because this is likely to be a common combination. Please note that
|
futures, because this is likely to be a common combination. Please note that
|
||||||
all of the above is completely non-blocking and asynchronous: `ask` produces
|
all of the above is completely non-blocking and asynchronous: `ask` produces
|
||||||
a `Future`, three of which are composed into a new future using the
|
a `Future`, @scala[three] @java[two] of which are composed into a new future using the
|
||||||
for-comprehension and then `pipeTo` installs an `onComplete`-handler on the
|
@scala[for-comprehension and then `pipeTo` installs an `onComplete`-handler on the future to affect]
|
||||||
future to affect the submission of the aggregated `Result` to another
|
@java[`Futures.sequence` and `map` methods and then `pipe` installs an `onComplete`-handler on the future to effect]
|
||||||
actor.
|
the submission of the aggregated `Result` to another actor.
|
||||||
|
|
||||||
Using `ask` will send a message to the receiving Actor as with `tell`, and
|
Using `ask` will send a message to the receiving Actor as with `tell`, and
|
||||||
the receiving actor must reply with `sender() ! reply` in order to complete the
|
the receiving actor must reply with @scala[`sender() ! reply`] @java[`getSender().tell(reply, getSelf())` ] in order to
|
||||||
returned `Future` with a value. The `ask` operation involves creating
|
complete the returned `Future` with a value. The `ask` operation involves creating
|
||||||
an internal actor for handling this reply, which needs to have a timeout after
|
an internal actor for handling this reply, which needs to have a timeout after
|
||||||
which it is destroyed in order not to leak resources; see more below.
|
which it is destroyed in order not to leak resources; see more below.
|
||||||
|
|
||||||
|
@@@ note { .group-java }
|
||||||
|
|
||||||
|
A variant of the `ask` pattern that returns a `CompletionStage` instead of a Scala `Future`
|
||||||
|
is available in the `akka.pattern.PatternsCS` object.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
@@@ warning
|
@@@ warning
|
||||||
|
|
||||||
To complete the future with an exception you need send a Failure message to the sender.
|
To complete the future with an exception you need send a Failure message to the sender.
|
||||||
|
|
@ -581,11 +738,17 @@ This is *not done automatically* when an actor throws an exception while process
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #reply-exception }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #reply-exception }
|
||||||
|
|
||||||
If the actor does not complete the future, it will expire after the timeout
|
Java
|
||||||
period, completing it with an `AskTimeoutException`. The timeout is
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #reply-exception }
|
||||||
taken from one of the following locations in order of precedence:
|
|
||||||
|
If the actor does not complete the future, it will expire after the timeout period,
|
||||||
|
@scala[completing it with an `AskTimeoutException`. The timeout is taken from one of the following locations in order of precedence:]
|
||||||
|
@java[specified as parameter to the `ask` method; this will complete the `Future` with an `AskTimeoutException`.]
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
1. explicitly given timeout as in:
|
1. explicitly given timeout as in:
|
||||||
|
|
||||||
|
|
@ -595,6 +758,8 @@ taken from one of the following locations in order of precedence:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #using-implicit-timeout }
|
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #using-implicit-timeout }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
See @ref:[Futures](futures.md) for more information on how to await or query a
|
See @ref:[Futures](futures.md) for more information on how to await or query a
|
||||||
future.
|
future.
|
||||||
|
|
||||||
|
|
@ -604,7 +769,7 @@ you a way to avoid blocking.
|
||||||
|
|
||||||
@@@ warning
|
@@@ warning
|
||||||
|
|
||||||
When using future callbacks, such as `onComplete`, `onSuccess`, and `onFailure`,
|
When using future callbacks, @scala[such as `onComplete`, `onSuccess`, and `onFailure`,]
|
||||||
inside actors you need to carefully avoid closing over
|
inside actors you need to carefully avoid closing over
|
||||||
the containing actor’s reference, i.e. do not call methods or access mutable state
|
the containing actor’s reference, i.e. do not call methods or access mutable state
|
||||||
on the enclosing actor from within the callback. This would break the actor
|
on the enclosing actor from within the callback. This would break the actor
|
||||||
|
|
@ -622,51 +787,119 @@ original sender address/reference is maintained even though the message is going
|
||||||
through a 'mediator'. This can be useful when writing actors that work as
|
through a 'mediator'. This can be useful when writing actors that work as
|
||||||
routers, load-balancers, replicators etc.
|
routers, load-balancers, replicators etc.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #forward }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #forward }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #forward }
|
||||||
|
|
||||||
## Receive messages
|
## Receive messages
|
||||||
|
|
||||||
An Actor has to implement the `receive` method to receive messages:
|
|
||||||
|
|
||||||
@@snip [Actor.scala]($akka$/akka-actor/src/main/scala/akka/actor/Actor.scala) { #receive }
|
An Actor has to
|
||||||
|
@scala[implement the `receive` method to receive messages:]
|
||||||
|
@java[define its initial receive behavior by implementing the `createReceive` method in the `AbstractActor`:]
|
||||||
|
|
||||||
|
Scala
|
||||||
|
: @@snip [Actor.scala]($akka$/akka-actor/src/main/scala/akka/actor/Actor.scala) { #receive }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #createReceive }
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
This method returns a `PartialFunction`, e.g. a ‘match/case’ clause in
|
This method returns a `PartialFunction`, e.g. a ‘match/case’ clause in
|
||||||
which the message can be matched against the different case clauses using Scala
|
which the message can be matched against the different case clauses using Scala
|
||||||
pattern matching. Here is an example:
|
pattern matching. Here is an example:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #imports1 #my-actor }
|
@@@
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
The return type is `AbstractActor.Receive` that defines which messages your Actor can handle,
|
||||||
|
along with the implementation of how the messages should be processed.
|
||||||
|
You can build such behavior with a builder named `ReceiveBuilder`. Here is an example:
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
|
@Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #imports1 #my-actor }
|
||||||
|
|
||||||
|
@Java
|
||||||
|
: @@snip [MyActor.java]($code$/java/jdocs/actor/MyActor.java) { #imports #my-actor }
|
||||||
|
|
||||||
|
@@@ div { .group-java }
|
||||||
|
|
||||||
|
In case you want to provide many `match` cases but want to avoid creating a long call
|
||||||
|
trail, you can split the creation of the builder into multiple statements as in the example:
|
||||||
|
|
||||||
|
@@snip [GraduallyBuiltActor.java]($code$/java/jdocs/actor/GraduallyBuiltActor.java) { #imports #actor }
|
||||||
|
|
||||||
|
Using small methods is a good practice, also in actors. It's recommended to delegate the
|
||||||
|
actual work of the message processing to methods instead of defining a huge `ReceiveBuilder`
|
||||||
|
with lots of code in each lambda. A well structured actor can look like this:
|
||||||
|
|
||||||
|
@@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #well-structured }
|
||||||
|
|
||||||
|
That has benefits such as:
|
||||||
|
|
||||||
|
* easier to see what kind of messages the actor can handle
|
||||||
|
* readable stack traces in case of exceptions
|
||||||
|
* works better with performance profiling tools
|
||||||
|
* Java HotSpot has a better opportunity for making optimizations
|
||||||
|
|
||||||
|
The `Receive` can be implemented in other ways than using the `ReceiveBuilder` since it in the
|
||||||
|
end is just a wrapper around a Scala `PartialFunction`. In Java, you can implement `PartialFunction` by
|
||||||
|
extending `AbstractPartialFunction`. For example, one could implement an adapter
|
||||||
|
to [Javaslang Pattern Matching DSL](http://www.javaslang.io/javaslang-jdocs/#_pattern_matching).
|
||||||
|
|
||||||
|
If the validation of the `ReceiveBuilder` match logic turns out to be a bottleneck for some of your
|
||||||
|
actors you can consider to implement it at lower level by extending `UntypedAbstractActor` instead
|
||||||
|
of `AbstractActor`. The partial functions created by the `ReceiveBuilder` consist of multiple lambda
|
||||||
|
expressions for every match statement, where each lambda is referencing the code to be run. This is something
|
||||||
|
that the JVM can have problems optimizing and the resulting code might not be as performant as the
|
||||||
|
untyped version. When extending `UntypedAbstractActor` each message is received as an untyped
|
||||||
|
`Object` and you have to inspect and cast it to the actual message type in other ways, like this:
|
||||||
|
|
||||||
|
@@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #optimized }
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
<a id="actor-reply"></a>
|
<a id="actor-reply"></a>
|
||||||
## Reply to messages
|
## Reply to messages
|
||||||
|
|
||||||
If you want to have a handle for replying to a message, you can use
|
If you want to have a handle for replying to a message, you can use
|
||||||
`sender()`, which gives you an ActorRef. You can reply by sending to
|
@scala[`sender()`] @java[`getSender()`], which gives you an ActorRef. You can reply by sending to
|
||||||
that ActorRef with `sender() ! replyMsg`. You can also store the ActorRef
|
that ActorRef with @scala[`sender() ! replyMsg`.] @java[`getSender().tell(replyMsg, getSelf())`.] You can also store the ActorRef
|
||||||
for replying later, or passing on to other actors. If there is no sender (a
|
for replying later, or passing on to other actors. If there is no sender (a
|
||||||
message was sent without an actor or future context) then the sender
|
message was sent without an actor or future context) then the sender
|
||||||
defaults to a 'dead-letter' actor ref.
|
defaults to a 'dead-letter' actor ref.
|
||||||
|
|
||||||
```scala
|
Scala
|
||||||
case request =>
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #reply-without-sender }
|
||||||
val result = process(request)
|
|
||||||
sender() ! result // will have dead-letter actor as default
|
Java
|
||||||
```
|
: @@snip [MyActor.java]($code$/java/jdocs/actor/MyActor.java) { #reply }
|
||||||
|
|
||||||
## Receive timeout
|
## Receive timeout
|
||||||
|
|
||||||
The *ActorContext* `setReceiveTimeout` defines the inactivity timeout after which
|
The `ActorContext` `setReceiveTimeout` defines the inactivity timeout after which
|
||||||
the sending of a *ReceiveTimeout* message is triggered.
|
the sending of a `ReceiveTimeout` message is triggered.
|
||||||
When specified, the receive function should be able to handle an *akka.actor.ReceiveTimeout* message.
|
When specified, the receive function should be able to handle an `akka.actor.ReceiveTimeout` message.
|
||||||
1 millisecond is the minimum supported timeout.
|
1 millisecond is the minimum supported timeout.
|
||||||
|
|
||||||
Please note that the receive timeout might fire and enqueue the *ReceiveTimeout* message right after
|
Please note that the receive timeout might fire and enqueue the `ReceiveTimeout` message right after
|
||||||
another message was enqueued; hence it is **not guaranteed** that upon reception of the receive
|
another message was enqueued; hence it is **not guaranteed** that upon reception of the receive
|
||||||
timeout there must have been an idle period beforehand as configured via this method.
|
timeout there must have been an idle period beforehand as configured via this method.
|
||||||
|
|
||||||
Once set, the receive timeout stays in effect (i.e. continues firing repeatedly after inactivity
|
Once set, the receive timeout stays in effect (i.e. continues firing repeatedly after inactivity
|
||||||
periods). Pass in *Duration.Undefined* to switch off this feature.
|
periods). Pass in `Duration.Undefined` to switch off this feature.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #receive-timeout }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #receive-timeout }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #receive-timeout }
|
||||||
|
|
||||||
Messages marked with `NotInfluenceReceiveTimeout` will not reset the timer. This can be useful when
|
Messages marked with `NotInfluenceReceiveTimeout` will not reset the timer. This can be useful when
|
||||||
`ReceiveTimeout` should be fired by external inactivity but not influenced by internal activity,
|
`ReceiveTimeout` should be fired by external inactivity but not influenced by internal activity,
|
||||||
|
|
@ -681,7 +914,12 @@ the actor itself or child actors and the system for stopping top level actors. T
|
||||||
termination of the actor is performed asynchronously, i.e. `stop` may return before
|
termination of the actor is performed asynchronously, i.e. `stop` may return before
|
||||||
the actor is stopped.
|
the actor is stopped.
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #stoppingActors-actor }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #stoppingActors-actor }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [MyStoppingActor.java]($code$/java/jdocs/actor/MyStoppingActor.java) { #my-stopping-actor }
|
||||||
|
|
||||||
|
|
||||||
Processing of the current message, if any, will continue before the actor is stopped,
|
Processing of the current message, if any, will continue before the actor is stopped,
|
||||||
but additional messages in the mailbox will not be processed. By default these
|
but additional messages in the mailbox will not be processed. By default these
|
||||||
|
|
@ -707,7 +945,11 @@ whole system.
|
||||||
The `postStop()` hook is invoked after an actor is fully stopped. This
|
The `postStop()` hook is invoked after an actor is fully stopped. This
|
||||||
enables cleaning up of resources:
|
enables cleaning up of resources:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #postStop }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #postStop }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #postStop }
|
||||||
|
|
||||||
@@@ note
|
@@@ note
|
||||||
|
|
||||||
|
|
@ -727,14 +969,28 @@ stop the actor when the message is processed. `PoisonPill` is enqueued as
|
||||||
ordinary messages and will be handled after messages that were already queued
|
ordinary messages and will be handled after messages that were already queued
|
||||||
in the mailbox.
|
in the mailbox.
|
||||||
|
|
||||||
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #poison-pill }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #poison-pill }
|
||||||
|
|
||||||
### Graceful Stop
|
### Graceful Stop
|
||||||
|
|
||||||
`gracefulStop` is useful if you need to wait for termination or compose ordered
|
`gracefulStop` is useful if you need to wait for termination or compose ordered
|
||||||
termination of several actors:
|
termination of several actors:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #gracefulStop }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #gracefulStop }
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #gracefulStop-actor }
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #import-gracefulStop #gracefulStop }
|
||||||
|
|
||||||
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #gracefulStop-actor }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #gracefulStop-actor }
|
||||||
|
|
||||||
When `gracefulStop()` returns successfully, the actor’s `postStop()` hook
|
When `gracefulStop()` returns successfully, the actor’s `postStop()` hook
|
||||||
will have been executed: there exists a happens-before edge between the end of
|
will have been executed: there exists a happens-before edge between the end of
|
||||||
|
|
@ -777,9 +1033,13 @@ The phases are ordered with [topological](https://en.wikipedia.org/wiki/Topologi
|
||||||
|
|
||||||
Tasks can be added to a phase with:
|
Tasks can be added to a phase with:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-addTask }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-addTask }
|
||||||
|
|
||||||
The returned `Future[Done]` should be completed when the task is completed. The task name parameter
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #coordinated-shutdown-addTask }
|
||||||
|
|
||||||
|
The returned @scala[`Future[Done]`] @java[`CompletionStage<Done>`] should be completed when the task is completed. The task name parameter
|
||||||
is only used for debugging/logging.
|
is only used for debugging/logging.
|
||||||
|
|
||||||
Tasks added to the same phase are executed in parallel without any ordering assumptions.
|
Tasks added to the same phase are executed in parallel without any ordering assumptions.
|
||||||
|
|
@ -793,12 +1053,16 @@ Tasks should typically be registered as early as possible after system startup.
|
||||||
the coordinated shutdown tasks that have been registered will be performed but tasks that are
|
the coordinated shutdown tasks that have been registered will be performed but tasks that are
|
||||||
added too late will not be run.
|
added too late will not be run.
|
||||||
|
|
||||||
To start the coordinated shutdown process you can invoke `run` on the `CoordinatedShutdown`
|
To start the coordinated shutdown process you can invoke @scala[`run`] @java[`runAll`] on the `CoordinatedShutdown`
|
||||||
extension:
|
extension:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-run }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-run }
|
||||||
|
|
||||||
It's safe to call the `run` method multiple times. It will only run once.
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #coordinated-shutdown-run }
|
||||||
|
|
||||||
|
It's safe to call the @scala[`run`] @java[`runAll`] method multiple times. It will only run once.
|
||||||
|
|
||||||
That also means that the `ActorSystem` will be terminated in the last phase. By default, the
|
That also means that the `ActorSystem` will be terminated in the last phase. By default, the
|
||||||
JVM is not forcefully stopped (it will be stopped if all non-daemon threads have been terminated).
|
JVM is not forcefully stopped (it will be stopped if all non-daemon threads have been terminated).
|
||||||
|
|
@ -825,7 +1089,11 @@ If you have application specific JVM shutdown hooks it's recommended that you re
|
||||||
`CoordinatedShutdown` so that they are running before Akka internal shutdown hooks, e.g.
|
`CoordinatedShutdown` so that they are running before Akka internal shutdown hooks, e.g.
|
||||||
those shutting down Akka Remoting (Artery).
|
those shutting down Akka Remoting (Artery).
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-jvm-hook }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #coordinated-shutdown-jvm-hook }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #coordinated-shutdown-jvm-hook }
|
||||||
|
|
||||||
For some tests it might be undesired to terminate the `ActorSystem` via `CoordinatedShutdown`.
|
For some tests it might be undesired to terminate the `ActorSystem` via `CoordinatedShutdown`.
|
||||||
You can disable that by adding the following to the configuration of the `ActorSystem` that is
|
You can disable that by adding the following to the configuration of the `ActorSystem` that is
|
||||||
|
|
@ -845,7 +1113,7 @@ akka.cluster.run-coordinated-shutdown-when-down = off
|
||||||
|
|
||||||
Akka supports hotswapping the Actor’s message loop (e.g. its implementation) at
|
Akka supports hotswapping the Actor’s message loop (e.g. its implementation) at
|
||||||
runtime: invoke the `context.become` method from within the Actor.
|
runtime: invoke the `context.become` method from within the Actor.
|
||||||
`become` takes a `PartialFunction[Any, Unit]` that implements the new
|
`become` takes a @scala[`PartialFunction[Any, Unit]`] @java[`PartialFunction<Object, BoxedUnit>`] that implements the new
|
||||||
message handler. The hotswapped code is kept in a Stack which can be pushed and
|
message handler. The hotswapped code is kept in a Stack which can be pushed and
|
||||||
popped.
|
popped.
|
||||||
|
|
||||||
|
|
@ -857,11 +1125,16 @@ Please note that the actor will revert to its original behavior when restarted b
|
||||||
|
|
||||||
To hotswap the Actor behavior using `become`:
|
To hotswap the Actor behavior using `become`:
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #hot-swap-actor }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #hot-swap-actor }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #hot-swap-actor }
|
||||||
|
|
||||||
This variant of the `become` method is useful for many different things,
|
This variant of the `become` method is useful for many different things,
|
||||||
such as to implement a Finite State Machine (FSM, for an example see [Dining
|
such as to implement a Finite State Machine (FSM, for an example see @scala[[Dining
|
||||||
Hakkers](http://www.lightbend.com/activator/template/akka-sample-fsm-scala)). It will replace the current behavior (i.e. the top of the behavior
|
Hakkers](http://www.lightbend.com/activator/template/akka-sample-fsm-scala)).] @java[[Dining
|
||||||
|
Hakkers](http://www.lightbend.com/activator/template/akka-sample-fsm-java-lambda)).] It will replace the current behavior (i.e. the top of the behavior
|
||||||
stack), which means that you do not use `unbecome`, instead always the
|
stack), which means that you do not use `unbecome`, instead always the
|
||||||
next behavior is explicitly installed.
|
next behavior is explicitly installed.
|
||||||
|
|
||||||
|
|
@ -871,7 +1144,11 @@ of “pop” operations (i.e. `unbecome`) matches the number of “push” ones
|
||||||
in the long run, otherwise this amounts to a memory leak (which is why this
|
in the long run, otherwise this amounts to a memory leak (which is why this
|
||||||
behavior is not the default).
|
behavior is not the default).
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #swapper }
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #swapper }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #swapper }
|
||||||
|
|
||||||
### Encoding Scala Actors nested receives without accidentally leaking memory
|
### Encoding Scala Actors nested receives without accidentally leaking memory
|
||||||
|
|
||||||
|
|
@ -880,27 +1157,43 @@ See this @extref[Unnested receive example](github:akka-docs/src/test/scala/docs/
|
||||||
<a id="stash"></a>
|
<a id="stash"></a>
|
||||||
## Stash
|
## Stash
|
||||||
|
|
||||||
The *Stash* trait enables an actor to temporarily stash away messages
|
The @scala[`Stash` trait] @java[`AbstractActorWithStash` class] enables an actor to temporarily stash away messages
|
||||||
that can not or should not be handled using the actor's current
|
that can not or should not be handled using the actor's current
|
||||||
behavior. Upon changing the actor's message handler, i.e., right
|
behavior. Upon changing the actor's message handler, i.e., right
|
||||||
before invoking `context.become` or `context.unbecome`, all
|
before invoking @scala[`context.become` or `context.unbecome`] @java[`getContext().become()` or `getContext().unbecome()`], all
|
||||||
stashed messages can be "unstashed", thereby prepending them to the actor's
|
stashed messages can be "unstashed", thereby prepending them to the actor's
|
||||||
mailbox. This way, the stashed messages can be processed in the same
|
mailbox. This way, the stashed messages can be processed in the same
|
||||||
order as they have been received originally.
|
order as they have been received originally. @java[An actor that extends
|
||||||
|
`AbstractActorWithStash` will automatically get a deque-based mailbox.]
|
||||||
|
|
||||||
@@@ note
|
@@@ note { .group-scala }
|
||||||
|
|
||||||
The trait `Stash` extends the marker trait
|
The trait `Stash` extends the marker trait
|
||||||
`RequiresMessageQueue[DequeBasedMessageQueueSemantics]` which
|
`RequiresMessageQueue[DequeBasedMessageQueueSemantics]` which
|
||||||
requests the system to automatically choose a deque based
|
requests the system to automatically choose a deque based
|
||||||
mailbox implementation for the actor. If you want more control over the
|
mailbox implementation for the actor. If you want more
|
||||||
|
control over the
|
||||||
mailbox, see the documentation on mailboxes: @ref:[Mailboxes](mailboxes.md).
|
mailbox, see the documentation on mailboxes: @ref:[Mailboxes](mailboxes.md).
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
Here is an example of the `Stash` in action:
|
@@@ note { .group-java }
|
||||||
|
|
||||||
@@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #stash }
|
The abstract class `AbstractActorWithStash` implements the marker
|
||||||
|
interface `RequiresMessageQueue<DequeBasedMessageQueueSemantics>`
|
||||||
|
which requests the system to automatically choose a deque based
|
||||||
|
mailbox implementation for the actor. If you want more
|
||||||
|
control over the mailbox, see the documentation on mailboxes: @ref:[Mailboxes](mailboxes.md).
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
|
Here is an example of the @scala[`Stash`] @java[`AbstractActorWithStash` class] in action:
|
||||||
|
|
||||||
|
Scala
|
||||||
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #stash }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #stash }
|
||||||
|
|
||||||
Invoking `stash()` adds the current message (the message that the
|
Invoking `stash()` adds the current message (the message that the
|
||||||
actor received last) to the actor's stash. It is typically invoked
|
actor received last) to the actor's stash. It is typically invoked
|
||||||
|
|
@ -924,7 +1217,7 @@ The stash is backed by a `scala.collection.immutable.Vector`. As a
|
||||||
result, even a very large number of messages may be stashed without a
|
result, even a very large number of messages may be stashed without a
|
||||||
major impact on performance.
|
major impact on performance.
|
||||||
|
|
||||||
@@@ warning
|
@@@ warning { .group-scala }
|
||||||
|
|
||||||
Note that the `Stash` trait must be mixed into (a subclass of) the
|
Note that the `Stash` trait must be mixed into (a subclass of) the
|
||||||
`Actor` trait before any trait/class that overrides the `preRestart`
|
`Actor` trait before any trait/class that overrides the `preRestart`
|
||||||
|
|
@ -935,14 +1228,14 @@ callback. This means it's not possible to write
|
||||||
|
|
||||||
Note that the stash is part of the ephemeral actor state, unlike the
|
Note that the stash is part of the ephemeral actor state, unlike the
|
||||||
mailbox. Therefore, it should be managed like other parts of the
|
mailbox. Therefore, it should be managed like other parts of the
|
||||||
actor's state which have the same property. The `Stash` trait’s
|
actor's state which have the same property. The @scala[`Stash` trait’s] @java[`AbstractActorWithStash`]
|
||||||
implementation of `preRestart` will call `unstashAll()`, which is
|
implementation of `preRestart` will call `unstashAll()`, which is
|
||||||
usually the desired behavior.
|
usually the desired behavior.
|
||||||
|
|
||||||
@@@ note
|
@@@ note
|
||||||
|
|
||||||
If you want to enforce that your actor can only work with an unbounded stash,
|
If you want to enforce that your actor can only work with an unbounded stash,
|
||||||
then you should use the `UnboundedStash` trait instead.
|
then you should use the @scala[`UnboundedStash` trait] @java[`AbstractActorWithUnboundedStash` class] instead.
|
||||||
|
|
||||||
@@@
|
@@@
|
||||||
|
|
||||||
|
|
@ -957,10 +1250,11 @@ See @ref:[What Supervision Means](general/supervision.md#supervision-directives)
|
||||||
|
|
||||||
Use `Kill` like this:
|
Use `Kill` like this:
|
||||||
|
|
||||||
```scala
|
Scala
|
||||||
// kill the 'victim' actor
|
: @@snip [ActorDocSpec.scala]($code$/scala/docs/actor/ActorDocSpec.scala) { #kill }
|
||||||
victim ! Kill
|
|
||||||
```
|
Java
|
||||||
|
: @@snip [ActorDocTest.java]($code$/java/jdocs/actor/ActorDocTest.java) { #kill }
|
||||||
|
|
||||||
## Actors and exceptions
|
## Actors and exceptions
|
||||||
|
|
||||||
|
|
@ -990,6 +1284,8 @@ supervision process is started (see @ref:[supervision](general/supervision.md)).
|
||||||
supervisor’s decision the actor is resumed (as if nothing happened), restarted
|
supervisor’s decision the actor is resumed (as if nothing happened), restarted
|
||||||
(wiping out its internal state and starting from scratch) or terminated.
|
(wiping out its internal state and starting from scratch) or terminated.
|
||||||
|
|
||||||
|
@@@ div { .group-scala }
|
||||||
|
|
||||||
## Extending Actors using PartialFunction chaining
|
## Extending Actors using PartialFunction chaining
|
||||||
|
|
||||||
Sometimes it can be useful to share common behavior among a few actors, or compose one actor's behavior from multiple smaller functions.
|
Sometimes it can be useful to share common behavior among a few actors, or compose one actor's behavior from multiple smaller functions.
|
||||||
|
|
@ -1005,6 +1301,8 @@ traits and implementing the actor's `receive` as combination of these partial fu
|
||||||
|
|
||||||
Instead of inheritance the same pattern can be applied via composition - one would simply compose the receive method using partial functions from delegates.
|
Instead of inheritance the same pattern can be applied via composition - one would simply compose the receive method using partial functions from delegates.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
||||||
## Initialization patterns
|
## Initialization patterns
|
||||||
|
|
||||||
The rich lifecycle hooks of Actors provide a useful toolkit to implement various initialization patterns. During the
|
The rich lifecycle hooks of Actors provide a useful toolkit to implement various initialization patterns. During the
|
||||||
|
|
@ -1034,7 +1332,12 @@ this behavior, and ensure that there is only one call to `preStart()`.
|
||||||
One useful usage of this pattern is to disable creation of new `ActorRefs` for children during restarts. This can be
|
One useful usage of this pattern is to disable creation of new `ActorRefs` for children during restarts. This can be
|
||||||
achieved by overriding `preRestart()`:
|
achieved by overriding `preRestart()`:
|
||||||
|
|
||||||
@@snip [InitializationDocSpec.scala]($code$/scala/docs/actor/InitializationDocSpec.scala) { #preStartInit }
|
Scala
|
||||||
|
: @@snip [InitializationDocSpec.scala]($code$/scala/docs/actor/InitializationDocSpec.scala) { #preStartInit }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [InitializationDocTest.java]($code$/java/jdocs/actor/InitializationDocTest.java) { #preStartInit }
|
||||||
|
|
||||||
|
|
||||||
Please note, that the child actors are *still restarted*, but no new `ActorRef` is created. One can recursively apply
|
Please note, that the child actors are *still restarted*, but no new `ActorRef` is created. One can recursively apply
|
||||||
the same principles for the children, ensuring that their `preStart()` method is called only at the creation of their
|
the same principles for the children, ensuring that their `preStart()` method is called only at the creation of their
|
||||||
|
|
@ -1049,7 +1352,11 @@ for example in the presence of circular dependencies. In this case the actor sho
|
||||||
and use `become()` or a finite state-machine state transition to encode the initialized and uninitialized states
|
and use `become()` or a finite state-machine state transition to encode the initialized and uninitialized states
|
||||||
of the actor.
|
of the actor.
|
||||||
|
|
||||||
@@snip [InitializationDocSpec.scala]($code$/scala/docs/actor/InitializationDocSpec.scala) { #messageInit }
|
Scala
|
||||||
|
: @@snip [InitializationDocSpec.scala]($code$/scala/docs/actor/InitializationDocSpec.scala) { #messageInit }
|
||||||
|
|
||||||
|
Java
|
||||||
|
: @@snip [InitializationDocTest.java]($code$/java/jdocs/actor/InitializationDocTest.java) { #messageInit }
|
||||||
|
|
||||||
If the actor may receive messages before it has been initialized, a useful tool can be the `Stash` to save messages
|
If the actor may receive messages before it has been initialized, a useful tool can be the `Stash` to save messages
|
||||||
until the initialization finishes, and replaying them after the actor became initialized.
|
until the initialization finishes, and replaying them after the actor became initialized.
|
||||||
|
|
|
||||||
37
akka-docs/src/main/paradox/scala/scala-compat.md
Normal file
37
akka-docs/src/main/paradox/scala/scala-compat.md
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
# Java 8 and Scala Compatibility
|
||||||
|
|
||||||
|
Akka requires that you have [Java 8](http://www.oracle.com/technetwork/java/javase/downloads/index.html) or
|
||||||
|
later installed on your machine.
|
||||||
|
|
||||||
|
## Java 8 types
|
||||||
|
|
||||||
|
Starting with Akka 2.4.2 we have begun to introduce Java 8 types (most
|
||||||
|
prominently `java.util.concurrent.CompletionStage` and
|
||||||
|
`java.util.Optional`) where that was possible without breaking binary or
|
||||||
|
source compatibility. Where this was not possible (for example in the return
|
||||||
|
type of `ActorSystem.terminate()`) please refer to the
|
||||||
|
`scala-java8-compat` library that allows easy conversion between the Scala
|
||||||
|
and Java counterparts. The artifact can be included in Maven builds using:
|
||||||
|
|
||||||
|
```
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.scala-lang.modules</groupId>
|
||||||
|
<artifactId>scala-java8-compat_2.11</artifactId>
|
||||||
|
<version>0.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
We will only be able to seamlessly integrate all functional interfaces once
|
||||||
|
we can rely on Scala 2.12 to provide full interoperability—this will mean that
|
||||||
|
Scala users can directly implement Java Functional Interfaces using lambda syntax
|
||||||
|
as well as that Java users can directly implement Scala functions using lambda
|
||||||
|
syntax.
|
||||||
|
|
||||||
|
## Do not use -optimize Scala compiler flag
|
||||||
|
|
||||||
|
@@@ warning
|
||||||
|
|
||||||
|
Akka has not been compiled or tested with -optimize Scala compiler flag.
|
||||||
|
Strange behavior has been reported by users that have tried it.
|
||||||
|
|
||||||
|
@@@
|
||||||
|
|
@ -310,6 +310,13 @@ class Ponger(pinger: ActorRef) extends Actor {
|
||||||
|
|
||||||
//#fiddle_code
|
//#fiddle_code
|
||||||
|
|
||||||
|
//#immutable-message-definition
|
||||||
|
case class User(name: String)
|
||||||
|
|
||||||
|
// define the case class
|
||||||
|
case class Register(user: User)
|
||||||
|
//#immutable-message-definition
|
||||||
|
|
||||||
class ActorDocSpec extends AkkaSpec("""
|
class ActorDocSpec extends AkkaSpec("""
|
||||||
akka.loglevel = INFO
|
akka.loglevel = INFO
|
||||||
akka.loggers = []
|
akka.loggers = []
|
||||||
|
|
@ -381,6 +388,23 @@ class ActorDocSpec extends AkkaSpec("""
|
||||||
system.terminate()
|
system.terminate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"instantiates a case class" in {
|
||||||
|
//#immutable-message-instantiation
|
||||||
|
val user = User("Mike")
|
||||||
|
// create a new case class message
|
||||||
|
val message = Register(user)
|
||||||
|
//#immutable-message-instantiation
|
||||||
|
}
|
||||||
|
|
||||||
|
"use poison pill" in {
|
||||||
|
val victim = system.actorOf(Props[MyActor])
|
||||||
|
//#poison-pill
|
||||||
|
watch(victim)
|
||||||
|
victim ! PoisonPill
|
||||||
|
//#poison-pill
|
||||||
|
expectTerminated(victim)
|
||||||
|
}
|
||||||
|
|
||||||
"creating a Props config" in {
|
"creating a Props config" in {
|
||||||
//#creating-props
|
//#creating-props
|
||||||
import akka.actor.Props
|
import akka.actor.Props
|
||||||
|
|
@ -562,10 +586,12 @@ class ActorDocSpec extends AkkaSpec("""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//#watch
|
//#watch
|
||||||
val a = system.actorOf(Props(classOf[WatchActor], this))
|
val victim = system.actorOf(Props(classOf[WatchActor], this))
|
||||||
implicit val sender = testActor
|
implicit val sender = testActor
|
||||||
a ! "kill"
|
//#kill
|
||||||
|
victim ! "kill"
|
||||||
expectMsg("finished")
|
expectMsg("finished")
|
||||||
|
//#kill
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue