incubator-esme-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From David Pollak <feeder.of.the.be...@gmail.com>
Subject Work on the ESME REST APIs (and some stuff that will be rolled into Lift)
Date Wed, 04 Feb 2009 20:45:53 GMT
Folks,
I'm been working on the updates to the ESME REST APIs.

I've reduced the call cycle to something that looks like:

   1. A request is dispatched based on the URL
   2. The target of the dispatch returns a Box[T] where T is the type of the
   thing that will be calculated if it can be
      1. T might be Boolean, Int, User, etc.
      2. It's in a Box because it perhaps cannot be calculated (e.g., not
      enough permissions, etc.)
      3. The Box can be a Failure or even a FailureParam.  In the case of
      FailureParam, the param is the HTTP return code
   3. The result is put in an IntermediateAnswer along with a function that
   can convert from T to the expected HTTP response type (e.g., XML or JSON)
   4. The IntermediateAnswer is queried in order to build the actual
   response.

With a nice dose of implicit, the code becomes very clean:

  val dispatch: RetType = {
    case Req("rest" :: "status" :: Nil, "", GetRequest) => status()
    case Req("rest" :: "login" :: Nil, "", PostRequest) => login()
    case Req("rest" :: "logout" :: Nil, "", GetRequest) => logout()
    case Req("rest" :: "message" :: Nil, "", GetRequest) => getMsgs()
  }

And let's see some implementations:
  def status()  = User.currentUser ?~ "No Session" ~> 400

  def logout() = {
    User.logUserOut()
    true
  }

In status(), if there's no user logged in, we create a "No Session" error
message and return a 400.

In logout(), we just return true.

Now, the implicit magic comes from:
  implicit def boolToResp(v: Boolean, t: RequestedResponse): LiftResponse =
(v, t) match {
    case (v, XMLReqResponse) => new XmlResponse(<resp answer={v.toString}/>)
    case (v, JSONReqResponse) => JSONResponse(v)
  }

  implicit def userToResp(v: User, t: RequestedResponse): LiftResponse = (v,
t) match {
    case (v, XMLReqResponse) => new XmlResponse(v.toXml)
    case (v, JSONReqResponse) => JSONResponse(v.asJs)
  }

The code will automatically pick up these methods that convert from the
object type to the appropriate response type.  One of these "views" must
exist for each type that is returned from a dispatched method.

As I finish this stuff up, I'll roll it into some generic Lift classes.

Thanks,

David

-- 
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Git some: http://github.com/dpp

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message