Error while doing a very basic test of http server using scala akka spray can

akka, httpserver, scala, spray

Solution

In Scala world it's very important to be careful with versions since everything develops rapidly and backwards compatibility between major versions is not guaranteed.

Spray depends on Akka and this page contains information regarding supported combinations.

spray 1.3.1 is built against Scala 2.10.3 and Akka 2.3.0 as well as Scala 2.11.1 and Akka 2.3.2.

So, if you use Scala 2.10.3 the correct version of Akka would be at least 2.3.0.

Moreover, the example which I think you are following from this page is not very good.

First of all it misses the fact that the code where you initialise the thing with `IO(Http) ! Http.Bind(...)` must be inside an actor. The actor, which received `Http.Bind` tries to reply with `Http.Bound` and since the caller is not an actor you get dead letters.

So, I would advise to do something like this:

class MyApp extends Actor {

  implicit val system = context.system

  override def receive: Receive = {
    case "start" =>
      val myListener: ActorRef = system.actorOf(Props[TestHttpListener], "httpListener")
      IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080)
  }
}

Then from the `main()` method of your app you need to do:

val myApp: ActorRef = system.actorOf(Props[MyApp], "myApp")
myApp ! "start"

Another thing that is not so easy to understand from the example is that in your listener actor you need not only to process messages, but also register itself on every connection:

class TestHttpListener extends Actor {
  def receive = {
    case HttpRequest(HttpMethods.GET, Uri.Path("/ping"), _, _, _) =>
      sender() ! HttpResponse(entity = "PONG")

    case c : Tcp.Connected =>
      sender() ! Http.Register(self)
  }
}

Problem

I did a very basic test of spray can using: - Akka 2.10 2.24 - Scala 2.10.3 - Spray Can 1.3.1 - sbt 0.13 - IntelliJ 13 Here is my code: ``` val myListener: ActorRef = system.actorOf(Props[TestHttpListener], "httpListener") IO(Http) ! Http.Bind(myListener, interface = "localhost", port = 8080) ``` The `httpListener` reacts to `Http.Connected` with `Http.Register(self)`. I use sbt to run my code. It fails with an `AbstractMethodError`: ``` [ERROR] [07/12/2014 18:46:48.364] [default-akka.actor.default-dispatcher-5] [ActorSystem(default)] Uncaught error from thread [default-akka.actor.default-dispatcher-5] shutting down JVM since 'akka.jvm-exit-on-fatal-error' is enabled java.lang.AbstractMethodError: spray.can.HttpManager.akka$actor$ActorLogging$_setter_$log_$eq(Lakka/event/LoggingAdapter;)V at akka.actor.ActorLogging$class.$init$(Actor.scala:335) at spray.can.HttpManager.<init>(HttpManager.scala:29) at spray.can.HttpExt$$anonfun$1.apply(Http.scala:153) at spray.can.HttpExt$$anonfun$1.apply(Http.scala:153) at akka.actor.TypedCreatorFunctionConsumer.produce(Props.scala:422) at akka.actor.Props.newActor(Props.scala:331) at akka.actor.ActorCell.newActor(ActorCell.scala:534) at akka.actor.ActorCell.create(ActorCell.scala:560) at akka.actor.dungeon.FaultHandling$class.finishCreate(FaultHandling.scala:135) at akka.actor.dungeon.FaultHandling$class.faultCreate(FaultHandling.scala:129) at akka.actor.ActorCell.faultCreate(ActorCell.scala:338) at akka.actor.dungeon.FaultHandling$class.faultRecreate(FaultHandling.scala:58) at akka.actor.ActorCell.faultRecreate(ActorCell.scala:338) at akka.actor.ActorCell.invokeAll$1(ActorCell.scala:428) at akka.actor.ActorCell.systemInvoke(ActorCell.scala:447) at akka.dispatch.Mailbox.processAllSystemMessages(Mailbox.scala:262) at akka.dispatch.Mailbox.run(Mailbox.scala:218) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:385) 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) ```

Original source