SlideShare a Scribd company logo
1 of 34
Getting started with Lift
       Richard Dallaway, @d6y
         richard@taykt.com
lsug.org
Struts       Play      GWT        Seam

 Rails    Spring MVC    JSF     WebObjects

Grails       PHP       Cocoon     Seaside

Stripes    JAX-RS      Wicket      Lift
Struts       Play        GWT       Seam

        Rails    Spring MVC      JSF    WebObjects

       Grails       PHP        Cocoon     Seaside

       Stripes    JAX-RS       Wicket      Lift

Zero                                                Plenty
                           Weirdness
http://liftweb.net
Versions

1.0.3   Updated Jan 2010

2.0 M2 Released Feb 2010


  both for Scala 2.7.7
$ find . -name lift* -depth 2 -type d

lift-base/lift-actor          lift-modules/lift-paypal
lift-base/lift-common         lift-modules/lift-testkit
lift-base/lift-json           lift-modules/lift-textile
lift-base/lift-util           lift-modules/lift-widgets
lift-base/lift-webkit         lift-modules/lift-wizard
                              lift-modules/lift-xmpp
lift-modules/lift-amqp
lift-modules/lift-facebook    lift-persistence/lift-couchdb
lift-modules/lift-imaging     lift-persistence/lift-jpa
lift-modules/lift-jta         lift-persistence/lift-mapper
lift-modules/lift-ldap        lift-persistence/lift-record
lift-modules/lift-machine
lift-modules/lift-oauth
lift-modules/lift-openid
lift-modules/lift-osgi
Agenda

• Part I: View first
• Part II: Doing stuff quickly
• Part III: Ajax
• Part IV: Real time web
The time on this server is: Mon Mar 08 18:40:51 GMT 2010.
<html xmlns="http://www.w3.org/1999/xhtml">
 <body>
   <h1>Hello world</h1>

  <p>The time on this server is:
       <lift:Time.now>
          time appears here
       </lift:Time.now>
  </p>

 </body>
</html>
package com.myproject.snippet

import scala.xml.NodeSeq

class Time {

    // My <lift:Time.now /> implementation:
    def now(xhtml: NodeSeq) =
        <span>{new java.util.Date()}</span>

}
<html xmlns="http://www.w3.org/1999/xhtml">
 <body>
   <h1>Hello world</h1>

  <lift:Time.now>
   <p>It’s <when:day/> at <when:hour/>.</p>
  </lift:Time.now>

 </body>
</html>
package com.myproject.snippet

import scala.xml.{NodeSeq,Text}
import net.liftweb.util.Helpers._

class Time {

    def now(xhtml:NodeSeq) = {
      val day = "Monday"
      val hour = "7 o'clock"
      bind("when", xhtml,
       "hour" -> <span>{hour}</span>,
       "day" -> Text(day) )
    }
}
<html xmlns="http://www.w3.org/1999/xhtml">

<body>

<h1>Hello Canada</h1>

<lift:Olympics.results>
    <table>
        <table:rows>
        <tr>
             <td><r:country>Country here</r:country></td>
             <td><r:golds>Gold medal count</r:golds></td>
        </tr>
        </table:rows>
    </table>
</lift:Olympics.results>

</body>


</html>
package com.myprojects.snippet

import scala.xml.NodeSeq
import net.liftweb.util.Helpers._

class Olympics {

    case class Golds(country: String, medals: Int)

    def results(xhtml: NodeSeq) = {

        val vancouver = Golds("CAN", 14) :: Golds("GER", 10) ::
                        Golds("GBR", 1) :: Nil

        // <table:rows> <r:country/> <r:golds/> </table:rows>
        bind("table", xhtml,
        ! ! "rows" -> vancouver.flatMap( gold =>
                 bind("r", chooseTemplate("table", "rows", xhtml),
                       "country" -> gold.country,
                       "golds" -> gold.medals )
                 )
        )
    }

}
$ mvn archetype:generate 
 -DarchetypeCatalog=http://scala-tools.org/
