5
Österreich 8,60 Schweiz sFr 15,80 Deutschland 7,50 8.09 D 45 86 7 Plus CD! Alle CD-Infos 3 Java Architekturen SOA Agile Java Magazin Stellenmarkt S. 62 Das Tutorial: Lose Kopplung mit Mule S. 71 CD-Inhalt Apache Commons Compress Grails 1.1.1 Spring dm 1.2 Project Mojarra Scala 2.7.5 Mule 2.2.1 Java Magazin 8.2009 JSF 2.0 Spring dm Meta Programming System ScalaModules Grails Garbage Collector Java Core OSGi on Scala DSLs mit ScalaModules 18 XML vs. Annotations Sind Annotations die erhoffte Rettung? 37 Tools Java-Spracherweiterung mit JetBrains MPS Effizient DSLs erstellen 78 Enterprise Garbage Collector Das unbekannte Wesen 65 Quo vadis JSF? Interview mit Ed Burns 52 Grails in Action Erfahrungsbericht: WerKannWann.de 56 OSGi mit Spring dm Viele Köche verderben (nicht) den Brei 24 Die nächste Generation der Webentwicklung 42 Ed Burns: Secrets of the Rockstar Programmers Session von der JAX 2009 ALLE INFOS ZUR AB SEITE 29 www.javamagazin.de

JM 08/09 - ScalaModules

Embed Size (px)

DESCRIPTION

Introduction to OSGi on Scala and the ScalaModules DSL in German Java Magazin.

Citation preview

Page 1: JM 08/09 - ScalaModules

Österreich € 8,60 Schweiz sFr 15,80Deutschland € 7,508.09

D 45 86 7

Plus CD!

Alle CD-Infos 3

Java • Architekturen • SOA • AgileJava

Mag

azin

Stellenmarkt S. 62 Das Tutorial: Lose Kopplung mit Mule S. 71

CD-Inhalt Apache Commons Compress

Grails 1.1.1

Spring dm 1.2

Project Mojarra

Scala 2.7.5

Mule 2.2.1

Java Magazin 8.2009

JSF 2.0 • Spring dm • M

eta Programm

ing System • ScalaM

odules • Grails • G

arbage Collector

Java CoreOSGi on ScalaDSLs mit ScalaModules 18

XML vs. AnnotationsSind Annotations die erhoffte Rettung? 37

ToolsJava-Spracherweiterung mit JetBrains MPSEffizient DSLs erstellen 78

EnterpriseGarbage CollectorDas unbekannte Wesen 65

Quo vadis JSF? Interview mit Ed Burns 52

Grails in ActionErfahrungsbericht: WerKannWann.de 56

OSGi mit Spring dmViele Köche verderben (nicht) den Brei 24

Quo vadis JSF? Interview mit Ed Burns

Die nächste Generation der Webentwicklung 42Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Die nächste Generation der Ed Burns:

Secrets of the Rockstar Programmers

Session von der JAX 2009

ALLE INFOS ZUR

AB SEITE 29

www.javamagazin.de

EUROPEAN HEADQUARTERS - LANGEN, GERMANY

LIFERAY GMBH — ROBERT - BOSCH - STRASSE 11, 63225 LANGEN, GERMANY

TEL: +49 - (0) 6103 - 3018570 FAX: +49 - (0) 6103 - 3018571

Now get the best of both worlds.Liferay Enterprise Edition gives you all the benefits of open source with the stability, security, and reliability of an enterprise subscription.

And with version 5.1, get the latest in SOA, Social Networking, and Collaboration technology, all at a fraction of the cost of Oracle® or IBM®.

For more information, email us at [email protected].

You spoke. We listened. Introducing Liferay Enterprise Edition.

Liferay 5.1 Enterprise Edition

Maintenance Subscription2.950 EUR / server / year

Platinum Support (24x7)19.950 EUR / server / year

Compare Oracle® WebCenter Suite: 125.000 EUR / processor, support 27.500 EUR / yr, as of 6 / 2008

Page 2: JM 08/09 - ScalaModules

Java Core

18 www.JAXenter.de

Scala DSL für OSGi-Entwicklung

javamagazin 8|2009

