19 jun 2015 kl. 02:02 skrev Frederic <[email protected]
<mailto:[email protected]>>:
There's more... as context is also null in the Future's callback,
anything using context won't work, see below for an updated example
using the Akka's scheduler and dispatcher:
import akka.actor._
import scala.concurrent._
import scala.concurrent.duration._
case class Done(s: String)
case object Greet
case class Complete(p: Promise[Unit])
class Greeter extends Actor {
import context.dispatcher
def receive = {
case Done(s) => println(s"Done($s) (system still running)!")
case Complete(p) => p.success(())
case Greet =>
val p = Promise[Unit]()
val saveMyself = self
val sched = context.system.scheduler
val disp = context.dispatcher
p.future onComplete {
case _ =>
println(s"self is $self")
println(s"self is expexted to be $saveMyself")
// cannot use self to send a message, need to close on self
self ! Done("Send using self")
saveMyself ! Done("Send using saveMyself")
// are we supposed to avoid using context here?
println(s"context is $context") // outputs: context is null
// is this meant to work?
// context.system.scheduler.scheduleOnce(1.millisecond,
saveMyself, Done)
// will fail because we can't get the scheduler as context
is null
try { context.system.scheduler.scheduleOnce(1.millisecond,
saveMyself, Done("scheduler 1")) } catch { case e => println(e) }
// The following will still fail because implicit
dispatcher is context.dispatcher and context is null
try { sched.scheduleOnce(1.millisecond, saveMyself,
Done("scheduler 2")) } catch { case e => println(e) }
// that will work...
sched.scheduleOnce(1.millisecond, saveMyself, Done("scheduler
3"))(disp, saveMyself)
}
self ! Complete(p)
throw new Exception("Messing with onComplete callback, self
will be dead letters")
}
}
object HelloAkkaScala extends App {
val system = ActorSystem("helloakka")
val greeter = system.actorOf(Props[Greeter], "greeter")
greeter ! Greet
}
Program output :
Running HelloAkkaScala
self is Actor[akka://helloakka/deadLetters]
[ERROR] [06/18/2015 16:47:50.464]
[helloakka-akka.actor.default-dispatcher-3]
[akka://helloakka/user/greeter] Messing with onComplete callback,
self will be dead letters
java.lang.Exception: Messing with onComplete callback, self will be
dead letters
at Greeter$anonfun$receive$1.applyOrElse(HelloAkkaScala.scala:40)
at akka.actor.Actor$class.aroundReceive(Actor.scala:467)
at Greeter.aroundReceive(HelloAkkaScala.scala:9)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
at akka.actor.ActorCell.invoke(ActorCell.scala:487)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at
akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at
scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at
scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at
scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
self is expexted to be Actor[akka://helloakka/user/greeter#-1327535750]
context is null
java.lang.NullPointerException
java.lang.NullPointerException
Done(Send using saveMyself) (system still running)!
[INFO] [06/18/2015 16:47:50.480]
[helloakka-akka.actor.default-dispatcher-4]
[akka://helloakka/deadLetters] Message [Done] from
Actor[akka://helloakka/deadLetters] to
Actor[akka://helloakka/deadLetters
<akka://helloakka/deadLetters]%20Message%20[Done]%20from%20Actor[akka://helloakka/deadLetters]%20to%20Actor[akka://helloakka/deadLetters>]
was not delivered. [1] dead letters encountered. This logging can be
turned off or adjusted with configuration settings
'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
Done(scheduler 3) (system still running)!
On Thursday, June 18, 2015 at 2:37:35 PM UTC-7, Frederic wrote:
Hello,
I found a quite specific case involving Actors, Future callbacks
and exceptions where self becomes deadLetters.
I have the feeling I'm using self the way it is meant to be used,
as described here:
http://doc.akka.io/docs/akka/2.3.11/general/jmm.html#jmm-shared-state
<http://doc.akka.io/docs/akka/2.3.11/general/jmm.html#jmm-shared-state>
Am I doing something wrong or is it a bug?
Please see code and output below to reproduce/illustrate the issue.
Thanks, Fred
import akka.actor._
import scala.concurrent._
case object Done
case object Greet
case class Complete(p: Promise[Unit])
class Greeter extends Actor {
import context.dispatcher
def receive = {
case Done => println("Done (system still running)!")
case Complete(p) => p.success(())
case Greet =>
val p = Promise[Unit]()
val saveMyself = self
p.future onComplete {
case _ =>
println(s"self is $self")
println(s"self is expexted to be $saveMyself")
// cannot use self to send a message, bug?
self ! Done
saveMyself ! Done
}
self ! Complete(p)
throw new Exception("Messing with onComplete callback, self
will be dead letters")
}
}
object HelloAkkaScala extends App {
val system = ActorSystem("helloakka")
val greeter = system.actorOf(Props[Greeter], "greeter")
greeter ! Greet
}
Program output :
Running HelloAkkaScala
self is Actor[akka://helloakka/deadLetters]
[ERROR] [06/18/2015 14:25:41.510]
[helloakka-akka.actor.default-dispatcher-4]
[akka://helloakka/user/greeter] Messing with onComplete callback,
self will be dead letters
java.lang.Exception: Messing with onComplete callback, self will
be dead letters
at Greeter$anonfun$receive$1.applyOrElse(HelloAkkaScala.scala:27)
at akka.actor.Actor$class.aroundReceive(Actor.scala:467)
at Greeter.aroundReceive(HelloAkkaScala.scala:8)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:516)
at akka.actor.ActorCell.invoke(ActorCell.scala:487)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:238)
at akka.dispatch.Mailbox.run(Mailbox.scala:220)
at
akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:397)
at
scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
at
scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
at
scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at
scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
self is expexted to be Actor[akka://helloakka/user/greeter#990239115]
Done (system still running)!
[INFO] [06/18/2015 14:25:41.516]
[helloakka-akka.actor.default-dispatcher-3]
[akka://helloakka/deadLetters] Message [Done$
<akka://helloakka/deadLetters]%20Message%20[Done$>] from
Actor[akka://helloakka/deadLetters] to
Actor[akka://helloakka/deadLetters] was not delivered. [1] dead
letters encountered. This logging can be turned off or adjusted
with configuration settings 'akka.log-dead-letters' and
'akka.log-dead-letters-during-shutdown'.
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ:
http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google
Groups "Akka User List" group.
To unsubscribe from this group and stop receiving emails from it,
send an email to [email protected]
<mailto:[email protected]>.
To post to this group, send email to [email protected]
<mailto:[email protected]>.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.