Search code examples
scalasprayspray-test

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


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 ?


Solution

  • 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