Elevate your webapps with Scala &   Lift




                           @Sander_Mak
About
Coding      at



  Writing              Blog @
                 branchandbound.net




   Speaking
What should a
webframework
do?
Webframeworks
                        should...
     Provide templating
     Show dynamic content
     Handle user input
     Abstract from request/response
     cycle?
     Be highly interactive?


Preferably: concise, performant, secure
Webframeworks
                                should...
                                 Provide templating
Lift is view-first
   Templates pure HTML5 or XHTML
Embed and surround to compose
                                default.html with:
                                <lift:bind name=”content” />




signup.html with:
<lift:surround with=”default”
   name=”content”>
   <form>
   ... signup form ...
   </form>
<lift:surround />
Webframeworks
                  should...
                 Show dynamic content


Pure templates: no code in
templates
            Problem?
Webframeworks
                  should...
                 Show dynamic content


Pure templates: no code in
templates
            Problem?
Webframeworks
                 should...
                Show dynamic content




Snippets transform DOM to DOM
 NodeSeq => NodeSeq
Guarantee: well-formedness,
sanitized
Use {request, session, database}
state
Webframeworks
                                    should...
                                   Show dynamic content




                Snippet                           View

class IndexSnippet {                   .. surrounding html ..

    def date(in: NodeSeq): NodeSeq =   <lift:indexSnippet.date>
     Helpers.bind("b", in,               <div>Current date:
      "date" -> new Date())                <b:date>
                                            10:00:00 1/1/2012
}                                          </b:date>
                                         </div>
                                       </lift:indexSnippet.date>
Webframeworks
                                    should...
                                   Show dynamic content

                            ‘Operators’ and implicit conversions:
                                   “date”.->(new Date())
                                     results in a tuple:
                                    (“date”, new Date())



                Snippet                                        View

class IndexSnippet {                              .. surrounding html ..

    def date(in: NodeSeq): NodeSeq =              <lift:indexSnippet.date>
     Helpers.bind("b", in,                          <div>Current date:
      "date" -> new Date())                           <b:date>
                                                       10:00:00 1/1/2012
}                                                     </b:date>
                                                    </div>
                                                  </lift:indexSnippet.date>
Webframeworks
                                  should...
                                 Show dynamic content




        Snippet (CSS binding)                           View

class CssSnippet {                   .. surrounding html ..

                                     <div class="lift:cssSnippet.date">
    def date: NodeSeq => NodeSeq =    Current date:
     "#date" #> currentDate           <span id="date">10:00:00
                                          1/1/2012</span>
}                                    </div>

                                     .. surrounding html ..
Webframeworks
                                  should...
                                 Show dynamic content


                                     Constructs a function
                                     NodeSeq => NodeSeq




        Snippet (CSS binding)                                View

class CssSnippet {                       .. surrounding html ..

                                         <div class="lift:cssSnippet.date">
    def date: NodeSeq => NodeSeq =        Current date:
     "#date" #> currentDate               <span id="date">10:00:00
                                              1/1/2012</span>
}                                        </div>

                                         .. surrounding html ..
Webframeworks
                                  should...
                                 Show dynamic content


                                   Implicit conversion from
                                 String to ToCssBindPromoter




        Snippet (CSS binding)                              View

class CssSnippet {                      .. surrounding html ..

                                        <div class="lift:cssSnippet.date">
    def date: NodeSeq => NodeSeq =       Current date:
     "#date" #> currentDate              <span id="date">10:00:00
                                             1/1/2012</span>
}                                       </div>

                                        .. surrounding html ..
Webframeworks
                                  should...
                                 Show dynamic content


                                      With HTML5 may also be
                                     data-lift=”cssSnippet.date”




        Snippet (CSS binding)                                  View

class CssSnippet {                          .. surrounding html ..

                                            <div class="lift:cssSnippet.date">
    def date: NodeSeq => NodeSeq =           Current date:
     "#date" #> currentDate                  <span id="date">10:00:00
                                                 1/1/2012</span>
}                                           </div>

                                            .. surrounding html ..
Webframeworks
                          should...
                         Show dynamic content




No MVC:                          MenuSnippet
View <=> Snippet
                                  NewsSnippet
Many <=> Many
                                  FormSnippet
Webframeworks
                   should...
                   Handle user input

 Add server-side behavior to DOM
 ... with snippets
 Behavior captured in closures
  ... managed by Lift, executed after