Choose archetype:
1: http://scala-tools.org/ -> scala-archetype-simple (A simple scala project)
2: http://scala-tools.org/ -> lift-archetype-blank (A blank/empty liftweb project)
3: http://scala-tools.org/ -> lift-archetype-basic (A basic liftweb project (with DB, css, ...))
Choose a number: (1/2/3):
$ mvn archetype:generate 
 -DarchetypeGroupId=net.liftweb 
 -DarchetypeArtifactId=lift-archetype-blank 
 -DarchetypeVersion=2.0-M2 
 -DremoteRepositories=http://scala-tools.org/repo-releases 
 -DgroupId=com.example.proj
package com.brightonbloggers.admin.model

import   net.liftweb.common._
import   net.liftweb.util._
import   net.liftweb.mapper._
import   net.liftweb.http._

class Blog extends LongKeyedMapper[Blog] with IdPK {

  def getSingleton = Blog

  object title extends MappedString(this, 20)

  object url extends MappedString(this, 100) {
    override def validations = isUrl _ :: super.validations
  }

  def isUrl(u:String) = if (url startsWith "http")
!     ! !   !   !   !   !    Nil
!     ! !   !   !   !   else
!     ! !   !   !   !   !    List(FieldError(url, S.?("field.url.error")))
}

object Blog extends Blog with LongKeyedMetaMapper[Blog] with CRUDify[Long,Blog]
{
}
<lift:surround with="default" at="content">

    <h1>Ajax blog</h1>

    <div id="list">

    <lift:Blogs.list>

        <ul>
           <directory:entry />
        </ul>

        <directory:new_blog />

    </lift:Blogs.list>

    </div>

</lift:surround>
import com.brightonbloggers.admin.model.Blog

import     scala.xml._
import     net.liftweb.common._
import     net.liftweb.mapper._
import     net.liftweb.http.SHtml._
import     net.liftweb.http.js.JsCmds._
import     net.liftweb.util.Helpers._
import     net.liftweb.http.S._

class Blogs {

        def list(xhtml: NodeSeq): NodeSeq = {
!
        def add_new_blog(s: String) = {
          Blog.create.url(s).title(s).save
          SetHtml( "list", list(xhtml) )
        }

        bind("directory", xhtml,
        ! ! "entry" -> Blog.findAll().flatMap(
                               b => <li>{b.url}</li> ),
        ! ! "new_blog" -> ajaxText("", add_new_blog _)
        )

    }

}
package com.brightonbloggers.admin.snippet

import com.brightonbloggers.admin.model.Blog

import     scala.xml._
import     net.liftweb.common._
import     net.liftweb.mapper._
import     net.liftweb.http.SHtml._
import     net.liftweb.http.js.JsCmds._
import     net.liftweb.util.Helpers._
import     net.liftweb.http.S._

class Blogs {

    def list(xhtml: NodeSeq): NodeSeq = {
!
        def add_new_blog(s: String) = {
          Blog.create.url(s).title(s).save
          SetHtml("list", list(xhtml) )
        }

        def update_blog(blog: Blog)(new_value: String) = {
           blog.url(new_value).save
           SetHtml("list", list(xhtml) )
        }

        def click_to_edit(blog: Blog) : NodeSeq =
        !!   swappable( <li>{blog.url}</li>,
        !!   !           ajaxText(blog.url, update_blog(blog) _ ) )

        bind("directory", xhtml,
        !!   "entry" -> Blog.findAll().flatMap( click_to_edit _ ),
        !!   "new_blog" -> ajaxText("", add_new_blog _)
        )

    }
}
User Activity




                                                                    Client Processing




                                 Comet Event Bus
                         Event
                                                   Initialization

                                                   Data Push
                         Event                                                          Displa
                                                                                               y
                                                   Data Push
                                                                                        Displa
                                                                                               y



                         Event
                                                   Data Push
                         Event                                                          Displa
                                                                                               y
                                                   Data Push
                                                                                        Displa
                                                                                               y


                         Event
                                                   Data Push
Server-Side Processing


                                                                                        Displa
                                                                                               y
