The Artima Developer Community
Sponsored Link

Akka Concurrency Forum
Section 8.5, PilotProvider changes

7 replies on 1 page. Most recent reply: Jan 7, 2019 11:17 AM by band wealth

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 7 replies on 1 page
Dan Luu

Posts: 27
Nickname: amitra
Registered: Feb, 2013

Section 8.5, PilotProvider changes Posted: Feb 26, 2013 1:28 PM
Reply to this message Reply
Advertisement
I'm doing something wrong here, and I suspect the right thing is fairly obvious, but I just don't see it at the moment.

This is the section where you have to change PilotProvider because Pilot and CoPilot now take parameters.

The "obvious" thing that occurred to me was to do this:


trait PilotProvider{
def newPilot(plane: ActorRef, controls: ActorRef, altimeter: ActorRef): Actor = new Pilot(plane, controls, altimeter)
def newCoPilot(plane: ActorRef, altimeter: ActorRef): Actor = new CoPilot(plane, altimeter)
}


But then when I 'sbt run', I get these errors:
Caused by: java.lang.ClassCastException: zzz.akka.avionics.Plane cannot be cast to zzz.akka.avionics.PilotProvider
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$2.apply(Plane. scala:53)
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$2.apply(Plane. scala:53)

Caused by: java.lang.ClassCastException: zzz.akka.avionics.Plane cannot be cast to zzz.akka.avionics.PilotProvider
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$3.apply(Plane. scala:54)
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$3.apply(Plane. scala:54)

I'm new enough to scala that the meaning of this error message isn't obvious to me. Why would this cause a Plane object to be cast to a PilotProvider object? Or is that not what the message means?

The lines in the error message are:

context.actorOf(Props(newCoPilot(plane, altimeter)), copilotName)
context.actorOf(Props(newPilot(plane, controls, altimeter)), pilotName)


Derek Wyatt

Posts: 69
Nickname: dwyatt
Registered: Oct, 2012

Re: Section 8.5, PilotProvider changes Posted: Feb 27, 2013 2:21 AM
Reply to this message Reply
The error is all about the Plane itself. The Plane has been defined as:


