Your SlideShare is downloading. ×
Java Magazin - Lift
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×
Saving this for later? Get the SlideShare app to save on your phone or tablet. Read anywhere, anytime – even offline.
Text the download link to your phone
Standard text messaging rates apply

Java Magazin - Lift

1,667
views

Published on

Published in: Technology

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
1,667
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
11
Comments
0
Likes
0
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide

Transcript

  • 1. Web Lift-Webframework Twitter nachgebaut mit Lift Wer sich mit Scala beschäftigt, kommt an Lift nicht vorbei: Wie kaum ein anderes Produkt hat dieses innovative Webframework dazu beigetragen, das Scala-Ökosystem aufzubauen. In diesem Artikel zeigen wir anhand eines konkreten Fallbeispiels die Gründe für diesen Erfolg. von Heiko Seeberger und Johannes Hohenbichler as könnte als Vorlage besser anderen Benutzern folgen und natürlich noch unter dem Namen Scala with Sails. geeignet sein als Twitter [1]? das Nachrichtenverschicken und -an- Sein Ziel war und ist es noch heute, ein Einerseits dürfte es kaum je- zeigen unter Verwendung der Web-2.0- einfach zu benutzendes, sicheres und manden in unserer Branche geben, der Features Ajax und Comet. Doch bevor höchst produktives Webframework zu diese Art des Zwitscherns nicht kennt. wir uns die Hände schmutzig machen, schaffen. Dazu bedient sich Lift der bes- Andererseits steht Twitter trotz über- ein kurzer Überblick über Lift. ten Konzepte anderer Frameworks und schaubarem Funktionsumfang gera- ergänzt sie um eigene innovative Ideen. dezu idealtypisch für heutige moderne Von den Ursprüngen bis heute Beispiele für dieses Rosinenpicken sind Webapplikationen. Wir werden mit Im Jahr 2006 startete David Pollak [2], an Wicket [3] angelehnte Templates, Chatter – unserem Nachbau – die wich- inspiriert von vielfältigen Erfahrungen CRUD-Unterstützung wie bei Rails tigsten Features auf vereinfachte Weise mit Programmiersprachen und Frame- [4] oder Djangos [5] „More than just umsetzen: Registrieren und Anmelden, works, die Arbeit an Lift, ursprünglich CRUD“ bei der Benutzerverwaltung. 52 javamagazin 5|2010 www.JAXenter.de
  • 2. Lift-Webframework Web Heute sehen wir eine große und sehr le- Abb. 1: Initia- bendige Lift-Community mit mehr als le Startseite zehn aktiven Committern und etliche produktive Anwendungen auf Basis von Lift, z. B. Foursquare.com [6] oder ESME [7]. Derzeit befindet sich bereits die Ver- sion 2.0 in der Entwicklung, die vermut- lich auf Scala 2.8 aufsetzen wird. unter weiglewilczek.com/labs/chatter Eine Anmerkung: Selbstverständ- einen Blick auf die laufende Anwendung lich unterstützt Lift internationalisierte Ein modularer Baukasten in Endausbaustufe werfen. Einfach mit Anwendungen, aber um die Dinge noch Lift bringt als „Full Stack Framework“ E-Mail-Adresse registrieren und dann einfacher zu halten, blenden wir das hier alles mit, um eine komplette Webappli- loslegen. Zum Testen am besten mit zwei aus und halten uns konsequent an Eng- kation zu entwickeln. Dazu gehören unterschiedlichen Browsern, um die Ak- lisch. typischerweise Templates, Menüs und tualisierung der Nachrichten via Comet Zugriffskontrolle, Persistenz, CRUD- sehen zu können. Lift konfigurieren Support und eine komplette Benutzer- Den kompletten Sourcecode gibt Natürlich müss en w ir uns erer verwaltung. Aber auch ausgefallenere es unter der Eclipse Public License bei Webapplikation beibringen, dass sie Features wie PayPal-Anbindung, Open- github.com/weiglewilczek/chatter zum „geliftet“ ist, und das tun wir über ei- ID- oder OAuth-Schnittstellen sowie Browsen oder Herunterladen. Die ein- nen Servlet-Filter in web.xml. Scala ist Support für JSON-APIs werden ange- zelnen Schritte, in denen wir Chatter so flexibel und ausdrucksstark, dass boten. Doch es gibt keinen Grund, vor entwickeln werden, sind mit Tags (z. B. Lift selbst auf Konfigurationsdateien dieser Fülle an Features zu erschrecken. 0.1-template) versehen, sodass Sie die in XML verzichten kann. Stattdessen Lift ist modular aufgebaut und wir kön- Entwicklung im Sourcecode nachvoll- wird Lift in der Scala-Klasse Boot kon- nen wählen, was wir verwenden möch- ziehen können. Selbstverständlich sind figuriert, die per Default im Verzeichnis ten und was nicht. So können wir z. B. die Tickets für Fehler oder Erweiterungs- liftweb.bootstrap erwartet wird, bei uns mit lift-mapper mitgelieferte Benutzer- wünsche sehr gern gesehen. aber via Servlet-Filter-Parameter nach verwaltung verwenden oder auch eine com.weiglewilczek.chatter verschoben eigene bzw. vorhandene. Das Projekt aufsetzen ist. Neben einigen nützlichen Vorgaben Lift nutzt selbst Maven [9] und bietet für Formatierung und Internationa- Ein funktionales Framework uns mit verschiedenen Maven Arti- lisierung enthält Boot eine besonders Wozu eigentlich ein weiteres Webframe- facts eine sehr angenehme Möglichkeit, wichtige Zeile: LiftRules addToPackages work? Löst Lift unsere täglichen Aufga- unser Projekt aufzusetzen. Selbstver- getClass.getPackage. Hiermit bestim- ben anders und vor allem auch besser ständlich können wir Lift-Projekte auch men wir, dass Lift im Package com. als andere? Dank Scala: Ja. Eine kürzlich in der IDE unserer Wahl oder mit Ant weiglewilczek.chatter nach Sub-Pa- durchgeführte Umfrage auf JAXenter entwickeln, aber für Chatter bleiben ckages für Snippets und Comet-Klassen [8] hat ergeben, dass für die Leser Scala wir Maven treu, weil das einiges verein- – dazu später mehr – suchen soll. die JVM-Sprache mit dem größten Po- facht, insbesondere das Management tenzial ist. Und dieses Potenzial hebt Lift, der Abhängigkeiten. Wir verwenden Templates für das UI indem es insbesondere die funktiona- Lift 2.0-SNAPSHOT , d. h. den aktuel- Wie erstellen wir eigentlich Webseiten len Features, Traits sowie das mächtige len Entwicklungsstand für die Version mit Lift? Am einfachsten mit Templates: Typsystem von Scala nutzt. Ein gutes 2.0 sowie Maven 2.2.1. Mit dem Arti- Das sind XHTML-Seiten, die keiner- Beispiel hierfür: Wenn ein Formular- fact lift-archetype-basic erhalten wir ein lei Logik enthalten. Doch wie kommen feld übertragen oder ein Button geklickt einfaches Projekttemplate. Da wir hier dann die dynamischen Elemente auf die wird, dann soll etwas passieren, und das grundlegende CSS- und Scala-Kennt- Seite? Das funktioniert ähnlich wie bei geben wir in Lift einfach in Form von nisse voraussetzen, reichern wir unser Wicket, nur dass wir bei Lift nicht über Funktionen an. Dies entspricht viel bes- Projekt ohne weitere Erläuterungen um IDs, sondern über spezielle Elemente ser unserem intuitiven Verständnis, als ein Stylesheet sowie Hilfsklassen für mit eigenen Namespaces gehen, die so- z. B. die Kapselung in Form- und Con- die Locale-abhängige Datumsforma- zusagen als Platzhalter für den dynami- troller-Klassen, wie wir sie bei typischen tierung an. Nach ein wenig Tuning von schen Inhalt stehen. OO-Frameworks finden. POM und Projektstruktur erhalten wir unser Projekttemplate. Chatter in Action Um Chatter lokal laufen zu lassen, Listing 1 : index.xhtml Bevor wir loslegen, sollten wir uns eine genügt es, mvn jetty:run im Projektver- <lift:surround with="default" at="content"> Vorstellung davon machen, was wir im zeichnis abzusetzen. Dann können wir <div>Welcome to Chatter</div> Folgenden Schritt für Schritt entwi- unter http://localhost:8080 auf die Start- </lift:surround> ckeln. Das geht am besten, indem wir seite zugreifen (Abb. 1). www.JAXenter.de javamagazin 5|2010 53
  • 3. Web Lift-Webframework Besonders praktisch: Templates kön- lift:ChatterInput. Damit referenzieren bzw. anzumelden. Lift bringt mit dem nen verschachtelt werden. Im Verzeich- wir das Snippet ChatterInput, eine Sca- Persistenzmodul lift-mapper für relati- nis templates-hidden liegt unser „Wur- la-Klasse, die für das Dynamisieren des onale Datenbanken eine komplette Be- zeltemplate“ default.xhtml. Es enthält Inhalts zuständig ist. Im Inhalt selbst fin- nutzerverwaltung mit anpassbarem UI das HTML-Skelett für all unsere Seiten. den wir die statischen HTML-Elemente und Persistenz mit. Wir verwenden den Über ein spezielles Element aus dem lift und zwei spezielle Platzhalterelemente Trait MegaProtoUser (zugegeben, das ist Namespace definieren wir einen Anker- im chatter Namespace. Wir haben die ein komischer Name), der Attribute wie punkt, um den eigentlichen Inhalt ein- freie Wahl bei der Benennung des Name- E-Mail, Passwort, Vor- und Nachname zubinden: <lift:bind name="content"/>. spaces und müssen nur darauf achten, etc. besitzt und missbrauchen den Vor- Doch was wird dort eingebunden? dass das betroffene Snippet ihn auflöst. namen als einzigen Namen, indem wir Das ist der Inhalt aus dem Template, das Genau das tut ChatterInput in der ren- den Anzeigenamen ändern (Listing 4). wir aufrufen, also z. B. von der Seite in- der-Methode (Listing 3). Durch die Im dazugehörigen Companion dex.xhtml. Diese ist, wie in Listing 1 dar- bind-Methode werden die Elemente Object, zu dem wir den Trait MetaMe- gestellt, nur ein Fragment einer XHTML chatter:text und chatter:submit durch gaProtoUser mixen, konfigurieren wir -Seite. Mittels lift:surround geben wir die HTML-Elemente für eine Textarea unter anderem, welche Attribute wir das Template und den Ankerpunkt an, und einen Submit-Button ersetzt. Der verwenden, dass wir auf E-Mail-Validie- sodass die Willkommensnachricht in Methode textarea übergeben wir einen rung verzichten und dass die Seiten für das Default-Template eingebettet wird. leeren String als Default-Wert und eine Registrierung, Log-in etc. von unserem Funktion, die ausgeführt wird, sobald Default-Template umgeben sein sollen Interaktionen mit Snippets das Formular zum Server geschickt (Listing 5). Nun wollen wir als Erstes eine Eingabe- wird. In unserem Fall loggen wir einfach Wie aktivieren wir nun unsere Be- möglichkeit für Nachrichten schaffen, die Eingabedaten. Die Methode submit nutzerverwaltung? Indem wir in Boot d. h. wir benötigen ein Formular. Wie erwartet eine Bezeichnung für den Sub- zum einen eine Datenbankverbindung bereits erwähnt, setzt Lift zur Bearbei- mit-Button sowie ebenfalls eine Funkti- konfigurieren und zum anderen unse- tung von Formularen auf Funktionen. In on. Hier tun wir allerdings nichts. re User-Klasse mittels Schemifier.sche- unserem Fall wollen wir erst einmal nur mify in das Datenbankschema bringen die Eingabe loggen. Dazu nehmen wir Ready-to-use- (Listing 6). Das funktioniert so ähnlich ein Formular in unser Template für die Benutzerverwaltung wie in Hibernate die Einstellung ddl. Startseite auf (Listing 2). Wir umgeben Als Nächstes wollen wir uns darum küm- auto. Wir verwenden hier H2 [10] im In- den Inhalt mit dem speziellen Element mern, uns als Benutzer zu registrieren Process-Modus als Datenbank, aber lift- Listing 2 : index.xhtml Listing 5 : User.scala <lift:surround with="default" at="content"> object User extends User with MetaMegaProtoUser[User] { <lift:ChatterInput form="post"> override def signupFields = firstName :: email :: password :: Nil <div>What's happening?</div> override def skipEmailValidation = true <div><chatter:text/></div> ... <div class="right"><chatter:submit/></div> <hr/> Listing 6 : Boot.scala </lift:ChatterInput> </lift:surround> ... val dbVendor = new StandardDBVendor(Props get "db.driver" openOr "org.h2.Driver", Listing 3 : ChatterInput.scala Props get "db.url" openOr "jdbc:h2:chatter", class ChatterInput extends Logging { Props get "db.user", def render(xhtml: NodeSeq) = { Props get "db.password") { def handleUpdate(text: String) { override def maxPoolSize = Props getInt "db.pool.size" openOr 3 logger debug "Sending message: %s".format(text) } } DB.defineConnectionManager(DefaultConnectionIdentifier, dbVendor) bind("chatter", xhtml, Schemifier.schemify(true, Log infoF _, User) "text" -> textarea("", handleUpdate _), ... "submit" -> submit("Update", () => ())) } Listing 7 : Boot.scala } ... val ifLoggedIn = If(() => User.loggedIn_?, Listing 4 : User.scala () => RedirectResponse(User.loginPageURL)) class User extends MegaProtoUser[User] { val homeMenu = Menu(Loc("home", List("index"),"Home", ifLoggedIn)) override def firstNameDisplayName = "Name" val menus = homeMenu :: User.menus override def getSingleton = User LiftRules setSiteMap SiteMap(menus: _*) ... 54 javamagazin 5|2010 www.JAXenter.de
  • 4. Anzeige Agile Projekte – stabil oder fragil? Um agile Projekte zu skalieren, brauchen Teams die passenden Werkzeuge Agile Prozesse mit agilen Praktiken haben sich in vielen Projekten des Repositories herstellen. Beim Chatten erkennt das System bewährt. Zu den Erfolgskriterien agiler Projekte zählt die gelunge- automatisch Schlüsselwörter wie „Task“ oder „Story“ und erzeugt ne Zusammenarbeit. Daher sind die Teams von überschaubarer zusammen mit einer Nummer den Link zum entsprechenden Größe. Idealerweise arbeiten sie zusammen in einem Zimmer, an Work-Item. Der Chat-Partner kann diesen Link anklicken und hat einer gemeinsamen Werkbank. Aber lässt sich dieses dynamische dann ebenfalls das Work-Item auf dem Schirm. Der Chat kann im Setting auch auf andere, größere Projekte übertragen, damit der Kontext weiter gehen. Erfolg der agilen Projekte auch auf diese abstrahlt? Das Problem: Je höher man Projekte skaliert, desto weiter entfernt Eigenschaften in die IDE integrieren man sich von den bekannten Erfolgsvoraussetzungen: Das Team Dies alles ist nur dann bequem möglich, wenn all diese Eigen- ist nicht mehr überschaubar und häu g über mehrere Standorte schaften in die IDE der Entwickler eingebettet sind. Das leistet IBM verteilt. Außerdem gehören die Mitglieder oft verschiedenen Orga- Rational Team Concert durch die Integration des Clients sowohl in nisationen an, arbeiten beispielsweise bei einer Partner rma oder Eclipse als auch in Visual Studio .NET. einem Zulieferer. Continuous Integration ist eine weitere wichtige Praxis in agilen Diese Veränderung der Rahmenbedingungen führt zu Problemen in Projekten. Sie hat bei großen, verteilten Projekten eine besondere der Kommunikation und behindert die Abstimmung innerhalb des Bedeutung, denn hier können Integrationsprobleme besonders Teams. Der Informations uss ist gestört, und damit verliert man unangenehm und aufwändig werden. Daher ist ein Source-Code- einen der wichtigsten Vorteile der agilen Prozesse. Bewährte Tech- Management-System unabdingbar, das auch standortübergreifend niken wie das Arbeiten mit Taskboards funktionieren nicht mehr. einsetzbar ist. Durch ein solches System können alle Entwickler auf den Quellcode zugreifen und diesen leicht integrieren. Moderne Werkzeuge entschärfen Probleme Diese Probleme lassen sich mit modernen Werkzeugen zur agilen Bei Fehlern alten Zustand wiederherstellen Planung entschärfen. Ganz wichtig dabei ist ein gemeinsames In Rational Team Concert ndet man eine enge Verzahnung mit Repository, in dem sich alle Artefakte des Projektes be nden dem Build-Management-System. Kontinuierlich und einfach lassen und den Teammitgliedern zur Verfügung stehen. Damit sind die sich lokale und globale Builds erstellen. Bei Fehlern können die Backlogs mit ihren Stories, Epics und Tasks für alle immer sichtbar. Mitarbeiter über einen Snapshot des Repositories den alten Zu- Produktverantwortliche und Teammitglieder werden bei der Ver- stand ohne viel Aufwand wiederherstellen. waltung des Backlogs deutlich entlastet. Auch das Taskboard lässt Dieses gemeinsame Repository macht auch eine leistungsfähige sich elektronisch p egen, was den Projektfortschritt wieder für alle Verknüpfung zwischen Quellcode und Stories bzw. Work-Items sichtbar macht. Gra ken über den Zustand des Projektes wie zum möglich. Per Knopfdruck ndet man heraus, warum welche Pro- Beispiel Burndown-Charts lassen sich automatisiert erstellen und grammzeile von wem verändert wurde. Der umgekehrte Fall ist fast spiegeln immer einen aktuellen Projektstand wider. noch wichtiger: Welche Änderungen waren nötig, um eine Story zu Damit lassen sich agile Vorgehensmodelle, wie zum Beispiel realisieren oder um einen Fehler zu beheben? Nur so lassen sich Scrum, bereits sehr ef zient einsetzen. Dennoch bleibt es bei der behobene Fehler auch in mehreren Versionen sicher nachkorrigie- Fülle von Informationen für die Teammitglieder schwierig, die für sie ren. wichtigen und relevanten Informationen zu verfolgen und zu erfas- Agile Vorgehensweisen lassen sich nur skalieren, wenn den Teammit- sen. Arbeiten zum Beispiel mehrere Personen an unterschiedlichen gliedern dafür die geeigneten Werkzeuge zur Verfügung stehen. IBM Standorten an einer Story, so fällt es allen Beteiligten schwer, sich hat diese Erfahrung bei der Entwicklung von Rational Team Concert ständig zu synchronisieren. Kontinuierlich treffen im Repository selbst gemacht und genutzt. Denn das IBM-Entwicklerteam hat bei verfeinerte Anforderungen seitens der Business-Owner ein. Um der Arbeit bereits Alphaversionen des Produkts verwendet und die diese Änderungen alle zur Kenntnis zu nehmen, müssten die Team- frischen Erfahrungen nahtlos in der Weiterentwicklung und Vollen- mitglieder fortlaufend das Repository durchforsten. dung der Software umgesetzt. Dabei ist mit Rational Team Concert Viel praktischer und leichter ist es hingegen, wenn die Teammitglie- eine vollständig interaktive Entwicklungsumgebung für größere, der Änderungen im Repository per RSS-Feed erhalten. In diesem unternehmensweite Teams entstanden. Ein Werkzeug, mit dem sich Fall bekommen sie sofort eine Nachricht im eigenen Event-Log, Agilität skalieren lässt. wenn sich in der Story etwas ändert. Sie sind also immer auf dem aktuellen Stand der Informationen. Dieser Event-Log ist individu- Interesse? ell auf den Mitarbeiter zugeschnitten: Er kann selbst auswählen, über welche Veränderungen er informiert werden will. Auf diese Dann setzen Sie sich noch heute mit uns in Verbindung. Weise ießen die Informationen, die in agilen Projekten in den Daily Ansprechpartner: Werner Schoepe Stand-Ups weitergegeben werden, auch standortübergreifend. Telefon: +49-211-476-2163 E-Mail: werner.schoepe@de.ibm.com Anforderungen „just in time“ festhalten Weitere Infos und Downloads nden sich unter: www.ibm.com/software/products/de/de/rtc-standard Die Stories und Tasks spielen im Repository eine zentrale Rolle beim Informationsaustausch. Hier können die Anforderungen oder direkt auf der Community Site: „just in time“ festgehalten werden. Zusätzlich bieten sie Rubri- www.jazz.net ken für Diskussionen. So kann man im virtuellen Team Probleme und Fragestellungen gleich im Kontext der Stories erörtern. Die Treffen Sie Werner Schoepe auf der JAX 2010 – zu seinem Vortrag entsprechenden Änderungen sehen die Beteiligten sofort in ihrem „Die neue Herausforderung: Skalierung von agilen Projekten!“ Event-Log. am Montag, 3. Mai, 11:45 – 12:30 Uhr Instant Messaging ist heute an vielen Arbeitsplätzen Standard. Oder auf dem IBM-Stand. Integriert in die IDE lässt sich auch hier ein Kontext zu Objekten
  • 5. Web Lift-Webframework mapper unterstützt natürlich alle gängi- kümmert sich um Menüs und optio- cken bzw. empfangene Nachrichten gen relationalen Datenbanken. nale Zugriffskontrolle. Hier definieren anzeigen. Dazu ergänzen wir als Erstes wir das Home-Menü, sodass wir nur als unser Formular um einen Bereich zur Menüs und Zugriffskontrolle angemeldete Benutzer Zugriff haben, Anzeige der Nachrichten (Listing 8). Jetzt müssen wir dafür sorgen, dass nur sowie das Menü für die Benutzerverwal- Ähnlich wie ein Snippet, referenzieren angemeldete Benutzer Chatter verwen- tung, das wir von unserer User-Klasse wir mit dem Element lift:comet und des- den können. Dazu müssen wir erst noch quasi geschenkt bekommen. sen type-Attribut eine Klasse, die sich das Menü und die Seiten der Benutzer- um Comet kümmert. Weiter finden wir verwaltung anzeigen. Das konfigurieren Chat mit Ajax und Comet im Template einen Block mit statischen wir wiederum in Boot, indem wir eine So weit, so gut, aber das Wichtigste fehlt HTML-Elementen und Platzhaltern zur Sitemap definieren (Listing 7). Diese noch: Wir wollen Nachrichten verschi- Anzeige einer Nachricht. Listing 8 Listing 11 : ChatterInput.scala ... ... <lift:comet type="ChatterMessages"> def handleUpdate(text: String) { <messages:list> val message = ChatterMessage(user.id.is, user.shortName, now, text.trim) <div> logger debug "Sending Chatter message to server: %s".format(message) <span class="messageName"><message:name/></span> ChatterServer ! message <span class="messageDate"><message:date/></span> } <message:text/> ... </div> </messages:list> Listing 12 : ChatterServer.scala </lift:comet> ... object ChatterServer extends LiftActor with ListenerManager with Logging { private var message: ChatterMessage = _ Listing 9 : ChatterMessages.scala override def lowPriority = { case message @ ChatterMessage(_, _, _, text) if !text.isEmpty => { class ChatterMessages extends CometActor with logger debug "Received Chatter message: %s".format(message) CometListener with Logging { this.message = message private var messages = List[ChatterMessage]() updateListeners() override def render = { } def bindMessages(template: NodeSeq): NodeSeq = messages flatMap { m => } bind("message", template, override protected def createUpdate = message "name" -> m.name, } "date" -> format(m.date, boxedSessionLocale), "text" -> m.text) Listing 13 : UserFollowingUser.scala } logger debug "Rendering messages: %s".format(messages) object UserFollowingUser extends UserFollowingUser bind("messages", defaultXml, "list" -> bindMessages _) with LongKeyedMetaMapper[UserFollowingUser] { } def following_?(u: User, userId: Long) = override def lowPriority = { find(By(user, u), By(following, userId)).isDefined case message: ChatterMessage => { def findAllFollowers = User.currentUser map { u => logger debug "Received Chatter message: %s".format(message) User findAll In(User.id, user, By(following, u)) messages ::= message } openOr Nil reRender(false) ... } } } override def registerWith = ChatterServer class UserFollowingUser extends LongKeyedMapper[UserFollowingUser] } with IdPK with Logging { val user = new MappedLongForeignKey(this, User) {} Listing 10 : ChatterInput.scala val following = new MappedLongForeignKey(this, User) {} ... ... } ajaxForm(After(100, SetValueAndFocus(messageId, "")), bind("chatter", xhtml, Listing 14 : ChatterMessages.scala "name" -> user.shortName, "text" -> textarea("", handleUpdate _, "id" -> messageId), override def shouldUpdate = { "submit" -> submit("Update", () => ()))) case ChatterMessage(userId, _, _, _) => ... if (user.id.is == userId) true else following_?(user, userId) } 56 javamagazin 5|2010 www.JAXenter.de
  • 6. Lift-Webframework Web Unsere Comet-Klasse ChatterMes- sages, dargestellt in Listing 9, kümmert sich um das Empfangen und die Anzei- ge der Nachrichten. Sie ist ein CometAc- tor und ein CometListener: Mit der Me- thode lowPriority werden eingehende Nachrichten entgegengenommen und threadsafe verarbeitet. Für die Anzeige ist die Methode render verantwortlich, die sich den Nachrichtenblock aus dem Template schnappt und damit jede ein- zelne Nachricht darstellt. Wie beim Snippet weiter oben, werden die Platz- halter durch die anzuzeigenden Daten ersetzt, hier Absendername, Datum und Abb. 2: Chatter in Endaus-baustufe Text der Nachricht. Durch registerWith meldet sich unsere Comet-Klasse beim ChatterServer (siehe unten) an. Nun müssen wir noch das Versen- wir schon folgen, als auch die Möglichkeit Menüs, Zugriffskontrolle, Persistenz, den von Nachrichten ergänzen. Zuerst bietet, weiteren Benutzern zu folgen. Der Benutzerverwaltung und vieles mehr machen wir aus unserem Eingabefor- Vollständigkeit halber möchten wir na- fertig zur Verfügung. Das macht klar, mular ein Ajax-Formular, denn wir türlich auch sehen, wer uns folgt, sodass warum Lift heute eine herausragende wollen nicht bei jedem Versenden einer wir auch ein Template followers.xhtml be- Position im Scala-Ökosystem einnimmt. Nachricht die Seite neu laden. Dies geht nötigen. Die Interaktionen setzen wir mit Bleibt nur die Frage, wann Sie sich mit mit Lift wirklich einfach (Listing 10), dem Follow-Snippet um. Diese Templates Lift befassen? denn Lift abstrahiert Ajax durch ein Sca- und dieses Snippet sind ganz ähnlich ge- la-API. Hier umgeben wir bloß unseren strickt wie die bisherigen, sodass wir hier existierenden Code im ChatterInput- auf Listings verzichten – bei Interesse bitte Heiko Seeberger ist Snippet mit der Methode ajaxForm, der einfach in den Sourcecode schauen. geschäftsführender Gesell- schafter der Weigle Wilczek wir zusätzlich noch ein JavaScript-Kom- Natürlich müssen wir diese Informa- GmbH und verantwortlich mando mitgeben, das die Textarea kurz tionen persistieren: Die Mapper-Klasse für die technologische Stra- nach dem Verschicken der Nachricht UserFollowingUser kümmert sich um die- tegie des Unternehmens mit leert. se Referenzen von einem Benutzer auf an- den Schwerpunkten Java, Scala, OSGi, Eclipse RCP und Lift. Zudem ist er Dann müssen wir, statt nur zu loggen, dere und das dazu gehörende Companion aktiver Open Source Committer, Autor nun tatsächlich eine Nachricht verschi- Object bietet uns die nötigen Methoden zahlreicher Fachartikel und Redner auf cken. Dazu erweitern wir die handleUp- für unser Follow Snippet bzw. die Chat- einschlägigen Konferenzen. date-Methode im ChatterInput-Snippet terMessages (Listing 13). Wir erweitern Johannes Hohenbichler ist Soft- wareentwickler bei der Weigle Wilczek (Listing 11). Wir erzeugen eine Chat- nun noch unsere ChatterMessage um die GmbH und definiert seinen technologi- terMessage mit Absendername, Datum ID des Absenders und teilen dem Chatter- schen Schwerpunkt im Bereich Eclipse und Text und schicken sie an den Chat- Server über die Methode shouldUpdate in RCP, OSGi, Scala und Lift. terServer (Listing 12). Letzterer ist ein ChatterMessages mit, ob wir eine Nach- LiftActor und ein ListenerManager, d. h. richt empfangen wollen: Das wollen wir er kann Nachrichten empfangen, die er genau dann, wenn wir selbst der Absender an (zunächst noch) alle Listener schickt, sind oder wenn wir dem Absender folgen Links & Literatur indem er updateListeners aufruft. (Listing 14). Damit hätten wir es geschafft: [1] http://www.twitter.com Chatter erstrahlt in voller Pracht (Abb. 2). [2] http://liftweb.net/team.html Persistenz mit Mapper [3] http://wicket.apache.org OK, damit sind wir fast schon fertig. Nun Fazit [4] http://rubyonrails.org müssen wir Chatter nur noch so erweitern, Dieser schnelle Überblick über einige [5] http://www.djangoproject.com dass Nachrichten nicht an alle geschickt der wichtigsten Features von Lift zeigt, [6] http://foursquare.com werden, sondern nur an unsere Freunde, wie produktiv wir mit Lift Webapplika- [7] http://incubator.apache.org/esme d. h. diejenigen, die uns folgen. Dazu müs- tionen entwickeln können: Es werden [8] http://it-republik.de/jaxenter/ sen wir erst einmal die Möglichkeit schaf- nicht nur wichtige und moderne Tech- quickvote/results/1/poll/75 fen, anderen zu folgen, und dazu brau- nologien wie Ajax und Comet einfach [9] http://maven.apache.org chen wir ein Template following.xhtml, zugänglich gemacht, sondern es stehen [10] http://www.h2database.com das sowohl die Benutzer auflistet, denen außerdem viele typische Funktionen wie www.JAXenter.de javamagazin 5|2010 57

×