submit
 Plain and Ajax requests unified
         Primarily
         stateful!
Webframeworks
                                   should...
                                   Handle user input


               Snippet                              View
class FormSnippet {

    def nameForm = {                .. surrounding html ..
     var name = ""                  <form method="POST"
     def processForm() =            class="lift:FormSnippet.nameForm">
          println(name)                  <input id="nameField"
                                               type="text"/>
      "#nameField" #>                    <input id="submitButton"
                                               type="submit"/>
       SHtml.text(name, name = _)   </form>
    &
      "#submitButton" #>            .. surrounding html ..
       SHtml.submit("Click",
                processForm)
    }
}
Webframeworks
                                   should...
                                   Handle user input

                                        Method within method:
               Snippet                                  View
                                    references name in outer scope

class FormSnippet {

    def nameForm = {                    .. surrounding html ..
     var name = ""                      <form method="POST"
     def processForm() =                class="lift:FormSnippet.nameForm">
          println(name)                      <input id="nameField"
                                                   type="text"/>
      "#nameField" #>                        <input id="submitButton"
                                                   type="submit"/>
       SHtml.text(name, name = _)       </form>
    &
      "#submitButton" #>                .. surrounding html ..
       SHtml.submit("Click",
                processForm)
    }
}
Webframeworks
                                   should...
                                   Handle user input
                                                  Equivalent to:
                                    (inputName: String) => name = inputName
               Snippet                                       View
                                          Closure in shorthand format
class FormSnippet {

    def nameForm = {                         .. surrounding html ..
     var name = ""                           <form method="POST"
     def processForm() =                     class="lift:FormSnippet.nameForm">
          println(name)                           <input id="nameField"
                                                        type="text"/>
      "#nameField" #>                             <input id="submitButton"
                                                        type="submit"/>
       SHtml.text(name, name = _)            </form>
    &
      "#submitButton" #>                     .. surrounding html ..
       SHtml.submit("Click",
                processForm)
    }
}
Webframeworks
                                   should...
                                   Handle user input

                                          Combine 2 CSS transforms
                                    into single aggregated transformation
               Snippet                                     View
                                          def &(other: CssSel): CssSel

class FormSnippet {

    def nameForm = {                       .. surrounding html ..
     var name = ""                         <form method="POST"
     def processForm() =                   class="lift:FormSnippet.nameForm">
          println(name)                         <input id="nameField"
                                                      type="text"/>
      "#nameField" #>                           <input id="submitButton"
                                                      type="submit"/>
       SHtml.text(name, name = _)          </form>
    &
      "#submitButton" #>                   .. surrounding html ..
       SHtml.submit("Click",
                processForm)
    }
}
Webframeworks
                        should...
                        Handle user input
   SHtml components: powerful but low-
   level
                   abstractions:
LiftScreen             Wizard

 Declarative             Multipage wizards
 forms                   Backbutton
 Validation              support
 Strongly typed          ‘Conversations’
Webframeworks
      should...
Comet
‘Reverse Ajax’ or ‘server push’
Realtime webapps




        How to model
        this?
Comet
... with actors!
   Asynchronous
   Mailbox serializes processing
   Lightweight
     Event-driven execution     Local state

                                   Behavior




                      mailbox
Comet
   ... with actors!
       Asynchronous
       Mailbox serializes processing
       Lightweight
          Event-driven execution         Local state

   Send message to actor:                 Behavior
actor ! MyMessage(“payload”)




                               mailbox
Comet
                                 Chat demo setup
               Actor

                  ChatServer


CometActor     CometActor              CometActor


  ChatClient      ChatClient              ChatClient
                                 ...



    Browser            Browser              Browser
                                 ...
Scala + Lift =




Abstraction
Scala + Lift =
          Abstraction


    Wiring UI:
Functional/reactive
  programming
Scala + Lift =
              Abstraction




Other abstractions:
 Mapper (ORM)
 Record (NoSQL)
 REST Helper (sync/async)
 Javascript & JSON DSL
Lift vs Play
Powertool




            vs




                 Polished product
Who uses Lift?
Wrapping up
Designer friendly, logic free views
Concise; leverages Scala
Comet/Ajax integration second to none
Mature framework with great community


