38
Copyright WeigleWilczek 2009 Das Web-Framework für Scala Heiko Seeberger

W-JAX 09 - Lift

Embed Size (px)

DESCRIPTION

Lift - Das Web-Framework für Scala

Citation preview

Page 1: W-JAX 09 - Lift

Copyright WeigleWilczek 2009

Das Web-Framework für ScalaHeiko Seeberger

Page 2: W-JAX 09 - Lift

2

“Lift is the only new framework in the last four years to offer fresh and innovative approaches to web development. It's not just some

incremental improvements over the status quo, it redefines the state of the art. If you are a web developer, you should learn Lift ...”

WARUM SIND WIR EIGENTLICH HIER?

Michael Galpin, Developer, eBay

Page 3: W-JAX 09 - Lift

WARUM NOCH EIN WEB-FRAMEWORK?

3

Lift pickt Rosinen von anderen Frameworks

Lift bringt eigene innovative Ansätze

Page 4: W-JAX 09 - Lift

DEMO: CHAT MIT 20 ZEILEN SCALA CODE

4

Page 5: W-JAX 09 - Lift

FÜR’S PROTOKOLL

5

• Projekt generieren mit mvn archetype:generate ...

• ChatServer.scala anlegen

• Chat.scala anlegen

• chat.xhtml Template anlegen

• In Boot.scala neues Menu zur SiteMap hinzufügen

Page 6: W-JAX 09 - Lift

DIE ANFÄNGE

6

2006

David Pollak Einfach zu benutzen

Sicher

Einfach zu deployenKeep the meaning

with the bytes

Scala with Sails

Page 7: W-JAX 09 - Lift

HEUTE

7

Lift 1.1 vor der Tür Sehr rege Community

Etliche Sites powered by Lift 32 Committer

Page 8: W-JAX 09 - Lift

FEATURES IM ANGEBOT

8

Templates

Persistenz

AJAX

Comet

User Management

Sitemap

Page 9: W-JAX 09 - Lift

“MUSTERLÖSUNG”

9

Page 10: W-JAX 09 - Lift

WEITERE FEATURES (UNVOLLSTÄNDIG)

10

JSON

JPA und JTA

Textile

Wizards

PayPay

AMPQ

OpenID

OSGi

Page 11: W-JAX 09 - Lift

TEMPLATES

11

Page 12: W-JAX 09 - Lift

<html> <head> <title>kix</title> ... <body> <div class="container"> ... <div class="span-18 last"> <lift:Msgs showAll="true"/> <lift:bind name="content"/> ... </div> <div class="span-12" style="text-align: center;"> <img src="/images/pbww.png"/> </div> ...

mit Lift-Tags

WIE SCHREIBEN WIR TEMPLATES?

12

In XHTML

Page 13: W-JAX 09 - Lift

TEMPLATES VERSCHACHTELN

13

<lift:surround ...>

<lift:bind ... />

Page 14: W-JAX 09 - Lift