er geneigte Leser wird erah-nen, dass wir diese Fragen po-sitiv beantworten. Wir werden

im Folgenden kurz vorstellen, wie die OSGi-Entwicklung auf Scala ein- bzw. umgestellt werden kann. Anschlie-ßend werden wir auf die wichtigsten Scala-Sprachmerkmale eingehen, die uns ermöglichen, eine Domain Speci-fic Language (DSL) zu erstellen. Und schließlich werden wir mit ScalaModu-les [1] eine solche DSL vorstellen.

OSGi on Scala

OSGi ist das Dynamic Module System for Java. Und Scala setzt auf volle Interope-rabilität mit Java. Daher liegt es nahe, an-zunehmen, dass es möglich sein müsste, OSGi Bundles mit Scala zu entwickeln. Diese Annahme wurde schon vor eini-ger Zeit verifi ziert, z. B. veröff entlichte bereits 2007 Neil Bartlett [2] in seinem Blog ein kleines Beispiel. Im Prinzip ist es ganz einfach: Scala-Code kompiliert zu

„ganz normalem” Java-Bytecode, sodass es letztendlich für das OSGi-Framework transparent ist, ob ein OSGi Bundle mit Java oder Scala entwickelt wurde. Da-rüber hinaus können Java Libraries aus Scala-Code heraus genutzt werden, also auch die OSGi Libraries. Daher können wir z. B. wie in Listing 1 eine Scala-Klas-se schreiben, die das OSGi-Interface BundleActivator implementiert.

Bleibt noch das Bundle Manifest. Auch die darin enthaltenen Informatio-nen sind Scala-kompatibel. Das gilt ganz allgemein für alle Informationen, die vom Inhalt des OSGi Bundles unabhän-gig sind, z. B. Bundle-SymbolicName oder Bundle-Version. Aber auch Ma-nifest Header wie Export-Package oder Bundle-Activator, die Packages oder voll qualifizierte Klassennamen erwarten, stellen uns dank der vollen Interopera-bilität von Scala mit Java vor keinerlei Schwierigkeiten. Listing 2 zeigt ein ein-faches Beispiel, das für Java genauso aus-sehen würde, wie hier für Scala.

Die Th eorie klingt viel versprechend. Aber wie können wir OSGi Bundles mit Scala entwickeln? Auch das funktioniert genauso wie mit Java: Entweder wir nut-zen BND [3] mit Ant [4] oder Maven

[5], oder wir setzen auf Eclipse PDE [6], wobei das Zusammenspiel von PDE und Scala-Plug-in für Eclipse noch „wacke-lig” erscheint. Wir favorisieren generell den Ansatz, das Bundle Manifest mit BND zu generieren, statt es à la Eclipse PDE selbst zu schreiben. Weiterhin ge-hören wir dem Teil der bipolar gespalte-nen Entwicklergemeinde an, die Maven sehr schätzen. Daher setzen die Beispie-le auf Maven mit Scala-Plug-in [7] und dem großartigen Bundle-Plug-in [8], die beide im zentralen Maven Reposi-tory verfügbar sind. Die im Folgenden gezeigten Beispiele sind Auszüge aus der ScalaModules-Demo [9] und können von der ScalaModules-Website kom-plett heruntergeladen werden.

Um ein mit Scala entwickeltes OS-Gi Bundle in einem OSGi-Framework der Wahl laufen zu lassen, benötigen wir ebenfalls die Scala Libraries (scala-library.jar, scala-swing.jar etc.) als OSGi Bundles. Leider werden diese noch nicht als solche ausgeliefert, sodass wir daraus selbst OSGi Bundles machen müssen, was wiederum am einfachsten mit BND gelingt. Wir haben das bereits erledigt und stellen die OSGi-Versionen der ak-tuellen Scala Libraries im Rahmen des

OSGi on Scala – ScalaModules

von Heiko Seeberger und Roman Roelofsen

