Java Pattern - Exception propagation in actor hierarchy using supervision
Ticket #2605
This commit is contained in:
parent
89c1f66b1f
commit
1b34290d4c
2 changed files with 129 additions and 1 deletions
45
akka-docs/rst/java/code/docs/pattern/JavaAsk.java
Normal file
45
akka-docs/rst/java/code/docs/pattern/JavaAsk.java
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
public class JavaAsk extends UntypedActor {
|
||||||
|
private ActorRef targetActor;
|
||||||
|
private ActorRef caller;
|
||||||
|
|
||||||
|
private static class AskParam {
|
||||||
|
Props props;
|
||||||
|
Object message;
|
||||||
|
AskParam(Props props, Object message) {
|
||||||
|
this.props = props;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SupervisorStrategy supervisorStrategy() {
|
||||||
|
return new OneForOneStrategy(0, Duration.Zero(), new Function<Throwable, Directive>() {
|
||||||
|
public Directive apply(Throwable cause) {
|
||||||
|
caller.tell(new Status.Failure(cause));
|
||||||
|
return SupervisorStrategy.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Object message) throws Exception {
|
||||||
|
if (message instanceof AskParam) {
|
||||||
|
AskParam param = (AskParam) message;
|
||||||
|
caller = getSender();
|
||||||
|
targetActor = getContext().actorOf(param.props);
|
||||||
|
targetActor.forward(param.message, getContext());
|
||||||
|
} else
|
||||||
|
unhandled(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ask(ActorSystem system, Props props, Object message, Timeout timeout) throws Exception {
|
||||||
|
ActorRef javaAsk = system.actorOf(Props.apply(JavaAsk.class));
|
||||||
|
try {
|
||||||
|
AskParam param = new AskParam(props, message);
|
||||||
|
Future<Object> finished = Patterns.ask(javaAsk, param, timeout);
|
||||||
|
Await.result(finished, timeout.duration());
|
||||||
|
} finally {
|
||||||
|
system.stop(javaAsk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
.. _howto-java:
|
.. _howto-java:
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
|
@ -17,6 +16,90 @@ sense to add to the ``akka.pattern`` package for creating an `OTP-like library
|
||||||
You might find some of the patterns described in the Scala chapter of
|
You might find some of the patterns described in the Scala chapter of
|
||||||
:ref:`howto-scala` useful even though the example code is written in Scala.
|
:ref:`howto-scala` useful even though the example code is written in Scala.
|
||||||
|
|
||||||
|
Exception propagation in actor hierarchy using supervision
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
*Contributed by: Rick Latrine*
|
||||||
|
|
||||||
|
A nice way to enter the actor world from java is the use of Patterns.ask().
|
||||||
|
This method starts a temporary actor to forward the message and collect the result from the actor to be "asked".
|
||||||
|
In case of errors within the asked actor the default supervision handling will take over.
|
||||||
|
The caller of Patterns.ask() will not be notified.
|
||||||
|
|
||||||
|
If that caller is interested in such an exception, he must reply to the temporary actor with Status.Failure(Throwable).
|
||||||
|
Behind the asked actor a complex actor hierarchy might be spawned to accomplish asynchronous work.
|
||||||
|
Then supervision is the established way to control error handling.
|
||||||
|
|
||||||
|
Unfortunately the asked actor must know about supervision and must catch the exceptions.
|
||||||
|
Such an actor is unlikely to be reused in a different actor hierarchy and contains crippled try/catch blocks.
|
||||||
|
|
||||||
|
This pattern provides a way to encapsulate supervision and error propagation to the temporary actor.
|
||||||
|
Finally the exception occurred in the asked actor is thrown by Patterns.ask().
|
||||||
|
|
||||||
|
Let's have a look at the example code:
|
||||||
|
|
||||||
|
.. code-block:: java
|
||||||
|
|
||||||
|
public class JavaAsk extends UntypedActor {
|
||||||
|
private ActorRef targetActor;
|
||||||
|
private ActorRef caller;
|
||||||
|
|
||||||
|
private static class AskParam {
|
||||||
|
Props props;
|
||||||
|
Object message;
|
||||||
|
AskParam(Props props, Object message) {
|
||||||
|
this.props = props;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SupervisorStrategy supervisorStrategy() {
|
||||||
|
return new OneForOneStrategy(0, Duration.Zero(), new Function<Throwable, Directive>() {
|
||||||
|
public Directive apply(Throwable cause) {
|
||||||
|
caller.tell(new Status.Failure(cause));
|
||||||
|
return SupervisorStrategy.stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Object message) throws Exception {
|
||||||
|
if (message instanceof AskParam) {
|
||||||
|
AskParam param = (AskParam) message;
|
||||||
|
caller = getSender();
|
||||||
|
targetActor = getContext().actorOf(param.props);
|
||||||
|
targetActor.forward(param.message, getContext());
|
||||||
|
} else
|
||||||
|
unhandled(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ask(ActorSystem system, Props props, Object message, Timeout timeout) throws Exception {
|
||||||
|
ActorRef javaAsk = system.actorOf(Props.apply(JavaAsk.class));
|
||||||
|
try {
|
||||||
|
AskParam param = new AskParam(props, message);
|
||||||
|
Future<Object> finished = Patterns.ask(javaAsk, param, timeout);
|
||||||
|
Await.result(finished, timeout.duration());
|
||||||
|
} finally {
|
||||||
|
system.stop(javaAsk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
In the ask method the parent actor is started.
|
||||||
|
The parent is sent which child it should create and which message is to be forwarded.
|
||||||
|
|
||||||
|
On receiving these parameteres the parent actor creates the target/child actor.
|
||||||
|
The message is forwarded in order to let the child actor reply the result directly to the temporary actor.
|
||||||
|
|
||||||
|
In case of an exception the supervisor tells the temporary actor which exception was thrown.
|
||||||
|
Afterwards the actor hierarchy is stopped.
|
||||||
|
The exception will be thrown by the ask method.
|
||||||
|
|
||||||
|
Finally we are able to execute an actor and receive the results or exceptions synchronously.
|
||||||
|
|
||||||
|
|
||||||
Template Pattern
|
Template Pattern
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue