Scala - How spray call path goes (Debugging spray code)

216 views Asked by At

I am new to Scala, Spray and functional programming. And I am so sad that I still can not understand event the basic example of Spray RestAPI.

I have written the program according to the instructions given in this blog post. http://www.smartjava.org/content/first-steps-rest-spray-and-scala

And my Route function is as bellow.

  val aSimpleRoute =
    path("path1") {
      println("in path path1..")
      put {
        println("in path path1/put..")
        respondWithMediaType(MediaTypes.`text/html`) {
          complete {
            <h1>in path path1/put..</h1>
          }
        }
      } ~ get {
        println("in path path1/get..")
        respondWithMediaType(MediaTypes.`application/json`) {
          complete {
            <h1>in path path1/get..</h1>
          }
        }
      }
    } ~
  path("path2") {
    println("in path path2..")
    get {
      println("in path path2/get..")
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          <h1>in path path2/get..</h1>
        }
      }
    } ~ post {
      println("in path path2/post..")
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          <h1>in path path2/post..</h1>
        }
      }
    }
  }

Everything works as expected. But my problem is, when my programm started it will run through the receive function. See my output of println, when program started (before it handle any http request)

in path path1..
in path path1/put..
in path path1/get..
in path path2..
in path path2/get..
in path path2/post..
[INFO] [09/14/2015 12:56:01.364] [on-spray-can-akka.actor.default-dispatcher-4] [akka://on-spray-can/user/IO-HTTP/listener-0] Bound to localhost/127.0.0.1:8080

So I can not understand why the program comes into all it's possible call paths, when it started. And also, non of these println is reached when an HTTP request received.

Can anyone explain why ?

2

There are 2 answers

2
dk14 On BEST ANSWER

You can find an explanation here: Understanding extractions

In short, non-leaf and non-parametrized (with no extraction) directives are executed only once when route is build. Leaf directive (like complete) is executed only if request is hitting directive's route. Parametrized directives (and everything inside them) are executed per request (as extracted parameter is different every time) - even if directive itself is coming after directive that already accepted this request.

In your case you've got printlns inside non-leaf and non-parametrized directives so they were executed only once on initialization. If you want them to be executed per acceptable request - just move them inside complete:

val aSimpleRoute =
  path("path1") {
    put {     
      respondWithMediaType(MediaTypes.`text/html`) {
        complete {
          println("in path path1/put..")
          <h1>in path path1/put..</h1>
        }
      }
    } ~ get {
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          println("in path path1/get..")
          <h1>in path path1/get..</h1>
        }
      }
    }
  } ~
  path("path2") {
    get {    
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          println("in path path2/get..")
          <h1>in path path2/get..</h1>
        }
      }
    } ~ post {
      respondWithMediaType(MediaTypes.`application/json`) {
        complete {
          println("in path path2/post..")
          <h1>in path path2/post..</h1>
        }
    }
  }

Discussion is here

0
Dmitri On

Well, you used "val" to declare spray routes, it is normal behavior because when you run your program, Scala initialize vals, if you will put "lazy val" instead of "val" you will see that you will get print when you will use this val explicitly.

For Example:

    val a = {
        println("val a initialization")
        "val a initialization"
      }
 
   lazy val b = {
        println("using of val b")
        "using of val b"
      }
    
      println("use of Val a " + a)
    
      println("use of val b  " + b)

Result:

val a initialization
use of Val a val a initialization
using of val b
use of val b  using of val b