Spätestens seit der Ausgabe 4.09 des Java Magazins wissen wir: Scala verändert die Java-Welt. In dieser dreht OSGi seit geraumer Zeit ein ganz großes Rad. Da liegt es nahe, Scala auch auf OSGi loszulassen – zunächst einmal, um zu sehen, ob man mit Scala überhaupt OSGi Bundles erstellen kann. Und falls ja, ob man nicht die vielen Stärken von Scala für OSGi nut-zen und z. B. eine Domain Specifi c Language für OSGi erstellen kann.

Teil 1: ScalaModules

Teil 2: BindForge

Artikelserie: OSGi on Scala

Page 3: JM 08/09 - ScalaModules

Java Core

www.JAXenter.de 19

Scala DSL für OSGi-Entwicklung

javamagazin 8|2009

Projekts scala-lang-osgi [10] auf scala-tools.org [11] zur Verfügung.

DSLs mit Scala

Nun wissen wir, wie wir normale OSGi Bundles mit Scala entwickeln können. Das allein bringt sicher schon einen ordentli-chen Mehrwert, weil Scala gegenüber Java zahlreiche Vorteile bietet. Aber ihre volle Kraft kann Scala dann ausspielen, wenn ihre Skalierbarkeit auf Sprachniveau dazu verwendet wird, für eine bestimmte Do-mäne eine maßgeschneiderte Sprache zu kreieren: eine DSL. Dabei handelt es sich genau genommen um eine so genannte interne DSL, d. h. in Scala eingebettete, spezifische Sprachkonstrukte [12]. Ohne hier zu tief einsteigen zu wollen, werden wir uns nun kurz die wichtigsten Scala-Sprachmerkmale ins Gedächtnis rufen, die so etwas möglich machen. Da wäre zu-nächst einmal der reichhaltige Zeichen-satz, der uns für Scala-Code zur Verfü-gung steht. Als Java-Entwickler kann man nur staunen, dass quasi alle Sonderzeichen erlaubt sind und z. B. die folgenden Be-zeichner zulässig sind: ??, ++, --, <=, und ::. Gerade in Verbindung mit der Infix Ope-rator Notation können wir auf diese Weise fast beliebige Operatoren definieren, die letztendlich in ganz normalen Methoden-aufrufen resultieren. Denn wir können den Punkt und die Klammern einfach weglassen und z. B. number1/number2 schreiben anstatt number1./(number2). Das kann zu deutlich ausdrucksstärkerem und übersichtlicherem Code führen.

Ein weiteres herausragendes Merkmal ergibt sich aus dem funktionalen Charak-ter der Sprache: In Scala können Funktio-nen als Parameter an andere Funktionen übergeben werden. Zusammen mit der erwähnten Infix Operator Notation kön-nen auf diese Weise Strukturen geschaffen werden, die sich wie ein natürlicher Be-standteil des Sprachwortschatzes anfüh-len, z. B. val list2 = list map { x => x+1 }.

Last but not least seien Implicit Con-versions genannt, ein ganz besonders mächtiges Feature. Damit kann sozu-sagen passend gemacht werden, was zunächst nicht passt. Dadurch wird un-ter anderem ermöglicht, auf einem Ob-jekt Methoden aufzurufen, die auf dem Objekt gar nicht existieren, sofern dem Compiler eine Konvertierungsfunktion

zur Verfügung gestellt wird, mit der er das Objekt in ein geeignetes Zielobjekt umwandeln kann, das die aufzurufen-den Methoden besitzt. Ein Beispiel zur Verdeutlichung: In Scala kann auf jedem Objekt die Methode -> aufgerufen wer-den, die ein Tupel zurückgibt:

scala> val tupel = "a" -> 1

tupel: (java.lang.String, Int) = (a,1)

Dabei ist die Methode -> gar nicht auf je-dem Objekt definiert, sondern wird durch die implizite Konvertierungsfunktion sca-la.Predef.any2ArrowAssoc ermöglicht.

Wozu eine DSL für OSGi?

Als Antwort möge das Java-Beispiel aus Listing 3 dienen, das eine recht triviale Aufgabe ausführt: einen Greeting-Ser-vice nutzen und den Grußtext ausgeben. Neben der eigentlichen Nutzung des Service wird eine ServiceReference bezo-gen und auf null geprüft, davon der Ser-vice bezogen und wieder auf null geprüft und abschließend die ServiceReference wieder freigegeben. Das ist ohne Zweifel jede Menge Code, der auch ein erhebli-ches Fehlerpotenzial birgt. Und das alles, bloß um eine doch recht triviale Aufgabe auszuführen.

