Normally, lift will look for a "view" that satifying an HTTP request. A view is an XHTML page or segment of a page with special <lift:xxx> processing instructions in it (e.g., an instruction to embed a controller, an instruction to surround the XHTML with another template, etc.) However, in certain cases, for example, when you want to satisfy a Web Services (REST) request, you can use Scala's pattern matching to intercept a request and service it with a "short lived" controller (rather than lift's normal long-lived, Actor-based controllers.)
It's easy to "dispatch" incoming HTTP requests.
In your "Boot" class create a PartialFunction
that matches a pattern related to the incoming request and
then create a short-lived controller to service the request.
/** * A class that's instantiated early and run. It allows the application * to modify lift's environment */ class Boot { def boot { val dispatcher: PartialFunction[{RequestState, List[String], (String) => java.io.InputStream}, (HttpServletRequest) => Option[Any]] = { case {r, "webservices" :: c :: Nil, _} => { (req: HttpServletRequest) => { val rc = new WebServices(r, req) val invoker = createInvoker(c, rc) invoker match { case None => None case Some(f) => f() } } } } Servlet.addBefore(dispatcher) } }
This code matches all the requests to "/webservices/????" and
assigns the stuff in '????' to the variable c
. Then
the code attempts to find a public method with that name on
the controller. If the method exists, it's invoked and lift
processes the result.
You can see a couple of examples:
All Users in the database
Add a User to the database
def add_user: XmlResponse = { var success = false for (val firstname <- params("firstname"); val lastname <- params("lastname"); val email <- params("email")) { val u = new User u.firstName := firstname u.lastName := lastname u.email := email params("textarea").map{v => u.textArea := v} params("password").map{v => u.password := v} success = u.save } XmlResponse(<add_user success={success.toString}/>) }
The controller simply validates that the required parameters exist
(the for
block.) If they do, they are assigned,
the optional parameters are assigned, and the user is saved.