SlideShare ist ein Scribd-Unternehmen logo
1 von 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

Weitere ähnliche Inhalte

Andere mochten auch

Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3Daniel Sikar Amazon Ec2 S3
Daniel Sikar Amazon Ec2 S3
Skills Matter
 
Uncertainty in agile projects
Uncertainty in agile projectsUncertainty in agile projects
Uncertainty in agile projects
Skills Matter
 
Betting On Data Grids
Betting On Data GridsBetting On Data Grids
Betting On Data Grids
Skills Matter
 
Primefaces Nextgen Lju
Primefaces Nextgen LjuPrimefaces Nextgen Lju
Primefaces Nextgen Lju
Skills 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
 

Andere mochten auch (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...
 

Ähnlich wie London Scala UG - Lift:Getting started with Scala

Scala based Lift Framework
Scala based Lift FrameworkScala based Lift Framework
Scala based Lift Framework
vhazrati
 
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
Webtrends
 
Lift 2 0
Lift 2 0Lift 2 0
Lift 2 0
SO
 
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
OSCON Byrum
 
Engage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data CollectionEngage 2013 - Multi Channel Data Collection
Engage 2013 - Multi Channel Data Collection
Webtrends
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegap
yangdj
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver
yangdj
 
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
philogb
 
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
philogb
 

Ähnlich wie 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
 

Mehr von Skills 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 manheim
Skills Matter
 
Russ miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-diveRuss miles-cloudfoundry-deep-dive
Russ miles-cloudfoundry-deep-dive
Skills 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_t
Skills Matter
 

Mehr von 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
 

Kürzlich hochgeladen

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
Enterprise Knowledge
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
Joaquim Jorge
 

Kürzlich hochgeladen (20)

IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
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
 
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
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...Driving Behavioral Change for Information Management through Data-Driven Gree...
Driving Behavioral Change for Information Management through Data-Driven Gree...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
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
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
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
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
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
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
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
 
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
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Artificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and MythsArtificial Intelligence: Facts and Myths
Artificial Intelligence: Facts and Myths
 

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