Wie kann eine DSL hier helfen? Ganz einfach, indem Sie uns Programmierern ermöglicht, genau das und nur das zu tun, was wir vorhaben, d. h. den Gree-

Listing 1package org.scalamodules.demo.hello.internal

import org.osgi.framework._

class Activator extends BundleActivator {

override def start(ctx: BundleContext) {

println(”Hello!“)

}

override def stop(ctx: BundleContext) {

println(”Good-bye!“)

}

}

Listing 2Manifest-Version: 1.0

Bundle-ManifestVersion: 2

Bundle-SymbolicName: org.scalamodules.demo.hello

Bundle-Version: 1.0.0

Bundle-Activator: org.scalamodules...Activator

Listing 3ServiceReference ref = ctx.getServiceReference

(Greeting.class.getName());

if (ref != null) {

try {

Object srv = ctx.getService(ref);

Greeting grt = (Greeting) srv;

if (grt != null) {

System.out.println(grt.welcome());

}

} finally {

ctx.ungetService(ref);

}

}

Listing 4ctx getOne classOf[Greeting] andApply {

grt => println(grt.welcome)

}

ting-Service nutzen und sonst nichts. Ein kleiner Vorgriff: Unser Beispiel er-scheint in Listing 4 unter Verwendung von ScalaModules radikal im Umfang reduziert und dreht sich bis auf wenig Glue-Code nur um das Wesentliche.

Wie wir sehen, ist die Verwendung des OSGi API aus zweierlei Gründen mitunter kompliziert. Zum einen ist es sehr low-level und feingranular, sodass typische Aufgaben wie z. B. die Service-nutzung oft aus zahlreichen einzelnen Arbeitsschritten bestehen. Das stellt übrigens in keiner Weise eine Kritik am Design des OSGi API dar, sondern verdeutlicht nur die Notwendigkeit für Abstraktionen auf einer höheren Ebe-ne. Zum anderen – und jetzt kommen wir doch zur Kritik – finden wir auch die eine oder andere unschöne Stelle im OSGi API. Zum Beispiel wird häufig mit fehleranfälligen Null-Referenzen gear-beitet. Und aus Kompatibilitätsgrün-den werden keine Generics verwendet, dafür aber „steinzeitliche“ Dictionaries statt Maps. Hier kann nun Scala in die Bresche springen, um diese Komplexität zu reduzieren und somit die OSGi-Ent-wicklung zu vereinfachen. Vorhang auf für ScalaModules!

ScalaModules by Example

Die folgenden Beispiele drehen sich um einen Greeting-Service mit den Metho-den welcome und goodbye:

Page 4: JM 08/09 - ScalaModules

Java Core

20 www.JAXenter.de

Scala DSL für OSGi-Entwicklung

javamagazin 8|2009

trait Greeting {

def welcome: String

def goodbye: String

}

Wie können wir einen solchen Greeting-Service mit ScalaModules registrieren? Mit der Methode registerAs, die dank Implicit Conversions auf dem Bundle-Context aufgerufen werden kann:

val grt = new Greeting {

override def welcome = "Hello!"

override def goodbye = "See you!";

}

ctx registerAs classOf[Greeting] theService grt

Wir bemerken zunächst die punkt- und klammerfreie Infix Operator Notati-on. Wenn man sich daran gewöhnt hat, ergibt sich in Verbindung mit den spre-chenden Bezeichnern ein gut zu verste-hendes Codefragment. Daneben hat die ScalaModules-Variante den Vorteil, dass der Compiler prüft, ob der registrierte Service tatsächlich zum Serviceinterface zuweisungskompatibel ist, während bei normaler OSGi-Programmierung in Java Überraschungen zur Laufzeit nicht ausge-schlossen sind. Die volle Stärke in Sachen Vereinfachung entfaltet ScalaModules, wenn zusätzlich noch Service-Properties angegeben werden sollen: Einfach noch die Methode withProperties mit einem oder mehreren Tupeln hinzufügen:

