SlideShare uma empresa Scribd logo
1 de 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

Mais conteúdo relacionado

Destaque

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
 

Destaque (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...
 

Semelhante a 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
 

Semelhante a 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
 

Mais de 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
 

Mais de 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
 

Último

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
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodJuan lago vázquez
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdflior mazor
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...apidays
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...DianaGray10
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonAnna Loughnan Colquhoun
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businesspanagenda
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...apidays
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FMESafe Software
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsJoaquim Jorge
 
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
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
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
 
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
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProduct Anonymous
 
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
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Scriptwesley chun
 

Último (20)

+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
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...
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
GenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdfGenAI Risks & Security Meetup 01052024.pdf
GenAI Risks & Security Meetup 01052024.pdf
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
Connector Corner: Accelerate revenue generation using UiPath API-centric busi...
 
Data Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt RobisonData Cloud, More than a CDP by Matt Robison
Data Cloud, More than a CDP by Matt Robison
 
Why Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire businessWhy Teams call analytics are critical to your entire business
Why Teams call analytics are critical to your entire business
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
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
 
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
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
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
 
Automating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps ScriptAutomating Google Workspace (GWS) & more with Apps Script
Automating Google Workspace (GWS) & more with Apps Script
 

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