Das Projekt KIX

W-JAX Challenge mit Scala und Lift gelöst

Heiko Seeberger

Als Münchner ist für mich die W-JAX quasi ein Heimspiel, und als Lift-Committer konnte ich den Aufruf zur Challenge ohnehin nicht ignorieren. Natürlich hätte ich einige Abende lieber damit verbracht, auf dem Sofa zu sitzen und Fussball zu schauen, aber ich wusste ja, dass ich mit Lift nicht allzu lange brauchen würde. Und so griff ich, von Kollegen beim Testen unterstützt, in die Tasten: die Geburtsstunde von KIX.

Warum Lift?

Wer schon einmal das Vergnügen mit Lift hatte, der darf diesen Abschnitt getrost überspringen. Allen anderen möchte ich dieses innovative Web Application Framework und seine Vorzüge kurz näher bringen.

Zunächst einmal basiert Lift auf Scala, der vielleicht vielve

rsprechendsten neuen JVM-Sprache, denn selbst Mr. Groovy (James Strachan) und Mr. JRuby (Charles Nutter) sehen Scala als den legitimen Anwärter auf den Java-Thron. Natürlich wäre es auch möglich, ein anderes Framework, z. B. JSF, mit Scala zu neuen Dimensionen in Sachen Produktivität und knappem und lesbarem Code zu bringen, denn Scala ist hundertprozentig abwärtskompatibel zu Java. Aber Lift macht darüber hinaus intensiven Gebrauch von neuen Features von Scala, z. B. Closures, nativem XML-Support etc. Dadurch entstehen neue Möglichkeiten und dadurch macht Lift einiges anders (besser), als andere Frameworks. Wobei auch viel Gutes von anderen abgeschaut wurde, z. B. Templating von Wicket und “More than just CRUD” von Django.

Lift ist ein “Full Stack Web Application Framework”. Wie bitte? O.K., das bedeutet, dass Lift alles mitbringt, was man für eine typische Web Application benötigt: zunächst einmal ein HTTP-Framework mit Templates, AJAX- und Comet-Support, dann natürlich auch Persistenzlösungen (Mapper, JPA etc.), Link- und Access-Management (Sitemap), ein komplettes User-Management und viele weitere Module, z. B. PayPal-Integration, Textile-Support, OpenID-Support etc.

Spätestens seit Rails wissen wir, dass wir, im Gegensatz zu Best-of-Breed-Ansätzen, mit dem Full Stack, wo die einzelnen Module bestens integriert sind, äußerst produktiv arbeiten können. Das beweisen die Zahlen: KIX wurde von mir in knapp fünf Personentagen mit 787 Lines of Code (LOC) erstellt. Das wäre mir mit anderen Ansätzen, mit denen ich vertraut bin, sicherlich nicht gelungen.

Highlight: Comet-Chat

So knapp Code auf Basis von Lift auch ist, würde eine detaillierte Vorstellung von Lift hier den Rahmen sprengen. Außerdem wird es in naher Zukunft einen Lift-Artikel im Java Magazin geben, der die Grundlagen detailliert darstellt.

Hier liegt der Fokus ohnehin auf KIX, und daher möchte ich nur ein besonderes Highlight herausstellen: KIX bietet einen Chat, der Server-Push mit Comet verwendet. Dadurch aktualisiert sich die Chatvorschau auf der Homepage oder der eigentliche Chatscreen “wie von Geisterhand”, wenn eine neue Nachricht eintrifft.

Abb. 1

Um das selbst nachzuvollziehen, müssen wir auf weiglewilczek.com/labs/kix nur zwei Browserfenster öffnen und uns unter zwei unterschiedlichen Usern anmelden: Schon können wir loschatten und bekommen die neuen Messages umgehend und ohne Interaktion oder Neuladen der Seite.

Abgesehen davon, dass Comet-Support an sich schon eine sehr feine Sache ist, besticht Lift dadurch, dass so ein Comet-Chat mit extrem wenig Code realisiert werden kann. Im Folgenden sehen wir den kompletten Code. Wem die Scala-Syntax nichts sagt, der kann trotzdem die Lines of Code (LOC) zählen und wird dabei feststellen, dass das nicht lange dauert. Zunächst brauchen wir einen Chat-Server (11 LOC):

