On Thu, Aug 18, 2011 at 12:15 AM, Alex Dean
<alexand...@keplarllp.com> wrote:
> path("orders" / LongNumber) { id =>
> get {
> Console.println("Get")
> _.complete("Get")
> } ~
I think the basic problem here is, that you have request handling
logic (`println`) inside the route *building* code. Because, that's
what the block which you pass to `get` is -- route building code which
returns a route which handles a request later on. The code that really
handles the request is the `_.complete()` part, so everything you want
to do to handle a request has to be done inside this function like `{
ctx => doSomething(); ctx.complete("Get") }`.
But you are right there seems to be something else going on regarding
your `printlns` only being executed in some cases.
HTH
--
Johannes
-----------------------------------------------
Johannes Rudolph
http://virtual-void.net
as Johannes already pointed out the problem is that your code executes "println" statements at other times than you expect.
Sprays rather compact route building DSL with all its function literals can be somewhat tricky, so let me go into some more detail to explain what's going on:
Assume you have the following route:
val route: Route = _.complete("yeah")
This is equivalent to
val route: Route = { ctx => ctx.complete("yeah") }
which is a function literal. The function defined by the literal is created at the time the "val" statement is reached but the code inside of the function is not executed until an actual request is injected into the route structure. This is all probably quite clear.
Not let's look at this slightly more complex structure:
val route = {
get {
_.complete("yeah")
}
}
This is equivalent to
val route = {
val x = { ctx => ctx.complete("yeah") }
get.apply(x)
}
First a function object is created from the literal. This function is passed to the apply function of the object returned by the "get" directive, which then creates the final route.
Now let's look at your code:
val route = get {
Console.println("Get all")
_.complete("Get all")
}
This is equivalent to
val route = {
val x = {
Console.println("Get all")
{ ctx => ctx.complete("yeah") }
}
get.apply(x)
}
You can now see whats going on. The "println" statement is executed when the route val is created, not when a request comes in!
In order to execute the "println" at request processing time it should therefore be _inside_ of the leaf-level route function literal:
val route = get { ctx =>
Console.println("Get all")
ctx.complete("Get all")
}
This will work as expected.
Now, why are you seeing the output you are seeing in your specific case?
Firstly, there should be "Get all" and "Post all" printouts in your log, just a lot further up, before the first request came in. Maybe you didn't see them because of that.
Secondly, the "Get", "Put" and "Delete" printouts are not executed at the time the whole route structure is built because they are inside of another function literal (the function "id => ..."). The route structure inside of your id-specific "orders" path directive depends on the extracted id. It is only being built when a request has come in and an id has been extracted. Therefore you are seeing the "Get", "Put" and "Delete" printouts at the time an id-specific orders request is being processed. In the end, only the right leaf-route is really being executed, which is why the HttpResponse is the one you are expecting.
I realize that all this might seem a bit confusing at first. However, once you understand where to put your code in order to have it be executed at the right time this whole logic is extremely powerful! You can for example construct routes dynamically depending on outer-level extractions if you want to.
Anyway, one key concept to remember is:
If you want to have code (like your "println" statements) be executed when the respective route is executed put it in the lowest-level function literal (the leaf-route). Then everything will be fine.
And of course: Remember that `_.complete("...")` is a function literal all by itself.
Cheers,
Mathias
---
mat...@spray.cc
http://www.spray.cc