More Related Content Similar to Lift Presentation at DuSE VI Similar to Lift Presentation at DuSE VI (20) Lift Presentation at DuSE VI1. The Lift Framework for Fun and Profit Peter Robinett [email_address] for DUSE VI, 2010-06-30 12. 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. 15. Comet class AskName extends CometActor { def render = ajaxForm(<div>What is your username?</div> ++ text("",name => answer(name.trim)) ++ <input type="submit" value="Enter"/>) } 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) } } } } 21. <lift:comet type=”Clock”> The time is <clock:time />. </lift:comet> 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 = (<span id={spanId}>{timeNow}</span>) 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. 22. XHTML Processing Template: <lift:DuSE.sayHello> Hi <DuSE:name />. It's now <DuSE:datetime />. </lift:DuSE.sayHello> Snippet: import java.util.Date import 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 <div>You didn't log in!</div> } } 23. 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”) :: Nil LiftRules.setSiteMap(SiteMap(entries :_*)) Regex Free! 42. RCs are really stable, only important bug fixes are added. We're at 2.0-RC2. 44. If you have crazy rules requiring that you MUST use 'official' releases, wait a week for 2.0. 46. PS Scala 2.8 support in 280_port_refresh, should see 3.0-SNAPSHOT after the 2.0 release. 58. 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. 59. 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/) 60. 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 Editor's Notes High-as-a-kite bg image?