object ChatServer extends LiftActor with ListenerManager { override def lowPriority = { case chatMsg @ ChatMsg(name, msg) if msg.trim.length > 0 => chatLines ::= ChatLine(name, now, msg) chatLines = chatLines take 5 updateListeners() } override protected def createUpdate = ChatServerUpdate(chatLines) private var chatLines = List[ChatLine]() } case class ChatServerUpdate(lines: List[ChatLine]) case class ChatLine(name: String, when: Date, msg: String) case class ChatMsg(name: String, msg: String) 

Dann einen Chat-Client, hier für die Chat-Preview (21 LOC):

class ChatPreview extends CometActor with CometListener { override def render = { def bindMessages = lines.reverse flatMap { line => bind("msg", chooseTemplate("chat", "msgs", defaultXml), "content" -> toXhtml(line)) } bind("chat", defaultXml, AttrBindParam("id", Text(MsgsId), "id"), "msgs" -> bindMessages) } override def lowPriority = { case ChatServerUpdate(newLines) => { lines = newLines take 3 partialUpdate(SetHtml(MsgsId, lines.reverse map { toXhtml(_) })) } } override def registerWith = ChatServer private lazy val MsgsId = uniqueId + "_msgs" private var lines = List[ChatLine]() private def toXhtml(line: ChatLine) = { def msg = if (line.msg.length <= 23) line.msg take 23 else (line.msg take 20) + "..." <div class="chatLine"> <b>{ line.name }</b>{ " " + msg } </div> } } 

Und schließlich noch das Template für die Oberfläche, hier der Ausschnitt für die Chat-Preview:

<div> <h3> <lift:loc>kix Chat Preview</lift:loc> </h3> <lift:comet type="ChatPreview"> <div chat:id="na" class="chatPreview"> <chat:msgs> <msg:content/> </chat:msgs> </div> </lift:comet> </div> 
Eindrücke

Im Folgenden möchte ich noch mit einigen Screenshots ein Gefühl für KIX vermitteln. Dabei wird (leider) rasch klar, dass ich nicht zur Elite der Webdesigner zähle. Da wir wissen, wie wichtig die äußere Verpackung ist, bin ich vom dritten Platz für KIX umso mehr begeistert. Das bedeutet, dass die Jury und vor allem das Publikum auch unter die Haube geblickt und die inneren Werte erkannt haben.

Die Homepage zeigt, auch ohne Login, die nächsten Begegnungen.

Abb. 2

Das komplette User Management mit Registrierung, E-Mail-Bestätigung, Anmeldung etc. bekommt man von Lift als out-of-the-box-Feature geschenkt. Sehr hilfreich!

Abb. 3

Die Übersicht über eigene Tipps und die der Mitspieler nutzt zum Löschen von Tipps den Ajax-Support von Lift, der uns ein intuitives Scala-API bietet, sodass wir uns nicht die Hände mit JavaScript schmutzig machen müssen. Aber natürlich dürfen wir auch nativ JavaScript programmieren oder jQuery oder eine alternative JavaScript-Bibliothek verwenden

Abb. 4

Natürlich vermitteln diese Bilder nur einen unzulänglichen Eindruck von KIX, insbesondere der Blick unter die Haube erfordert, sich mit dem Sourcecode auseinander zu setzen. KIX ist Open Source unter Apache-Lizenz und kann unter github.com/weiglewilczek/kix eingesehen werden. Wer dazu während der W-JAX keine Gelegenheit hatte oder einfach noch einmal einen Blick auf KIX in Action werfen möchte, der sei unter weiglewilczek.com/labs/kix herzlich dazu eingeladen.

Geschrieben von
Heiko Seeberger
Heiko Seeberger
Heiko Seeberger is Fellow at codecentric. He has been a Scala enthusiast ever since he came to know this fascinating language in 2008. Deeply interested in distributed computing he became a contributor to the amazing Akka project in 2010. Heiko has more than 20 years of professional expertise in consulting and software development and regularly shares his expertise in articles and talks. He is also the author of the German Scala book "Durchstarten mit Scala". Heiko tweets as @hseeberger and blogs under heikoseeberger.de.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.