class Plane extends Actor with ActorLogging {
this: AltimeterProvider
with PilotProvider
with LeadFlightAttendantProvider =>


But its construction doesn't include the PilotProvider. The Plane's factory method should look like this:


def apply() = new Plane with AltimeterProvider
with PilotProvider
with LeadFlightAttendantProvider


My guess is that yours doesn't.

I should probably include it to complete the refactoring for the Plane itself, but I'm trying to give more work to people as they progress. I like getting people more deeply involved cuz it makes things stick in their head better.

But like I said, I should probably stick it in there, so I'll file that bug.

Now, if this doesn't work for you, then my guess is wrong, so let me know if you're still screwed.

Thanks,
D

Dan Luu

Posts: 27
Nickname: amitra
Registered: Feb, 2013

Re: Section 8.5, PilotProvider changes Posted: Feb 27, 2013 3:56 AM
Reply to this message Reply
Yep, I had that already. I'm a scala neophyte, so I could easily be wrong about this, but I think I would have gotten a compile time error, had I not included that. Instead, the code compiles fine (and all the tests even pass), but I get a runtime error.

Personally, I like having little exercises, but with solutions in the back, because it's easy to read a book through without understanding it, without some checks, but it's annoying to get stuck for hours if you're just completely missing something obvious. And, even if I do something that works, it's nice to see it done the "right" way, when I'm doing something inefficiently. But, everyone has different preferences about books; that's just my 2c.

I haven't had time to try to debug since running into the error, but I'll try to look later today, when I'll have some spare cycles.

In case it's obvious to you, just from the error message, here's the error I'm getting:

[DEBUG] [02/26/2013 20:56:17.885] [PlaneSimulation-akka.actor.default-dispatcher-3] [akka://PlaneSimulation/user/Plane/Pilots] now supervising Actor[a
kka://PlaneSimulation/user/Plane/Pilots/Joan]
[DEBUG] [02/26/2013 20:56:17.885] [PlaneSimulation-akka.actor.default-dispatcher-3] [akka://PlaneSimulation/user/Plane/Pilots] now supervising Actor[a
kka://PlaneSimulation/user/Plane/Pilots/Harry]
[ERROR] [02/26/2013 20:56:17.888] [PlaneSimulation-akka.actor.default-dispatcher-4] [akka://PlaneSimulation/user/Plane/Pilots/Harry] error while proce
ssing Create(-62053331)
d56d9e25-6f1b-45f9-9d6d-d45100839bfcakka.actor.ActorInitializ ationException: exception during creation
at akka.actor.ActorInitializationException$.apply(Actor.scala:170)
at akka.actor.ActorCell.create(ActorCell.scala:496)
at akka.actor.ActorCell.systemInvoke(ActorCell.scala:351)
at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:256)
at akka.dispatch.Mailbox.run(Mailbox.scala:211)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDi spatcher.scala:506)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:10 4)
Caused by: java.lang.ClassCastException: zzz.akka.avionics.Plane cannot be cast to zzz.akka.avionics.PilotProvider
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$3.apply(Plane. scala:54)
at zzz.akka.avionics.Plane$$anonfun$3$$anon$3$$anonfun$childStarter$3.apply(Plane. scala:54)
at akka.actor.ActorCell.newActor(ActorCell.scala:461)
at akka.actor.ActorCell.create(ActorCell.scala:479)
... 8 more


BTW, thanks for both writing the book and putting in time to answer questions and address issues. Despite the occasional frustration, I'm liking your book a lot.

Derek Wyatt

Posts: 69
Nickname: dwyatt
Registered: Oct, 2012

Re: Section 8.5, PilotProvider changes Posted: Feb 27, 2013 10:48 AM
Reply to this message Reply
> Yep, I had that already. I'm a scala neophyte, so I could
> easily be wrong about this, but I think I would have
> gotten a compile time error, had I not included that.
> Instead, the code compiles fine (and all the tests even
> pass), but I get a runtime error.

Yeah, both fortunately and unfortunately, Akka uses some reflection to get its job done, which means that you're not going to get a compile time error on those particular bits.

However, this sparks another question... What does your Plane's actor creation have? It should be

val plane = system.actorOf(Props(Plane()), "Plane")

inside the Avionics.scala file.
If it's...

val plane = system.actorOf(Props[Plane], "Plane")

then that'll explain it.

> Personally, I like having little exercises, but with
> solutions in the back, because it's easy to read a book
> through without understanding it, without some checks, but
> it's annoying to get stuck for hours if you're just
> completely missing something obvious. And, even if I do
> something that works, it's nice to see it done the "right"
> way, when I'm doing something inefficiently. But, everyone
> has different preferences about books; that's just my 2c.

I'm hoping to get the code out there soon... I've just been too busy to get it all done. I am working on it, though so... :)

>> I haven't had time to try to debug since running into the
> error, but I'll try to look later today, when I'll have
> some spare cycles.
>
> In case it's obvious to you, just from the error message,
> here's the error I'm getting:
>
...
> WorkerThread.java:104)
> Caused by: java.lang.ClassCastException:
> zzz.akka.avionics.Plane cannot be cast to
> zzz.akka.avionics.PilotProvider
> at
> at
> at
> at

...

Give that code above a try. If you've got the Props[Plane] there then the change I've given you will fix the issue.

> BTW, thanks for both writing the book and putting in time
> to answer questions and address issues. Despite the
> occasional frustration, I'm liking your book a lot.

I'm glad! And thanks for the feedback. When you clarify this stuff for me, it helps me make the book better and that's golden! I also greatly appreciate you taking up the challenge of really learning this stuff rather than just reading it through. Great work!

Dan Luu

Posts: 27
Nickname: amitra
Registered: Feb, 2013