def list(xhtml: NodeSeq): NodeSeq = {
!
     def countable(blog: Blog) : NodeSeq =
     !    <li>{link("/static/list",
            () => { StatsServer ! blog },
             Text(blog.url)) }</li>

     bind("directory", xhtml,
     ! ! "entry" -> Blog.findAll().flatMap(countable _)
     )
package com.brightonbloggers.admin.comet

import   net.liftweb.http._
import   net.liftweb.common._
import   net.liftweb.util.Helpers._
import   net.liftweb.http.js._
import   net.liftweb.actor._
import   net.liftweb.http.js.JsCmds._
import   scala.xml._

object StatsServer extends LiftActor with ListenerManager {

    var count = 0

    override def lowPriority = {
      case b =>
        count = count + 1
        updateListeners()
    }

    def createUpdate = count
}


// <lift:comet type=”StatsWatch” />
class StatsWatch extends CometActor with CometListenee {

    def registerWith = StatsServer

    override def render = <div id="total">0</div>

    override def lowPriority = {
      case count: Int =>
        partialUpdate(SetHtml("total", Text(count.toString)))
    }

}
Thank you.
• Lift book: http://groups.google.com/group/
  the-lift-book
• Liftweb.net: Wiki, mailing list, getting started
  guide
• Visit lsug.org, join the meetup.com group
apress discount code

 LONDONSCALAUQUCUAVGLT
Next Meeting

 Traits & Mixins
 Kevin
 Monday 12 April
 Here, Skillsmatter
London Scala UG - Lift:Getting started with Scala

More Related Content

Viewers also liked

Joe Baguley Cloud Camp London7 Ppt
Joe Baguley Cloud Camp London7 PptJoe Baguley Cloud Camp London7 Ppt
Joe Baguley Cloud Camp London7 PptSkills Matter
 
Building mobile web application with Grails, by Sebastien Blanc, presented at...
Building mobile web application with Grails, by Sebastien Blanc, presented at...Building mobile web application with Grails, by Sebastien Blanc, presented at...
Building mobile web application with Grails, by Sebastien Blanc, presented at...Skills Matter
 
Databases -- Have it Your Way (Frederick Cheung)
Databases -- Have it Your Way (Frederick Cheung)Databases -- Have it Your Way (Frederick Cheung)
Databases -- Have it Your Way (Frederick Cheung)Skills Matter
 
Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3Skills Matter
 
Uncertainty in agile projects
Uncertainty in agile projectsUncertainty in agile projects
Uncertainty in agile projectsSkills Matter
 
Betting On Data Grids
Betting On Data GridsBetting On Data Grids
Betting On Data GridsSkills Matter
 
Journey To Systemic Improvement Lean Exchange Dec 2009 David J
Journey To Systemic Improvement Lean Exchange Dec 2009 David JJourney To Systemic Improvement Lean Exchange Dec 2009 David J
Journey To Systemic Improvement Lean Exchange Dec 2009 David JSkills Matter
 
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Chris Richardson
 
Seth Edwards on MongoDB
Seth Edwards on MongoDBSeth Edwards on MongoDB
Seth Edwards on MongoDBSkills Matter
 
Command Query Responsibility Segregation
Command Query Responsibility SegregationCommand Query Responsibility Segregation
Command Query Responsibility SegregationSkills Matter
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen LjuSkills Matter
 
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...Amazon Web Services
 

Viewers also liked (13)

Joe Baguley Cloud Camp London7 Ppt
Joe Baguley Cloud Camp London7 PptJoe Baguley Cloud Camp London7 Ppt
Joe Baguley Cloud Camp London7 Ppt
 
Building mobile web application with Grails, by Sebastien Blanc, presented at...
Building mobile web application with Grails, by Sebastien Blanc, presented at...Building mobile web application with Grails, by Sebastien Blanc, presented at...
Building mobile web application with Grails, by Sebastien Blanc, presented at...
 
Databases -- Have it Your Way (Frederick Cheung)
Databases -- Have it Your Way (Frederick Cheung)Databases -- Have it Your Way (Frederick Cheung)
Databases -- Have it Your Way (Frederick Cheung)
 
Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3
 
Uncertainty in agile projects
Uncertainty in agile projectsUncertainty in agile projects
Uncertainty in agile projects
 
Why Cqrs
Why CqrsWhy Cqrs
Why Cqrs
 
Betting On Data Grids
Betting On Data GridsBetting On Data Grids
Betting On Data Grids
 
Journey To Systemic Improvement Lean Exchange Dec 2009 David J
Journey To Systemic Improvement Lean Exchange Dec 2009 David JJourney To Systemic Improvement Lean Exchange Dec 2009 David J
Journey To Systemic Improvement Lean Exchange Dec 2009 David J
 
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
Developing and Deploying Java applications on the Amazon Elastic Compute Clou...
 
Seth Edwards on MongoDB
Seth Edwards on MongoDBSeth Edwards on MongoDB
Seth Edwards on MongoDB
 
Command Query Responsibility Segregation
Command Query Responsibility SegregationCommand Query Responsibility Segregation
Command Query Responsibility Segregation
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
 
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...
Auto-Scaling Web Application Security in Amazon Web Services (SEC308) | AWS r...
 

Similar to London Scala UG - Lift:Getting started with Scala

Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Frameworkvhazrati
 
Engage 2013 - Why Upgrade to v10 Tag
Engage 2013 - Why Upgrade to v10 TagEngage 2013 - Why Upgrade to v10 Tag
Engage 2013 - Why Upgrade to v10 TagWebtrends
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0SO
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of usOSCON Byrum
 
Engage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data CollectionEngage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data CollectionWebtrends
 
Implementing and Visualizing Clickstream data with MongoDB
Implementing and Visualizing Clickstream data with MongoDBImplementing and Visualizing Clickstream data with MongoDB
Implementing and Visualizing Clickstream data with MongoDBMongoDB
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testingsmontanari
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEAndrzej Ludwikowski
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegapyangdj
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaveryangdj
 
Everything is Awesome - Cutting the Corners off the Web
Everything is Awesome - Cutting the Corners off the WebEverything is Awesome - Cutting the Corners off the Web
Everything is Awesome - Cutting the Corners off the WebJames Rakich
 
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSJavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSphilogb
 
JavaScript para Graficos y Visualizacion de Datos
JavaScript para Graficos y Visualizacion de DatosJavaScript para Graficos y Visualizacion de Datos
JavaScript para Graficos y Visualizacion de Datosphilogb
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
Whats New for WPF in .NET 4.5
Whats New for WPF in .NET 4.5Whats New for WPF in .NET 4.5
Whats New for WPF in .NET 4.5Rainer Stropek
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every dayVadym Khondar
 
Data visualization in python/Django
Data visualization in python/DjangoData visualization in python/Django
Data visualization in python/Djangokenluck2001
 
Integrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applicationsIntegrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applicationslucenerevolution
 

Similar to London Scala UG - Lift:Getting started with Scala (20)

Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
 
Engage 2013 - Why Upgrade to v10 Tag
Engage 2013 - Why Upgrade to v10 TagEngage 2013 - Why Upgrade to v10 Tag
Engage 2013 - Why Upgrade to v10 Tag
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of us
 
Engage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data CollectionEngage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data Collection
 
Serverless Java on Kubernetes
Serverless Java on KubernetesServerless Java on Kubernetes
Serverless Java on Kubernetes
 
Implementing and Visualizing Clickstream data with MongoDB
Implementing and Visualizing Clickstream data with MongoDBImplementing and Visualizing Clickstream data with MongoDB
Implementing and Visualizing Clickstream data with MongoDB
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testing
 
Event Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BEEvent Sourcing - what could go wrong - Devoxx BE
Event Sourcing - what could go wrong - Devoxx BE
 
Ajax-Tutorial
Ajax-TutorialAjax-Tutorial
Ajax-Tutorial
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegap
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver
 
Everything is Awesome - Cutting the Corners off the Web
Everything is Awesome - Cutting the Corners off the WebEverything is Awesome - Cutting the Corners off the Web
Everything is Awesome - Cutting the Corners off the Web
 
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJSJavaScript para Graficos y Visualizacion de Datos - BogotaJS
JavaScript para Graficos y Visualizacion de Datos - BogotaJS
 
JavaScript para Graficos y Visualizacion de Datos
JavaScript para Graficos y Visualizacion de DatosJavaScript para Graficos y Visualizacion de Datos
JavaScript para Graficos y Visualizacion de Datos
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Whats New for WPF in .NET 4.5
Whats New for WPF in .NET 4.5Whats New for WPF in .NET 4.5
Whats New for WPF in .NET 4.5
 
Reactive programming every day
Reactive programming every dayReactive programming every day
Reactive programming every day
 
Data visualization in python/Django
Data visualization in python/DjangoData visualization in python/Django
Data visualization in python/Django
 
Integrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applicationsIntegrate Solr with real-time stream processing applications
Integrate Solr with real-time stream processing applications
 

More from Skills Matter

5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard LawrenceSkills Matter
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applicationsSkills Matter
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmScala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmSkills Matter
 
Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimSkills Matter
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Skills Matter
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlCukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlSkills Matter
 
Cukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsCukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsSkills Matter
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Skills Matter
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Skills Matter
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldProgressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldSkills Matter
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Skills Matter
 
Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Skills Matter
 
A poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingA poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingSkills Matter
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveSkills Matter
 
Simon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSimon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSkills Matter
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tSkills Matter
 

More from Skills Matter (20)

5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence5 things cucumber is bad at by Richard Lawrence
5 things cucumber is bad at by Richard Lawrence
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
 
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvmScala e xchange 2013 haoyi li on metascala a tiny diy jvm
Scala e xchange 2013 haoyi li on metascala a tiny diy jvm
 
Oscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheimOscar reiken jr on our success at manheim
Oscar reiken jr on our success at manheim
 
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
Progressive f# tutorials nyc dmitry mozorov & jack pappas on code quotations ...
 
Cukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberlCukeup nyc ian dees on elixir, erlang, and cucumberl
Cukeup nyc ian dees on elixir, erlang, and cucumberl
 
Cukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.jsCukeup nyc peter bell on getting started with cucumber.js
Cukeup nyc peter bell on getting started with cucumber.js
 
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
Agile testing & bdd e xchange nyc 2013 jeffrey davidson & lav pathak & sam ho...
 
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
Progressive f# tutorials nyc rachel reese & phil trelford on try f# from zero...
 
Progressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source worldProgressive f# tutorials nyc don syme on keynote f# in the open source world
Progressive f# tutorials nyc don syme on keynote f# in the open source world
 
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
Agile testing & bdd e xchange nyc 2013 gojko adzic on bond villain guide to s...
 
Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#Dmitry mozorov on code quotations code as-data for f#
Dmitry mozorov on code quotations code as-data for f#
 
A poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testingA poet's guide_to_acceptance_testing
A poet's guide_to_acceptance_testing
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
 
Serendipity-neo4j
Serendipity-neo4jSerendipity-neo4j
Serendipity-neo4j
 
Simon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelismSimon Peyton Jones: Managing parallelism
Simon Peyton Jones: Managing parallelism
 
Plug 20110217
Plug   20110217Plug   20110217
Plug 20110217
 
Lug presentation
Lug presentationLug presentation
Lug presentation
 
I went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_tI went to_a_communications_workshop_and_they_t
I went to_a_communications_workshop_and_they_t
 
Plug saiku
Plug   saikuPlug   saiku
Plug saiku
 

Recently uploaded

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUK Journal
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024The Digital Insurer
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?Antenna Manufacturer Coco
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherRemote DBA Services
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024The Digital Insurer
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 

Recently uploaded (20)

How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdfUnderstanding Discord NSFW Servers A Guide for Responsible Users.pdf
Understanding Discord NSFW Servers A Guide for Responsible Users.pdf
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?What Are The Drone Anti-jamming Systems Technology?
What Are The Drone Anti-jamming Systems Technology?
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 

London Scala UG - Lift:Getting started with Scala

  • 1. Getting started with Lift Richard Dallaway, @d6y richard@taykt.com
  • 3.
  • 4. Struts Play GWT Seam Rails Spring MVC JSF WebObjects Grails PHP Cocoon Seaside Stripes JAX-RS Wicket Lift
  • 5. Struts Play GWT Seam Rails Spring MVC JSF WebObjects Grails PHP Cocoon Seaside Stripes JAX-RS Wicket Lift Zero Plenty Weirdness
  • 7. Versions 1.0.3 Updated Jan 2010 2.0 M2 Released Feb 2010 both for Scala 2.7.7
  • 8.
  • 9.
  • 10. $ find . -name lift* -depth 2 -type d lift-base/lift-actor lift-modules/lift-paypal lift-base/lift-common lift-modules/lift-testkit lift-base/lift-json lift-modules/lift-textile lift-base/lift-util lift-modules/lift-widgets lift-base/lift-webkit lift-modules/lift-wizard lift-modules/lift-xmpp lift-modules/lift-amqp lift-modules/lift-facebook lift-persistence/lift-couchdb lift-modules/lift-imaging lift-persistence/lift-jpa lift-modules/lift-jta lift-persistence/lift-mapper lift-modules/lift-ldap lift-persistence/lift-record lift-modules/lift-machine lift-modules/lift-oauth lift-modules/lift-openid lift-modules/lift-osgi
  • 11. Agenda • Part I: View first • Part II: Doing stuff quickly • Part III: Ajax • Part IV: Real time web
  • 12. The time on this server is: Mon Mar 08 18:40:51 GMT 2010.
  • 13. <html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello world</h1> <p>The time on this server is: <lift:Time.now> time appears here </lift:Time.now> </p> </body> </html>
  • 14. package com.myproject.snippet import scala.xml.NodeSeq class Time { // My <lift:Time.now /> implementation: def now(xhtml: NodeSeq) = <span>{new java.util.Date()}</span> }
  • 15. <html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello world</h1> <lift:Time.now> <p>It’s <when:day/> at <when:hour/>.</p> </lift:Time.now> </body> </html>
  • 16. package com.myproject.snippet import scala.xml.{NodeSeq,Text} import net.liftweb.util.Helpers._ class Time { def now(xhtml:NodeSeq) = { val day = "Monday" val hour = "7 o'clock" bind("when", xhtml, "hour" -> <span>{hour}</span>, "day" -> Text(day) ) } }
  • 17.
  • 18. <html xmlns="http://www.w3.org/1999/xhtml"> <body> <h1>Hello Canada</h1> <lift:Olympics.results> <table> <table:rows> <tr> <td><r:country>Country here</r:country></td> <td><r:golds>Gold medal count</r:golds></td> </tr> </table:rows> </table> </lift:Olympics.results> </body> </html>
  • 19. package com.myprojects.snippet import scala.xml.NodeSeq import net.liftweb.util.Helpers._ class Olympics { case class Golds(country: String, medals: Int) def results(xhtml: NodeSeq) = { val vancouver = Golds("CAN", 14) :: Golds("GER", 10) :: Golds("GBR", 1) :: Nil // <table:rows> <r:country/> <r:golds/> </table:rows> bind("table", xhtml, ! ! "rows" -> vancouver.flatMap( gold => bind("r", chooseTemplate("table", "rows", xhtml), "country" -> gold.country, "golds" -> gold.medals ) ) ) } }
  • 20.
  • 21. $ mvn archetype:generate -DarchetypeCatalog=http://scala-tools.org/ Choose archetype: 1: http://scala-tools.org/ -> scala-archetype-simple (A simple scala project) 2: http://scala-tools.org/ -> lift-archetype-blank (A blank/empty liftweb project) 3: http://scala-tools.org/ -> lift-archetype-basic (A basic liftweb project (with DB, css, ...)) Choose a number: (1/2/3):
  • 22. $ mvn archetype:generate -DarchetypeGroupId=net.liftweb -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=2.0-M2 -DremoteRepositories=http://scala-tools.org/repo-releases -DgroupId=com.example.proj
  • 23. package com.brightonbloggers.admin.model import net.liftweb.common._ import net.liftweb.util._ import net.liftweb.mapper._ import net.liftweb.http._ class Blog extends LongKeyedMapper[Blog] with IdPK { def getSingleton = Blog object title extends MappedString(this, 20) object url extends MappedString(this, 100) { override def validations = isUrl _ :: super.validations } def isUrl(u:String) = if (url startsWith "http") ! ! ! ! ! ! ! Nil ! ! ! ! ! ! else ! ! ! ! ! ! ! List(FieldError(url, S.?("field.url.error"))) } object Blog extends Blog with LongKeyedMetaMapper[Blog] with CRUDify[Long,Blog] { }
  • 24. <lift:surround with="default" at="content"> <h1>Ajax blog</h1> <div id="list"> <lift:Blogs.list> <ul> <directory:entry /> </ul> <directory:new_blog /> </lift:Blogs.list> </div> </lift:surround>
  • 25. import com.brightonbloggers.admin.model.Blog import scala.xml._ import net.liftweb.common._ import net.liftweb.mapper._ import net.liftweb.http.SHtml._ import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import net.liftweb.http.S._ class Blogs { def list(xhtml: NodeSeq): NodeSeq = { ! def add_new_blog(s: String) = { Blog.create.url(s).title(s).save SetHtml( "list", list(xhtml) ) } bind("directory", xhtml, ! ! "entry" -> Blog.findAll().flatMap( b => <li>{b.url}</li> ), ! ! "new_blog" -> ajaxText("", add_new_blog _) ) } }
  • 26. package com.brightonbloggers.admin.snippet import com.brightonbloggers.admin.model.Blog import scala.xml._ import net.liftweb.common._ import net.liftweb.mapper._ import net.liftweb.http.SHtml._ import net.liftweb.http.js.JsCmds._ import net.liftweb.util.Helpers._ import net.liftweb.http.S._ class Blogs { def list(xhtml: NodeSeq): NodeSeq = { ! def add_new_blog(s: String) = { Blog.create.url(s).title(s).save SetHtml("list", list(xhtml) ) } def update_blog(blog: Blog)(new_value: String) = { blog.url(new_value).save SetHtml("list", list(xhtml) ) } def click_to_edit(blog: Blog) : NodeSeq = !! swappable( <li>{blog.url}</li>, !! ! ajaxText(blog.url, update_blog(blog) _ ) ) bind("directory", xhtml, !! "entry" -> Blog.findAll().flatMap( click_to_edit _ ), !! "new_blog" -> ajaxText("", add_new_blog _) ) } }
  • 27.
  • 28. User Activity Client Processing Comet Event Bus Event Initialization Data Push Event Displa y Data Push Displa y Event Data Push Event Displa y Data Push Displa y Event Data Push Server-Side Processing Displa y
  • 29. def list(xhtml: NodeSeq): NodeSeq = { ! def countable(blog: Blog) : NodeSeq = ! <li>{link("/static/list", () => { StatsServer ! blog }, Text(blog.url)) }</li> bind("directory", xhtml, ! ! "entry" -> Blog.findAll().flatMap(countable _) )
  • 30. package com.brightonbloggers.admin.comet import net.liftweb.http._ import net.liftweb.common._ import net.liftweb.util.Helpers._ import net.liftweb.http.js._ import net.liftweb.actor._ import net.liftweb.http.js.JsCmds._ import scala.xml._ object StatsServer extends LiftActor with ListenerManager { var count = 0 override def lowPriority = { case b => count = count + 1 updateListeners() } def createUpdate = count } // <lift:comet type=”StatsWatch” /> class StatsWatch extends CometActor with CometListenee { def registerWith = StatsServer override def render = <div id="total">0</div> override def lowPriority = { case count: Int => partialUpdate(SetHtml("total", Text(count.toString))) } }
  • 31. Thank you. • Lift book: http://groups.google.com/group/ the-lift-book • Liftweb.net: Wiki, mailing list, getting started guide • Visit lsug.org, join the meetup.com group
  • 32. apress discount code LONDONSCALAUQUCUAVGLT
  • 33. Next Meeting Traits & Mixins Kevin Monday 12 April Here, Skillsmatter