Sorry, I have been buried with work. 

The problem with the DSL approach in my opinion is that it leaves too much 
space for error and strange things happening and at the same time it 
hamstrings you into a particular flow that may or may not be appropriate to 
the problem. Just to have some fun, this route doesn't work. It compiles 
just fine, the server comes up but nothing happens. Spot the problem? 

val route = {
  path("orders") {
    authenticateBasic(realm = "admin area", myAuthenticator) { user =>
      get {
        encodeResponseWith(Deflate) {
          complete {
            // marshal custom object with in-scope marshaller
            retrieveOrdersFromDB
          }
        }
      } ~
      post {
        // decompress gzipped or deflated requests if required
        decodeRequest {
          // unmarshal with in-scope unmarshaller
          entity(as[Order]) { order =>
            complete {
              // ... write order to DB
              "Order received"
            }
          }
        }
      }
    }
  } ~
  // extract URI path element as Int
  pathPrefix("order" / IntNumber) { orderId =>
    pathEnd {
      (put | parameter('method ! "put")) {
        // form extraction from multipart or www-url-encoded forms
        formFields(('email, 'total.as[Money])).as(Order) { order =>
          complete {
            // complete with serialized Future result
            (myDbActor ? Update(order)).mapTo[TransactionResult]
          }
        }
      } ~
      get {
        // debugging helper
        logRequest("GET-ORDER") {
          // use in-scope marshaller to create completer function
          completeWith(instanceOf[Order]) { completer =>
            // custom
            processOrderRequest(orderId, completer)
          }
        }
      }
    } 
    path("items") {
      get {
        // parameters to case class extraction
        parameters(('size.as[Int], 'color ?, 'dangerous ? "no"))
          .as(OrderItem) { orderItem =>
            // ... route using case class instance created from
            // required and optional query parameters
            complete("") // hide
          }
      }
    }
  } ~
  pathPrefix("documentation") {
    // optionally compresses the response with Gzip or Deflate
    // if the client accepts compressed responses
    encodeResponse {
      // serve up static content from a JAR resource
      getFromResourceDirectory("docs")
    }
  } ~
  path("oldApi" / Remaining) { pathRest =>
    redirect("http://oldapi.example.com/"; + pathRest, MovedPermanently)
  }}


If you got that there is one missing ~ between the routes you have a sharp 
eye but the DSL wont tell you, the code compiles just fine. But there I 
thought the DSL was supposed to make everything easy. Nope, if you put 
directives in the wrong order, nest them in the wrong order, or anything 
like that the code doesnt warn you, it just refuses to run. Yes, you can 
scream "unit test everything" but really? Is this untyped Ruby here? 
Testing everything is not a strategy that scales well in business or 
endures in a long running codebase, its an academic construct that 
eventually crumbles under the real world. 

The other problem with the routing is that it ties you into a certain set 
of directives and techs and breaking out of that is painful. Lets say you 
like the validation checking of Play-json over Spray-json? Can it be 
integrated with the route? With difficulty maybe but then you dont get the 
ability to handle errors like you do with the low level API. If the body 
doesnt parse out to the type the route blows up and the user gets back an 
internal error. What if I dont want to tell my users how to hack json to 
feed to my site? What if I dont want actors blowing up on internal errors? 
If so then I am up a creek of thin ice. 

Subsequent to my OP, I sat down and worked with the DSL for a good week, 
integrating it into the business project I am working on. It was painful. 
Missing tilde causes routes to not work, wrong nesting, wrong order of 
directives, not able to validate my json and return better error structures 
or handle things conditionally. It turned into a royal nightmare and it was 
entirely unnecessary. I switched back to using the low level api and other 
than some annoyances with handling headers that could be nicer, it just 
worked. I have flexibility to return what I want, when I want. I can 
offload to an actor that calls 10 other actors and integrates the results 
of the other actors into one actor and so on. In short, yes it was a bit 
more verbose but it was clear, easier to understand, easier to maintain, 
static type checked and solid. 

My personal conclusion is that the DSL is fine for simple projects but once 
you get into a real world business app, it starts to get in the way and 
frustrate. 

-- Robert 

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to