class Games { def upcoming5(xhtml: NodeSeq) = bind("games", xhtml, "list" -> bindGames(Game upcoming 5, xhtml))

<lift:surround with="default" at="content"> ... <lift:Games.upcoming5> <games:list> <tr game:class=""> <td><span game:id=""><game:action/></span></td> <td><game:date/></td> <td><game:group/></td> <td><game:location/></td> <td><game:teams/></td> ...

SNIPPETS EINBINDEN

14

Snippet-Tag

Platzhalter imNamespace game

Snippet

Page 15: W-JAX 09 - Lift

class Games {

def upcoming5(xhtml: NodeSeq) = bind("games", xhtml, "list" -> bindGames(Game upcoming 5, xhtml))

private def bindGames(games: List[Game], xhtml: NodeSeq) = { val oddOrEven = OddOrEven() games flatMap { game => bind("game", chooseTemplate("games", "list", xhtml), "date" -> format(game.date.is, locale), "group" -> game.group.is.toString, "location" -> game.location.is, ...

SNIPPETS UND BINDING

15

Platzhalter ersetzen

Page 16: W-JAX 09 - Lift

LIVE DEMO

16

Page 17: W-JAX 09 - Lift

SITEMAP

17

Page 18: W-JAX 09 - Lift

MENÜS UND ZUGRIFFSKONTROLLE

18

Page 19: W-JAX 09 - Lift

SITEMAP ANLEGEN

19

val ifAdmin = If(() => User.superUser_?, () => RedirectResponse("/index"))

val homeMenu = Menu(Loc("home", ("index" :: Nil) -> false, "Home"))...val adminMenu = Menu(Loc("admin", ("admin" :: Nil) -> true, "Admin", ifAdmin), adminSubMenu: _*)

val menus = homeMenu :: ... adminMenu :: User.sitemap

LiftRules setSiteMap SiteMap(menus : _*)

Page 20: W-JAX 09 - Lift

MENÜS ANZEIGEN

20

<html> <head> <title>kix</title> ... <body> <div class="container"> ... <div class="span-5"> <div class="menu"> <lift:Menu.builder/> </div> ...

Page 21: W-JAX 09 - Lift

LIVE DEMO

21

Page 22: W-JAX 09 - Lift

PERSISTENZ

22

Page 23: W-JAX 09 - Lift

MAPPER

23

class Game extends LongKeyedMapper[Game] with IdPK {

object group extends MappedEnum(this, Group) { override def displayName = ?("Group") }

object team1 extends MappedTeam(this, "Team 1")

object team2 extends MappedTeam(this, "Team 2")

object date extends MappedDateTime(this) { override def displayName = ?("Date") }

object location extends MappedString(this, 100) { override def displayName = ?("Location") } ... Keep the meaning

with the bytes

Page 24: W-JAX 09 - Lift

CRUD SUPPORT

24

... with CRUDify[Long, Game]

Page 25: W-JAX 09 - Lift

SCHEMA ANLEGEN

25

val dbVendor = new StandardDBVendor(Props get "db.driver" openOr "org.h2.Driver", Props get "db.url" openOr "jdbc:h2:kix", Empty, Empty) { override def maxPoolSize = Props getInt "db.pool.size" openOr 3}DB.defineConnectionManager(DefaultConnectionIdentifier, dbVendor)Schemifier.schemify(true, Log.infoF _, Team, Game, Result, Tip, User)

Page 26: W-JAX 09 - Lift

LIVE DEMO

26

Page 27: W-JAX 09 - Lift

USER MANAGEMENT

27

Page 28: W-JAX 09 - Lift

CLAUSTHALER-PRINZIP

28

Page 29: W-JAX 09 - Lift

MORE THAN JUST CRUD

29

class User extends MegaProtoUser[User] {

override def shortName = { val s = super.shortName val i = s indexOf "@" if (i == -1) s else s.substring(0, i) }

override def firstNameDisplayName = ?("Name")

object points extends MappedInt(this)}

Page 30: W-JAX 09 - Lift

LIVE DEMO

30

Page 31: W-JAX 09 - Lift

AJAX SUPPORT

31

Page 32: W-JAX 09 - Lift

BEISPIEL: LISTEN-ELEMENTE LÖSCHEN

32

Page 33: W-JAX 09 - Lift

SCALA API FÜR AJAX

33

def editDelete(tip: Tip) = { def delete = { Tip delete_! tip SetHtml(tip.id.is.toString, NodeSeq.Empty) } renderEditDelete(tip, delete _)}

private def renderEditDelete(tip: Tip, jsCmd: () => JsCmd) = link("/tips/edit", () => currentTip(Full(tip)), editImg) ++ Text("") ++ ajaxDeleteImg(ajaxInvoke(jsCmd))

Page 34: W-JAX 09 - Lift

LIVE DEMO

34

Page 35: W-JAX 09 - Lift

COMET SUPPORT

35

Page 36: W-JAX 09 - Lift

CHATTEN LEICHT GEMACHT

36

Page 37: W-JAX 09 - Lift

FRAGEN / DISKUSSION

37