Re: Section 8.5, PilotProvider changes Posted: Feb 27, 2013 1:22 PM
Reply to this message Reply
Thanks. That both fixed the bug and was enough for me to understand what the problem was.

I ran into a couple more bugs that had "obvious" error messages, and fixed those, but then I ran into another akka related error message, and I'm less sure that my thought process is correct. Does this make sense?

The error is:

java.lang.ClassCastException
at java.lang.Class.cast(Class.java:2990)
at scala.concurrent.Future$$anonfun$mapTo$1.liftedTree7$1(Future.scala:483)
at scala.concurrent.Future$$anonfun$mapTo$1.apply(Future.scala:482)
at scala.concurrent.Future$$anonfun$mapTo$1.apply(Future.scala:479)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:29)
at scala.concurrent.Future$InternalCallbackExecutor$.execute(Future.scala:680)
at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:37)
at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:133)
at akka.pattern.PromiseActorRef.$bang(AskSupport.scala:252)
at zzz.akka.avionics.Plane$$anonfun$receive$1.applyOrElse(Plane.scala:78)
at akka.actor.ActorCell.receiveMessage(ActorCell.scala:425)
at akka.actor.ActorCell.invoke(ActorCell.scala:386)
at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:230)
at akka.dispatch.Mailbox.run(Mailbox.scala:212)
at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDi spatcher.scala:502)
at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:262)
at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1478)
at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:10 4)


which refers to this:

sender ! Controls(actorForControls("ControlSurfaces"))


where the message surely must come from

val control = Await.result((plane ? Plane.GiveMeControl).mapTo[ActorRef], 5.seconds)


It makes sense to me to change the offending line to

sender ! actorForControls("ControlSurfaces")


Because we want an actorRef for the controls, so we can do the following:

control ! ControlSurfaces.StickBack(1f)


And it really makes no sense to pass a case class in, which is what I was doing previously. Is that reasonable? I'm more concerned about being able to reason about errors than fixing this particular error, because I'm going to want to write code that doesn't follow your book, someday :-).

Derek Wyatt

Posts: 69
Nickname: dwyatt
Registered: Oct, 2012

Re: Section 8.5, PilotProvider changes Posted: Feb 28, 2013 2:37 AM
Reply to this message Reply
Yup, that's it. You're casting from (mapTo) a Controls object to an ActorRef and that ain't gonna work, of course.

Nikos Anastopoulos

Posts: 1
Nickname: anastop
Registered: Sep, 2013

Re: Section 8.5, PilotProvider changes Posted: Sep 26, 2013 7:38 AM
Reply to this message Reply
Hi,

In the above solution proposed by Dan Luu, why would we prefer to send an "untyped" ActorRef for the ControlSurfaces, and not follow a more type-safe approach by wrapping the ActorRef within a Controls message.

I.e.:

In Plane.scala:

case GiveMeControl =>
log.info("Plane giving control.")
sender ! Controls(actorForControls("ControlSurfaces"))


In Avionics.scala main function:
...

val reply = Await.result(
(plane ? Plane.GiveMeControl).mapTo[Controls],
5.seconds)

val Controls(control) = reply

system.scheduler.scheduleOnce(200.millis) {
control ! ControlSurfaces.StickBack(2f)
}
...


and so on.

band wealth

Posts: 1
Nickname: bandwealth
Registered: Jan, 2019

Re: Section 8.5, PilotProvider changes Posted: Jan 7, 2019 11:17 AM
Reply to this message Reply
Hi
I've just spent an hour or so trying to figure out why my test expectMsg didn't get anything back.
I was copying code from the example on p116 for the Akka Concurrency book (paper edition)
eventually I cross checked the example in the Akka docs and copied stuff until I figured out ImplicitSender was also needed.how to make brosted chicken
Am I correct in thinking it's an error in the book?

Flat View: This topic has 7 replies on 1 page
Topic: Source code download? Previous Topic   Next Topic Topic: Ch 8.6 Testing Death Watch

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use