Relatively steep learning curve
Documentation slowly improving
Stateful, but no session replication
Questions




Code @ bit.ly/jeeconf-lift



                  branchandbound.ne

                  @Sander_Mak

Scala & Lift (JEEConf 2012)

  • 1.
    Elevate your webappswith Scala & Lift @Sander_Mak
  • 2.
    About Coding at Writing Blog @ branchandbound.net Speaking
  • 3.
  • 4.
    Webframeworks should... Provide templating Show dynamic content Handle user input Abstract from request/response cycle? Be highly interactive? Preferably: concise, performant, secure
  • 5.
    Webframeworks should... Provide templating Lift is view-first Templates pure HTML5 or XHTML Embed and surround to compose default.html with: <lift:bind name=”content” /> signup.html with: <lift:surround with=”default” name=”content”> <form> ... signup form ... </form> <lift:surround />
  • 6.
    Webframeworks should... Show dynamic content Pure templates: no code in templates Problem?
  • 7.
    Webframeworks should... Show dynamic content Pure templates: no code in templates Problem?
  • 8.
    Webframeworks should... Show dynamic content Snippets transform DOM to DOM NodeSeq => NodeSeq Guarantee: well-formedness, sanitized Use {request, session, database} state
  • 9.
    Webframeworks should... Show dynamic content Snippet View class IndexSnippet { .. surrounding html .. def date(in: NodeSeq): NodeSeq = <lift:indexSnippet.date> Helpers.bind("b", in, <div>Current date: "date" -> new Date()) <b:date> 10:00:00 1/1/2012 } </b:date> </div> </lift:indexSnippet.date>
  • 10.
    Webframeworks should... Show dynamic content ‘Operators’ and implicit conversions: “date”.->(new Date()) results in a tuple: (“date”, new Date()) Snippet View class IndexSnippet { .. surrounding html .. def date(in: NodeSeq): NodeSeq = <lift:indexSnippet.date> Helpers.bind("b", in, <div>Current date: "date" -> new Date()) <b:date> 10:00:00 1/1/2012 } </b:date> </div> </lift:indexSnippet.date>
  • 11.
    Webframeworks should... Show dynamic content Snippet (CSS binding) View class CssSnippet { .. surrounding html .. <div class="lift:cssSnippet.date"> def date: NodeSeq => NodeSeq = Current date: "#date" #> currentDate <span id="date">10:00:00 1/1/2012</span> } </div> .. surrounding html ..
  • 12.
    Webframeworks should... Show dynamic content Constructs a function NodeSeq => NodeSeq Snippet (CSS binding) View class CssSnippet { .. surrounding html .. <div class="lift:cssSnippet.date"> def date: NodeSeq => NodeSeq = Current date: "#date" #> currentDate <span id="date">10:00:00 1/1/2012</span> } </div> .. surrounding html ..
  • 13.
    Webframeworks should... Show dynamic content Implicit conversion from String to ToCssBindPromoter Snippet (CSS binding) View class CssSnippet { .. surrounding html .. <div class="lift:cssSnippet.date"> def date: NodeSeq => NodeSeq = Current date: "#date" #> currentDate <span id="date">10:00:00 1/1/2012</span> } </div> .. surrounding html ..
  • 14.
    Webframeworks should... Show dynamic content With HTML5 may also be data-lift=”cssSnippet.date” Snippet (CSS binding) View class CssSnippet { .. surrounding html .. <div class="lift:cssSnippet.date"> def date: NodeSeq => NodeSeq = Current date: "#date" #> currentDate <span id="date">10:00:00 1/1/2012</span> } </div> .. surrounding html ..
  • 15.
    Webframeworks should... Show dynamic content No MVC: MenuSnippet View <=> Snippet NewsSnippet Many <=> Many FormSnippet
  • 16.
    Webframeworks should... Handle user input Add server-side behavior to DOM ... with snippets Behavior captured in closures ... managed by Lift, executed after submit Plain and Ajax requests unified Primarily stateful!
  • 17.
    Webframeworks should... Handle user input Snippet View class FormSnippet { def nameForm = { .. surrounding html .. var name = "" <form method="POST" def processForm() = class="lift:FormSnippet.nameForm"> println(name) <input id="nameField" type="text"/> "#nameField" #> <input id="submitButton" type="submit"/> SHtml.text(name, name = _) </form> & "#submitButton" #> .. surrounding html .. SHtml.submit("Click", processForm) } }
  • 18.
    Webframeworks should... Handle user input Method within method: Snippet View references name in outer scope class FormSnippet { def nameForm = { .. surrounding html .. var name = "" <form method="POST" def processForm() = class="lift:FormSnippet.nameForm"> println(name) <input id="nameField" type="text"/> "#nameField" #> <input id="submitButton" type="submit"/> SHtml.text(name, name = _) </form> & "#submitButton" #> .. surrounding html .. SHtml.submit("Click", processForm) } }
  • 19.
    Webframeworks should... Handle user input Equivalent to: (inputName: String) => name = inputName Snippet View Closure in shorthand format class FormSnippet { def nameForm = { .. surrounding html .. var name = "" <form method="POST" def processForm() = class="lift:FormSnippet.nameForm"> println(name) <input id="nameField" type="text"/> "#nameField" #> <input id="submitButton" type="submit"/> SHtml.text(name, name = _) </form> & "#submitButton" #> .. surrounding html .. SHtml.submit("Click", processForm) } }
  • 20.
    Webframeworks should... Handle user input Combine 2 CSS transforms into single aggregated transformation Snippet View def &(other: CssSel): CssSel class FormSnippet { def nameForm = { .. surrounding html .. var name = "" <form method="POST" def processForm() = class="lift:FormSnippet.nameForm"> println(name) <input id="nameField" type="text"/> "#nameField" #> <input id="submitButton" type="submit"/> SHtml.text(name, name = _) </form> & "#submitButton" #> .. surrounding html .. SHtml.submit("Click", processForm) } }
  • 21.
    Webframeworks should... Handle user input SHtml components: powerful but low- level abstractions: LiftScreen Wizard Declarative Multipage wizards forms Backbutton Validation support Strongly typed ‘Conversations’
  • 22.
    Webframeworks should...
  • 23.
    Comet ‘Reverse Ajax’ or‘server push’ Realtime webapps How to model this?
  • 24.
    Comet ... with actors! Asynchronous Mailbox serializes processing Lightweight Event-driven execution Local state Behavior mailbox
  • 25.
    Comet ... with actors! Asynchronous Mailbox serializes processing Lightweight Event-driven execution Local state Send message to actor: Behavior actor ! MyMessage(“payload”) mailbox
  • 26.
    Comet Chat demo setup Actor ChatServer CometActor CometActor CometActor ChatClient ChatClient ChatClient ... Browser Browser Browser ...
  • 27.
    Scala + Lift= Abstraction
  • 28.
    Scala + Lift= Abstraction Wiring UI: Functional/reactive programming
  • 29.
    Scala + Lift= Abstraction Other abstractions: Mapper (ORM) Record (NoSQL) REST Helper (sync/async) Javascript & JSON DSL
  • 30.
    Lift vs Play Powertool vs Polished product
  • 31.
  • 32.
    Wrapping up Designer friendly,logic free views Concise; leverages Scala Comet/Ajax integration second to none Mature framework with great community Relatively steep learning curve Documentation slowly improving Stateful, but no session replication
  • 33.
    Questions Code @ bit.ly/jeeconf-lift branchandbound.ne @Sander_Mak

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 \n
  • #5 \n
  • #6 Designer-friendly\n\nDemo master layout\n
  • #7 \n
  • #8 \n
  • #9 \n
  • #10 Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
  • #11 Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
  • #12 Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
  • #13 Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
  • #14 Show code: Boot class and IndexSnippet. Explain designer-friendly templating based on code. Start with date example, also table to show multiple lines of output\n
  • #15 \n
  • #16 \n
  • #17 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #18 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #19 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #20 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #21 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #22 Show NameSnippet, introduce S object (with notices), stateful part\n
  • #23 First show Ajax autocomplete\n
  • #24 \n
  • #25 you can have millions of actors per JVM\n
  • #26 you can have millions of actors per JVM\n
  • #27 \n
  • #28 \n
  • #29 \n
  • #30 Documentation, err msg/dev experience: Play better\nView-first vs MVC with code in templates + Servlet based vs. custom HTTP stack\nLift: security, more freedom (more rope to hang yourself), Play more handholding\nLift doesn&amp;#x2019;t give one true way\n
  • #31 \n
  • #32 \n
  • #33 \n