1

Here's a smallest example

package org.example

import akka.actor._
import akka.pattern.ask
import akka.util.duration._
import akka.util.Timeout

class Counter extends Actor {
  def receive = {
    case _  => sender ! "hi"
  }
}

object AkkaProjectInScala extends App {
  val system = ActorSystem("AkkaProjectInScala")

  val counter = system.actorOf(Props[Counter])

  // this will raise NullPointerException    
  (counter ? "i just came to say hello") onSuccess {
    case x => println("He said " + x)
  }

  implicit val timeout = Timeout(5 seconds)
  system.shutdown()
}

This seems weird because the implicits raise compile error when I try something like this in the console

scala> def magic(a: Int)(implicit b: Int) = a + b
magic: (a: Int)(implicit b: Int)Int

scala> magic(3)
<console>:9: error: could not find implicit value for parameter b: Int
              magic(3)

Is there some other magic which happens when using Akka which prevents the compiler from detecting this at compile time?

Jakub Arnold
  • 85,596
  • 89
  • 230
  • 327
  • Might be [initialization issue](http://stackoverflow.com/q/15346600/298389): implicit is resolved, but not yet exists (the value is unset). – om-nom-nom Mar 15 '13 at 12:25
  • Does that mean the `Timeout` initialization is not thread safe? – Jakub Arnold Mar 15 '13 at 12:29
  • I wouldn't said so [in general]. It simply means [forward references](https://en.wikipedia.org/wiki/Forward_declaration) **inside App trait** (because compiler rewrites it) will lead to NPE's and it is mentioned in docs (e.g. if you'll try to forward-reference Int you'll get 0, but generally speaking Int initialization is thread safe). – om-nom-nom Mar 15 '13 at 12:33

2 Answers2

1

The timeout has not been initialized when you send the message. All val are initialized in the order they appear in the source code. Code not part of a method body is constructor code including "free standing" code like your message-sending code and the initialization of timeout. So the implicit is referenced before it is initialized.

Randall Schulz
  • 26,420
  • 4
  • 61
  • 81
1

You didn't state your used versions, but I guess it is not Akka 2.1 since duration has moved to scala.concurrent. With Scala 2.10.1-RC3 and Akka 2.1 however when I try to compile your code, it complains about a missing ExecutionContext (which can be imported with import scala.concurrent.ExecutionContext.Implicits.global). Also it did not compile with timeout defined after the ask-pattern. After solving the compile issues it worked fine for me. So, I suggest that you use the newest versions.

Here the working code again - with Akka 2.1

import scala.concurrent.duration._

import akka.actor._
import akka.dispatch._
import akka.util.Timeout
import akka.pattern.ask
import scala.concurrent.ExecutionContext.Implicits.global


class Counter extends Actor {
  def receive = {
    case _  => sender ! "hi"
  }
}

object AkkaProjectInScala extends App {
  val system = ActorSystem("AkkaProjectInScala")

  val counter = system.actorOf(Props[Counter])
  implicit val timeout = Timeout(5 seconds)

  val future = (counter ? "i just came to say hello") 
  future onSuccess {
    case x => println("He said " + x)
  }

  system.shutdown()
}
michael_s
  • 2,515
  • 18
  • 24