If you can't read please download the document
Upload
peter-robinett
View
2.315
Download
0
Embed Size (px)
Citation preview
The Lift Framework for
Fun and Profit
Peter [email protected] VI, 2010-06-30
Who am I?
Background in web programming with interpreted languages (PHP, Python, Javascript, etc)
Likes long walks on the beaches
Lift + Scala programmer for one year
Loves both cats AND dogs
Lift committer for approx. 6 months BUT only has minor commit to lift-flot to my name
Likes fine wine and smooth jazz
BUT active on mailing list and wiki
Isn't very good at making funny bullet points
What is Lift?
Lift is an expressive and elegant framework for writing web applications.
Lift stresses the importance of security, maintainability, scalability and performance, while allowing for high levels of developer productivity.
Lift is inspired by Seaside, Rails, Django, Wicket, and beyond.
Why Fun?
Comet
class AskName extends CometActor { def render = ajaxForm(What is your username? ++ text("",name => answer(name.trim)) ++ )}
class Chat extends CometActor with CometListener { private var userName = "" private var chats: List[ChatLine] = Nil private lazy val infoId = uniqueId + "_info" private lazy val infoIn = uniqueId + "_in" private lazy val inputArea = findKids(defaultXml, "chat", "input") private lazy val bodyArea = findKids(defaultXml, "chat", "body") private lazy val singleLine = deepFindKids(bodyArea, "chat", "list")
// handle an update to the chat lists // by diffing the lists and then sending a partial update // to the browser override def lowPriority = { case ChatServerUpdate(value) => val update = (value -- chats).reverse.map(b => AppendHtml(infoId, line(b))) partialUpdate(update) chats = value }
// render the input area by binding the // appropriate dynamically generated code to the // view supplied by the template override lazy val fixedRender: Box[NodeSeq] = ajaxForm(After(100, SetValueAndFocus(infoIn, "")), bind("chat", inputArea, "input" -> text("", sendMessage _, "id" -> infoIn)))
// send a message to the chat server private def sendMessage(msg: String) = ChatServer ! ChatServerMsg(userName, msg.trim)
// display a line private def line(c: ChatLine) = bind("list", singleLine, "when" -> hourFormat(c.when), "who" -> c.user, "msg" -> c.msg)
// display a list of chats private def displayList(in: NodeSeq): NodeSeq = chats.reverse.flatMap(line)
// render the whole list of chats override def render = bind("chat", bodyArea, "name" -> userName, AttrBindParam("id", Text(infoId), "id"), "list" -> displayList _)
// setup the component override def localSetup { askForName super.localSetup }
// register as a listener def registerWith = ChatServer
// ask for the user's name private def askForName { if (userName.length == 0) { ask(new AskName, "what's your username") { case s: String if (s.trim.length > 2) => userName = s.trim reRender(true)
case _ => askForName reRender(false) } } }}
The Community
Why Profitable?
Why Scala?
All the normal reasons, plus...
The time is .
class Clock extends CometActor { override def defaultPrefix = Full("clock") // schedule a ping every 10 seconds so we redraw ActorPing.schedule(this, Tick, 10 seconds)
private lazy val spanId = uniqueId+"_timespan"
def render = { bind("time" -> timeSpan) }
def timeSpan = ({timeNow})
override def lowPriority = { case Tick => partialUpdate(SetHtml(spanId, Text(timeNow.toString))) ActorPing.schedule(this, Tick, 10 seconds) }}
case object Tick
Actors
Allows great AJAX, Comet support.
BUT, there were issues with the EFPL library so David wrote LiftActor. This is actually a proof of Scala's strength.
XHTML Processing
Template:
Hi . It's now .
Snippet:
import java.util.Dateimport scala.xml.{NodeSeq, Text}import net.liftweb.util.Helpers.bind
object DuSE { def sayHello(xhtml: NodeSeq): NodeSeq = { User.currentUser.map(user => { bind(DuSE, xhtml, name -> Text(user.shortName), datetime -> Text((new Date).toString) ) }) openOr You didn't log in! }}
Routing
Routing is done via SiteMap...
LiftRules.statefulRewrite.prepend({ case RewriteRequest(ParsePath("app" :: appID :: "index" :: Nil, _, _,_), GetRequest, _) => RewriteResponse("app":: "view" :: Nil, Map("appID" -> appID)})
... and redirects with partial functions!
val entries = Menu(Loc(App Page, app :: view :: Nil, App Page) :: NilLiftRules.setSiteMap(SiteMap(entries :_*))
Regex Free!
What is Lift good at?
Comet, also AJAX
X(HT)ML processing
JSON
REST
As much or as little as you want done for you
Secure
Fast execution, fast development (IF you already know Lift)
Great code:functionality ratio
What is Lift bad at?
High learning curve
Stateless request/response cycle (but is possible)
View-first, not MVC
I.E. Does some things differently
Statefulness can lead to lots of stuff in memory if you're not careful
By Markus Ltkemeyerhttp://flickr.com/photos/helico/2245863081/
How to get Lifted?
High-as-a-kite bg image?
A Digression on Versions
By Alan Sunghttp://flickr.com/photos/clsung/310886130/
Conclusion?
2.0-SNAPSHOT is quite stable
RCs are really stable, only important bug fixes are added. We're at 2.0-RC2.
Milestones are very stable. Last one was 2.0-M6.
If you have crazy rules requiring that you MUST use 'official' releases, wait a week for 2.0.
Moral of the story: DON'T use 1.x.
PS Scala 2.8 support in 280_port_refresh, should see 3.0-SNAPSHOT after the 2.0 release.
Join the Google Group
http://groups.google.com/group/liftweb
Read the Getting Started Guide
http://www.liftweb.net/docs/getting_started.html
Skim the Wiki
http://www.assembla.com/wiki/show/liftweb/
Checkout the Scaladocs
http://scala-tools.org/mvnsites-snapshots/liftweb/
Clone the code
http://github.com/lift/lift *
* Yep, since last night we've been using the new GitHub organizations feature. We're cutting edge like that.
Use an Archetype
lift-archetype-basic
lift-archetype-blank
lift-archetype-jpa-basic
lift-archetyp-jpa-blank-single
lift-archetyp-jpa-blank
lift-archetyp-sbt
sbt
simple-build-tool is THE way to do Scala projects.
See http://www.assembla.com/wiki/show/liftweb/Using_SBT
OR
git clone git://github.com/dpp/lift_sbt_prototype.git
Then cd into lift_sbt_prototype and type:sbt
At the sbt prompt, type:update
Then:jetty-run
Point your browser to http://localhost:8080/
$ git clone ...$ sbt ...
Mads Hartmann is working on sbt processors for Google Summer of Code. It should be awesome.
Maven
http://www.assembla.com/wiki/show/liftweb/Using_Maven
mvn archetype:generate \ -DarchetypeGroupId=net.liftweb \ -DarchetypeArtifactId=lift-archetype-blank \ -DarchetypeVersion=2.0-SNAPSHOT \ -DarchetypeRepository=http://scala-tools.org/repo-snapshots \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DgroupId=your.groupId \ -DartifactId=your.artifactId
mvn jetty:run
mvn scala:cc(jRebel license: http://www.zeroturnaround.com/scala-license/)
Demos and Examples
http://demo.liftweb.net/
http://github.com/lift/lift/tree/master/examples/
http://github.com/dpp/lift-samples
http://www.liftweb.net
Questions?
By Gillian Maniscalcohttp://flickr.com/photos/gillian_m/448800043/