ctx registerAs classOf[Greeting] withProperties

(“name” -> “welcome”) theService grt { ... }

Wir haben oben schon im Vorgriff ge-zeigt, wie einfach die Nutzung eines

Greeting-Service mit ScalaModules wird (Listing 4): getOne auf dem Bund-leContext aufrufen und andApply eine Funktion mit dem Greeting-Service als Parameter übergeben. Ganz im Sinne der funktionalen Programmierung er-gibt natürlich auch ein Serviceaufruf auf diesem Weg ein Ergebnis, das wir auswerten können: None, falls gar kein Service verfügbar ist oder Some als Con-tainer für das eigentliche Ergebnis. Hoch lebe die Programmierung ohne Null-Referenzen!

ctx getOne classOf[Greeting] andApply {

_.welcome

} match {

case None => println(“No service!”)

case Some(s) => println(s)

}

Natürlich können wir auch alle verfüg-baren Greeting-Services nutzen und da-bei auf ihre Properties zugreifen (Listing 5). Dazu verwenden wir einfach getMa-ny und übergeben andApply eine Funk-tion mit Greeting und einer Map für die Properties als Parameter:

ctx getMany classOf[Greeting] andApply {

(greeting, properties) => ...

}

Und falls wir Filter verwenden möchten:

ctx getMany classOf[Greeting] withFilter

"(name=*)" andApply ...

Neben der gerade eben gezeigten Art, Services im Lookup-Stil zu nutzen, gibt es – vielleicht sogar noch verbreiteter – den Event-Stil, d. h. wir möchten über

das Kommen und Gehen von Services benachrichtigt werden, um darauf zu reagieren. Dafür wird gewöhnlich ein ServiceTracker mit einem ServiceTra-ckerCustomizer sowie einige Zeilen „handgeschriebenen“ Codes verwen-det. ScalaModules bietet hierfür die Me-thode track in Verbindung mit den Case Classes Adding, Modified und Removed für die möglichen TrackEvents:

ctx track classOf[Greeting] on {

case Adding(g, _) => println(g.welcome)

case Removed(g, _) => println(g.goodbye)

}

Abschließend sei noch ein Feature er-wähnt, das per Java API nur „unter Schmerzen“ programmiert werden kann, weshalb in der Praxis hierfür De-clarative Services oder etwas Vergleich-bares zum Einsatz kommt. Es geht um Abhängigkeiten zwischen Services, z. B. soll ein Command Service nur dann re-gistriert werden, wenn ein von ihm be-nötigter Greeting-Service verfügbar ist. ScalaModules bietet hierfür eine Varian-te von registerAs an, bei der die Methode dependOn eingefügt wird:

ctx registerAs classOf[Command] dependOn

classOf[Greeting] theService {

greeting => new Command { ... }

}

ScalaModules bietet weitere Details und Features, z. B. Unterstützung für den Config Admin Service – allfälligen Wis-sensdurst vermag der Reference Guide [13] zu stillen. Wir konnten mit diesen Beispielen hoffentlich vermitteln, wel-che Erleichterungen eine Scala DSL für ein klassisches Java API zu bringen ver-mag.

Unter der Haube

Nachdem wir ScalaModules aus der Sicht des Nutzers vorgestellt haben, werden wir kurz anreißen, wie es ei-gentlich unter der Haube aussieht, d. h. wie man so eine Scala DSL ange-hen kann. Dreh- und Angelpunkt von ScalaModules ist die Klasse RichBund-leContext. Sie ist ein Wrapper um den OSGi BundleContext und stellt die Me-thoden registerAs, getOne, track etc. zur

Listing 5ctx getMany classOf[Greeting] andApply {

(grt, props) => {

val name = props.get(”name“) match {

case None => ”UNKNOWN“

case Some(s) => s

}

name + ” says: ” + grt.welcome

}

} match {

case None => noGreetingService()

case Some(ss) => ss foreach { println }

}

Listing 6object RichBundleContext {

implicit def toRichBundleContext(

ctx: BundleContext) =

new RichBundleContext(context)

}

