Merge pull request #1933 from akka/wip-3764-props-docs-∂π

clean up docs and deprecation around how to create Props
This commit is contained in:
Roland Kuhn 2014-01-17 05:57:37 -08:00
commit 453815c073
17 changed files with 99 additions and 244 deletions

View file

@ -11,14 +11,17 @@ import static akka.pattern.Patterns.pipe;
import static akka.pattern.Patterns.gracefulStop;
//#import-gracefulStop
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;
import akka.testkit.AkkaJUnitActorSystemResource;
import org.junit.ClassRule;
import org.junit.Test;
//#import-gracefulStop
import scala.concurrent.Await;
//#import-ask
@ -119,43 +122,6 @@ public class UntypedActorDocTest {
}
//#parametric-creator
@SuppressWarnings("deprecation")
@Test
public void createPropsDeprecated() {
//#creating-props-deprecated
// DEPRECATED: encourages to close over enclosing class
final Props props1 = new Props(new UntypedActorFactory() {
private static final long serialVersionUID = 1L;
@Override
public UntypedActor create() throws Exception {
return new MyUntypedActor();
}
});
// DEPRECATED: encourages to close over enclosing class
final Props props2 = new Props().withCreator(new UntypedActorFactory() {
private static final long serialVersionUID = 1L;
@Override
public UntypedActor create() throws Exception {
return new MyUntypedActor();
}
});
// these are DEPRECATED due to duplicate functionality with Props.create()
final Props props3 = new Props(MyUntypedActor.class);
final Props props4 = new Props().withCreator(MyUntypedActor.class);
//#creating-props-deprecated
new JavaTestKit(system) {
{
for (Props props : new Props[] { props1, props2, props3, props4 }) {
final ActorRef a = system.actorOf(props);
a.tell("hello", getRef());
expectMsgEquals("hello");
}
}
};
}
@Test
public void systemActorOf() {
//#system-actorOf
@ -538,8 +504,15 @@ public class UntypedActorDocTest {
* @return a Props for creating this actor, which can then be further configured
* (e.g. calling `.withDispatcher()` on it)
*/
public static Props props(int magicNumber) {
return Props.create(DemoActor.class, magicNumber);
public static Props props(final int magicNumber) {
return Props.create(new Creator<DemoActor>() {
private static final long serialVersionUID = 1L;
@Override
public DemoActor create() throws Exception {
return new DemoActor(magicNumber);
}
});
}
final int magicNumber;

View file

@ -65,52 +65,22 @@ example of a parametric factory could be:
.. includecode:: code/docs/actor/UntypedActorDocTest.java#parametric-creator
Deprecated Variants
^^^^^^^^^^^^^^^^^^^
.. note::
Up to Akka 2.1 there were also the following possibilities (which are retained
for a migration period):
.. includecode:: code/docs/actor/UntypedActorDocTest.java#import-untypedActor
.. includecode:: code/docs/actor/UntypedActorDocTest.java#creating-props-deprecated
The last two are deprecated because their functionality is available in full
through :meth:`Props.create()`.
The first two are deprecated because the resulting :class:`UntypedActorFactory`
is typically a local class which means that it implicitly carries a reference
to the enclosing class. This can easily make the resulting :class:`Props`
non-serializable, e.g. when the enclosing class is an :class:`Actor`. Akka
advocates location transparency, meaning that an application written with
actors should just work when it is deployed over multiple network nodes, and
non-serializable actor factories would break this principle. In case indirect
actor creation is needed—for example when using dependency injection—there is
the possibility to use an :class:`IndirectActorProducer` as described below.
There were two use-cases for these methods: passing constructor arguments to
the actor—which is solved by the newly introduced :meth:`Props.create()` method
above—and creating actors “on the spot” as anonymous classes. The latter should
be solved by making these actors named inner classes instead (if they are not
``static`` then the enclosing instances ``this`` reference needs to be passed
as the first argument).
.. warning::
Declaring one actor within another is very dangerous and breaks actor
encapsulation unless the nested actor is a static inner class. Never pass an
actors ``this`` reference into :class:`Props`!
In order for mailbox requirements—like using a deque-based mailbox for actors
using the stash—to be picked up, the actor type needs to be known before
creating it, which is what the :class:`Creator` type argument allows.
Therefore make sure to use the specific type for your actors wherever
possible.
Recommended Practices
^^^^^^^^^^^^^^^^^^^^^
It is a good idea to provide static factory methods on the
:class:`UntypedActor` which help keeping the creation of suitable
:class:`Props` as close to the actor definition as possible, thus containing
the gap in type-safety introduced by reflective instantiation within a single
class instead of spreading it out across a whole code-base. This helps
especially when refactoring the actors constructor signature at a later point,
where compiler checks will allow this modification to be done with greater
confidence than without.
:class:`Props` as close to the actor definition as possible. This also allows
usage of the :class:`Creator`-based methods which statically verify that the
used constructor actually exists instead relying only on a runtime check.
.. includecode:: code/docs/actor/UntypedActorDocTest.java#props-factory