class RichBundleContext(

ctx: BundleContext) {

def registerAs[T](srvIf: Class[T]) = ...

def getOne[T](srvIf: Class[T]) = ...

...

Page 5: JM 08/09 - ScalaModules

Java CoreScala DSL für OSGi-Entwicklung

Verfügung. Doch wie kommen wir an einen RichBundleContext? Dank Im-plicit Conversions ganz einfach: Wir arbeiten mit dem OSGi BundleContext und lassen diesen vom Scala Compiler dort durch einen RichBundleContext ersetzen, wo wir das benötigen, also dort, wo wir registerAs, getOne, track etc. verwenden. Dafür ist es nur erfor-derlich, die folgende Konvertierungs-funktion zu importieren: import org.scalamodules.core.RichBundleContext.toRichBundleContext.

Listing 6 zeigt Ausschnitte aus dem Sourcecode des RichBundleContext. Im Companion Object wird die Konver-tierungsfunktion toRichBundleContext definiert. Man beachte das Schlüssel-wort implicit. Die Klasse selbst hat den zu wrappenden BundleContext als Class-Parameter und stellt die DSL-Methoden zur Verfügung. Voilà!

Resümee

Wir haben gezeigt, dass wir Scala ver-wenden können, um OSGi Bundles entwickeln zu können. Dazu müssen wir nur OSGi-fi zierte Scala Libra ries

verwenden. Darüber hinaus bietet sich für OSGi eine Scala DSL wie Sca-laModules an, um von komplexer Low-Level-Programmierung zu abstrahie-ren oder unschöne Ecken im API zu umgehen.

In der kommenden Ausgabe werden wir das Thema OSGi on Scala wieder aufgreifen und BindForge [14] vorstel-len, ein Module-Framework auf Basis von OSGi und – ja, richtig – einer Scala DSL.

Heiko Seeberger ist Technical Director der Weigle Wilczek GmbH. Sein Schwerpunkt liegt in der Entwicklung von Unternehmensanwen-dungen mit Java, Scala, AspectJ, OSGi, Eclipse RCP, Lift, Spring und JEE. Seine Erfahrung aus über fünfzehn Jahren IT-Beratung und Soft-wareentwicklung fl ießen in die Eclipse Training Alliance ein. Zudem ist er aktiver Open Source Committer, Autor zahlreicher Fachartikel und Redner auf einschlägigen Konferenzen.Roman Roelofsen ist Lead Architect bei der ProSyst Software GmbH und für den Enterprise-Solution-Bereich verantwortlich. Er repräsentiert ProSyst Software in den OSGi Core Platform und Enterprise Expert Groups. Weiterhin ist er Committer in der OSGi-basierten Open Source Distribution ModuleFusion. Seine Hauptinteressen sind modulare Pro-grammierung und Sprachendesign.

Links & Literatur

[1] ScalaModules: http://scalamodules.org/

[2] Neil Bartletts Blog: http://neilbartlett.name/blog/2007/04/06/an-osgi-bundle-built-in-scala/

[3] BND: http://aqute.biz/Code/Bnd

[4] Ant: http://ant.apache.org/

[5] Maven: http://maven.apache.org/

[6] Eclipse PDE: http://eclipse.org/pde/

[7] Scala-Plug-in für Maven: http://scala-tools.org/mvnsites/maven-scala-plugin/

[8] Bundle-Plug-in für Maven: http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html

[9] ScalaModules-Downloads: http://github.com/hseeberger/scalamodules/downloads

[10] Scala Libraries als OSGi Bundles: http://github.com/hseeberger/scala-lang-ogi/

[11] scala-tools.org Maven Repository: http://scala-tools.org/repo-releases/

[12] Details über Sprachen/DSLs: http://voelter.de/data/articles/trends2007.pdf

[13] ScalaModules-Downloads: http://github.com/hseeberger/scalamodules/downloads

[14] BindForge: http://bindforge.org/

Interview mit Scala Mastermind Martin Odersky: www.jaxenter.de/news/47686

JAX TV „The Challenge of Scalable Languages“ von Martin Odersky: www.jaxenter.de/news/47263

Mehr zum Thema Scala

Anzeige