1. Plus CD! Stellenmarkt S. 62 Das Tutorial: Lose Kopplung mit Mule S. 71
8.09
Deutschland € 7,50 Österreich € 8,60 Schweiz sFr 15,80
Java Magazin
Java • Architekturen • SOA • Agile www.javamagazin.de ALLE IN
FOS ZU
R
CD-Inhalt AB SEIT
E 29
Apache Commons
Compress
Grails 1.1.1
Spring dm 1.2
Project Mojarra
Scala 2.7.5
Mule 2.2.1
Ed Burns:
Secrets of
Die nächste Generation der
Webentwicklung 42
the Rockstar
Programmers
Session von der
JAX 2009
Alle CD-Infos 3
Java Core
OSGi on Scala
DSLs mit ScalaModules 18
XML vs. Annotations
Sind Annotations die
erhoffte Rettung? 37
Tools Quo vadis JSF?
Java-Spracherweiterung
mit JetBrains MPS Interview mit Ed Burns 52
Effizient DSLs erstellen 78
Enterprise
Garbage Collector
Grails in Action
Das unbekannte Wesen 65 Erfahrungsbericht: WerKannWann.de 56
D 45 86 7
OSGi mit Spring dm
Viele Köche verderben (nicht) den Brei 24
2. Java Core Scala DSL für OSGi-Entwicklung
OSGi on Scala –
ScalaModules
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 Specific Language für OSGi erstellen kann.
von Heiko Seeberger und Roman Roelofsen
er geneigte Leser wird erah- „ganz normalem” Java-Bytecode, sodass [5], oder wir setzen auf Eclipse PDE [6],
nen, dass wir diese Fragen po- es letztendlich für das OSGi-Framework wobei das Zusammenspiel von PDE und
sitiv beantworten. Wir werden transparent ist, ob ein OSGi Bundle mit Scala-Plug-in für Eclipse noch „wacke-
im Folgenden kurz vorstellen, wie die Java oder Scala entwickelt wurde. Da- lig” erscheint. Wir favorisieren generell
OSGi-Entwicklung auf Scala ein- bzw. rüber hinaus können Java Libraries aus den Ansatz, das Bundle Manifest mit
umgestellt werden kann. Anschlie- Scala-Code heraus genutzt werden, also BND zu generieren, statt es à la Eclipse
ßend werden wir auf die wichtigsten auch die OSGi Libraries. Daher können PDE selbst zu schreiben. Weiterhin ge-
Scala-Sprachmerkmale eingehen, die wir z. B. wie in Listing 1 eine Scala-Klas- hören wir dem Teil der bipolar gespalte-
uns ermöglichen, eine Domain Speci- se schreiben, die das OSGi-Interface nen Entwicklergemeinde an, die Maven
fic Language (DSL) zu erstellen. Und BundleActivator implementiert. sehr schätzen. Daher setzen die Beispie-
schließlich werden wir mit ScalaModu- Bleibt noch das Bundle Manifest. le auf Maven mit Scala-Plug-in [7] und
les [1] eine solche DSL vorstellen. Auch die darin enthaltenen Informatio- dem großartigen Bundle-Plug-in [8],
nen sind Scala-kompatibel. Das gilt ganz die beide im zentralen Maven Reposi-
OSGi on Scala allgemein für alle Informationen, die tory verfügbar sind. Die im Folgenden
OSGi ist das Dynamic Module System for vom Inhalt des OSGi Bundles unabhän- gezeigten Beispiele sind Auszüge aus der
Java. Und Scala setzt auf volle Interope- gig sind, z. B. Bundle-SymbolicName ScalaModules-Demo [9] und können
rabilität mit Java. Daher liegt es nahe, an- oder Bundle-Version. Aber auch Ma- von der ScalaModules-Website kom-
zunehmen, dass es möglich sein müsste, nifest Header wie Export-Package oder plett heruntergeladen werden.
OSGi Bundles mit Scala zu entwickeln. Bundle-Activator, die Packages oder voll Um ein mit Scala entwickeltes OS-
Diese Annahme wurde schon vor eini- qualifizierte Klassennamen erwarten, Gi Bundle in einem OSGi-Framework
ger Zeit verifiziert, z. B. veröffentlichte stellen uns dank der vollen Interopera- der Wahl laufen zu lassen, benötigen
bereits 2007 Neil Bartlett [2] in seinem bilität von Scala mit Java vor keinerlei wir ebenfalls die Scala Libraries (scala-
Blog ein kleines Beispiel. Im Prinzip ist es Schwierigkeiten. Listing 2 zeigt ein ein- library.jar, scala-swing.jar etc.) als OSGi
ganz einfach: Scala-Code kompiliert zu faches Beispiel, das für Java genauso aus- Bundles. Leider werden diese noch nicht
sehen würde, wie hier für Scala. als solche ausgeliefert, sodass wir daraus
Die Theorie klingt viel versprechend. selbst OSGi Bundles machen müssen,
Artikelserie: OSGi on Scala Aber wie können wir OSGi Bundles mit was wiederum am einfachsten mit BND
Scala entwickeln? Auch das funktioniert gelingt. Wir haben das bereits erledigt
Teil 1: ScalaModules
genauso wie mit Java: Entweder wir nut- und stellen die OSGi-Versionen der ak-
Teil 2: BindForge
zen BND [3] mit Ant [4] oder Maven tuellen Scala Libraries im Rahmen des
18 javamagazin 8|2009 www.JAXenter.de
3. Scala DSL für OSGi-Entwicklung Java Core
Projekts scala-lang-osgi [10] auf scala- zur Verfügung gestellt wird, mit der er ting-Service nutzen und sonst nichts.
tools.org [11] zur Verfügung. das Objekt in ein geeignetes Zielobjekt Ein kleiner Vorgriff: Unser Beispiel er-
umwandeln kann, das die aufzurufen- scheint in Listing 4 unter Verwendung
DSLs mit Scala den Methoden besitzt. Ein Beispiel zur von ScalaModules radikal im Umfang
Nun wissen wir, wie wir normale OSGi Verdeutlichung: In Scala kann auf jedem reduziert und dreht sich bis auf wenig
Bundles mit Scala entwickeln können. Das Objekt die Methode -> aufgerufen wer- Glue-Code nur um das Wesentliche.
allein bringt sicher schon einen ordentli- den, die ein Tupel zurückgibt: Wie wir sehen, ist die Verwendung
chen Mehrwert, weil Scala gegenüber Java des OSGi API aus zweierlei Gründen
zahlreiche Vorteile bietet. Aber ihre volle scala> val tupel = "a" -> 1 mitunter kompliziert. Zum einen ist es
tupel: (java.lang.String, Int) = (a,1)
Kraft kann Scala dann ausspielen, wenn sehr low-level und feingranular, sodass
ihre Skalierbarkeit auf Sprachniveau dazu typische Aufgaben wie z. B. die Service-
verwendet wird, für eine bestimmte Do- Dabei ist die Methode -> gar nicht auf je- nutzung oft aus zahlreichen einzelnen
mäne eine maßgeschneiderte Sprache zu dem Objekt definiert, sondern wird durch Arbeitsschritten bestehen. Das stellt
kreieren: eine DSL. Dabei handelt es sich die implizite Konvertierungsfunktion sca- übrigens in keiner Weise eine Kritik
genau genommen um eine so genannte la.Predef.any2ArrowAssoc ermöglicht. am Design des OSGi API dar, sondern
interne DSL, d. h. in Scala eingebettete, verdeutlicht nur die Notwendigkeit für
spezifische Sprachkonstrukte [12]. Ohne Wozu eine DSL für OSGi? Abstraktionen auf einer höheren Ebe-
hier zu tief einsteigen zu wollen, werden Als Antwort möge das Java-Beispiel aus ne. Zum anderen – und jetzt kommen
wir uns nun kurz die wichtigsten Scala- Listing 3 dienen, das eine recht triviale wir doch zur Kritik – finden wir auch
Sprachmerkmale ins Gedächtnis rufen, Aufgabe ausführt: einen Greeting-Ser- die eine oder andere unschöne Stelle im
die so etwas möglich machen. Da wäre zu- vice nutzen und den Grußtext ausgeben. OSGi API. Zum Beispiel wird häufig mit
nächst einmal der reichhaltige Zeichen- Neben der eigentlichen Nutzung des fehleranfälligen Null-Referenzen gear-
satz, der uns für Scala-Code zur Verfü- Service wird eine ServiceReference bezo- beitet. Und aus Kompatibilitätsgrün-
gung steht. Als Java-Entwickler kann man gen und auf null geprüft, davon der Ser- den werden keine Generics verwendet,
nur staunen, dass quasi alle Sonderzeichen vice bezogen und wieder auf null geprüft dafür aber „steinzeitliche“ Dictionaries
erlaubt sind und z. B. die folgenden Be- und abschließend die ServiceReference statt Maps. Hier kann nun Scala in die
zeichner zulässig sind: ??, ++, --, <=, und ::. wieder freigegeben. Das ist ohne Zweifel Bresche springen, um diese Komplexität
Gerade in Verbindung mit der Infix Ope- jede Menge Code, der auch ein erhebli- zu reduzieren und somit die OSGi-Ent-
rator Notation können wir auf diese Weise ches Fehlerpotenzial birgt. Und das alles, wicklung zu vereinfachen. Vorhang auf
fast beliebige Operatoren definieren, die bloß um eine doch recht triviale Aufgabe für ScalaModules!
letztendlich in ganz normalen Methoden- auszuführen.
aufrufen resultieren. Denn wir können Wie kann eine DSL hier helfen? Ganz ScalaModules by Example
den Punkt und die Klammern einfach einfach, indem Sie uns Programmierern Die folgenden Beispiele drehen sich um
weglassen und z. B. number1/number2 ermöglicht, genau das und nur das zu einen Greeting-Service mit den Metho-
schreiben anstatt number1./(number2). tun, was wir vorhaben, d. h. den Gree- den welcome und goodbye:
Das kann zu deutlich ausdrucksstärkerem
und übersichtlicherem Code führen.
Ein weiteres herausragendes Merkmal Listing 1 Listing 3
package org.scalamodules.demo.hello.internal ServiceReference ref = ctx.getServiceReference
ergibt sich aus dem funktionalen Charak- (Greeting.class.getName());
ter der Sprache: In Scala können Funktio- import org.osgi.framework._ if (ref != null) {
nen als Parameter an andere Funktionen try {
übergeben werden. Zusammen mit der class Activator extends BundleActivator { Object srv = ctx.getService(ref);
Greeting grt = (Greeting) srv;
erwähnten Infix Operator Notation kön-
override def start(ctx: BundleContext) { if (grt != null) {
nen auf diese Weise Strukturen geschaffen println(”Hello!“) System.out.println(grt.welcome());
werden, die sich wie ein natürlicher Be- } }
standteil des Sprachwortschatzes anfüh- } finally {
len, z. B. val list2 = list map { x => x+1 }. override def stop(ctx: BundleContext) { ctx.ungetService(ref);
println(”Good-bye!“) }
Last but not least seien Implicit Con- } }
versions genannt, ein ganz besonders }
mächtiges Feature. Damit kann sozu-
sagen passend gemacht werden, was Listing 2 Listing 4
zunächst nicht passt. Dadurch wird un- Manifest-Version: 1.0 ctx getOne classOf[Greeting] andApply {
ter anderem ermöglicht, auf einem Ob- Bundle-ManifestVersion: 2 grt => println(grt.welcome)
Bundle-SymbolicName: org.scalamodules.demo.hello }
jekt Methoden aufzurufen, die auf dem
Bundle-Version: 1.0.0
Objekt gar nicht existieren, sofern dem Bundle-Activator: org.scalamodules...Activator
Compiler eine Konvertierungsfunktion
www.JAXenter.de javamagazin 8|2009 19
4. Java Core Scala DSL für OSGi-Entwicklung
trait Greeting {
Greeting-Service mit ScalaModules das Kommen und Gehen von Services
def welcome: String wird (Listing 4): getOne auf dem Bund- benachrichtigt werden, um darauf zu
def goodbye: String leContext aufrufen und andApply eine reagieren. Dafür wird gewöhnlich ein
} Funktion mit dem Greeting-Service als ServiceTracker mit einem ServiceTra-
Parameter übergeben. Ganz im Sinne ckerCustomizer sowie einige Zeilen
der funktionalen Programmierung er- „handgeschriebenen“ Codes verwen-
Wie können wir einen solchen Greeting- gibt natürlich auch ein Serviceaufruf det. ScalaModules bietet hierfür die Me-
Service mit ScalaModules registrieren? auf diesem Weg ein Ergebnis, das wir thode track in Verbindung mit den Case
Mit der Methode registerAs, die dank auswerten können: None, falls gar kein Classes Adding, Modified und Removed
Implicit Conversions auf dem Bundle- Service verfügbar ist oder Some als Con- für die möglichen TrackEvents:
Context aufgerufen werden kann: tainer für das eigentliche Ergebnis. Hoch
lebe die Programmierung ohne Null- ctx track classOf[Greeting] on {
val grt = new Greeting { case Adding(g, _) => println(g.welcome)
Referenzen!
override def welcome = "Hello!" case Removed(g, _) => println(g.goodbye)
override def goodbye = "See you!"; }
ctx getOne classOf[Greeting] andApply {
}
_.welcome
ctx registerAs classOf[Greeting] theService grt
} match { Abschließend sei noch ein Feature er-
case None => println(“No service!”)
wähnt, das per Java API nur „unter
case Some(s) => println(s)
Wir bemerken zunächst die punkt- und }
Schmerzen“ programmiert werden
klammerfreie Infix Operator Notati- kann, weshalb in der Praxis hierfür De-
on. Wenn man sich daran gewöhnt hat, clarative Services oder etwas Vergleich-
ergibt sich in Verbindung mit den spre- Natürlich können wir auch alle verfüg- bares zum Einsatz kommt. Es geht um
chenden Bezeichnern ein gut zu verste- baren Greeting-Services nutzen und da- Abhängigkeiten zwischen Services, z. B.
hendes Codefragment. Daneben hat die bei auf ihre Properties zugreifen (Listing soll ein Command Service nur dann re-
ScalaModules-Variante den Vorteil, dass 5). Dazu verwenden wir einfach getMa- gistriert werden, wenn ein von ihm be-
der Compiler prüft, ob der registrierte ny und übergeben andApply eine Funk- nötigter Greeting-Service verfügbar ist.
Service tatsächlich zum Serviceinterface tion mit Greeting und einer Map für die ScalaModules bietet hierfür eine Varian-
zuweisungskompatibel ist, während bei Properties als Parameter: te von registerAs an, bei der die Methode
normaler OSGi-Programmierung in Java dependOn eingefügt wird:
Überraschungen zur Laufzeit nicht ausge- ctx getMany classOf[Greeting] andApply {
(greeting, properties) => ... ctx registerAs classOf[Command] dependOn
schlossen sind. Die volle Stärke in Sachen
} classOf[Greeting] theService {
Vereinfachung entfaltet ScalaModules,
greeting => new Command { ... }
wenn zusätzlich noch Service-Properties
}
angegeben werden sollen: Einfach noch Und falls wir Filter verwenden möchten:
die Methode withProperties mit einem
ctx getMany classOf[Greeting] withFilter
oder mehreren Tupeln hinzufügen: ScalaModules bietet weitere Details und
"(name=*)" andApply ...
Features, z. B. Unterstützung für den
ctx registerAs classOf[Greeting] withProperties Config Admin Service – allfälligen Wis-
(“name” -> “welcome”) theService grt { ... }
Neben der gerade eben gezeigten Art, sensdurst vermag der Reference Guide
Services im Lookup-Stil zu nutzen, gibt [13] zu stillen. Wir konnten mit diesen
Wir haben oben schon im Vorgriff ge- es – vielleicht sogar noch verbreiteter – Beispielen hoffentlich vermitteln, wel-
zeigt, wie einfach die Nutzung eines den Event-Stil, d. h. wir möchten über che Erleichterungen eine Scala DSL für
ein klassisches Java API zu bringen ver-
mag.
Listing 5 Listing 6 Unter der Haube
ctx getMany classOf[Greeting] andApply { object RichBundleContext {
(grt, props) => { implicit def toRichBundleContext( Nachdem wir ScalaModules aus der
val name = props.get(”name“) match { ctx: BundleContext) = Sicht des Nutzers vorgestellt haben,
case None => ”UNKNOWN“ new RichBundleContext(context) werden wir kurz anreißen, wie es ei-
case Some(s) => s }
gentlich unter der Haube aussieht,
}
name + ” says: ” + grt.welcome class RichBundleContext( d. h. wie man so eine Scala DSL ange-
} ctx: BundleContext) { hen kann. Dreh- und Angelpunkt von
} match { def registerAs[T](srvIf: Class[T]) = ... ScalaModules ist die Klasse RichBund-
case None => noGreetingService() def getOne[T](srvIf: Class[T]) = ...
leContext. Sie ist ein Wrapper um den
case Some(ss) => ss foreach { println } ...
}
OSGi BundleContext und stellt die Me-
thoden registerAs, getOne, track etc. zur
20 javamagazin 8|2009 www.JAXenter.de
5. Scala DSL für OSGi-Entwicklung Java Core
Verfügung. Doch wie kommen wir an verwenden. Darüber hinaus bietet In der kommenden Ausgabe werden
einen RichBundleContext? Dank Im- sich für OSGi eine Scala DSL wie Sca- wir das Thema OSGi on Scala wieder
plicit Conversions ganz einfach: Wir laModules an, um von komplexer Low- aufgreifen und BindForge [14] vorstel-
arbeiten mit dem OSGi BundleContext Level-Programmierung zu abstrahie- len, ein Module-Framework auf Basis
und lassen diesen vom Scala Compiler ren oder unschöne Ecken im API zu von OSGi und – ja, richtig – einer Scala
dort durch einen RichBundleContext umgehen. DSL.
ersetzen, wo wir das benötigen, also
dort, wo wir registerAs, getOne, track Heiko Seeberger ist Technical Director der Weigle Wilczek GmbH.
etc. verwenden. Dafür ist es nur erfor- Sein Schwerpunkt liegt in der Entwicklung von Unternehmensanwen-
derlich, die folgende Konvertierungs- dungen mit Java, Scala, AspectJ, OSGi, Eclipse RCP, Lift, Spring und
funktion zu importieren: import org. JEE. Seine Erfahrung aus über fünfzehn Jahren IT-Beratung und Soft-
wareentwicklung fließen in die Eclipse Training Alliance ein. Zudem ist
scalamodules.core.RichBundleContext. er aktiver Open Source Committer, Autor zahlreicher Fachartikel und
toRichBundleContext. Redner auf einschlägigen Konferenzen.
Listing 6 zeigt Ausschnitte aus dem Roman Roelofsen ist Lead Architect bei der ProSyst Software GmbH
Sourcecode des RichBundleContext. Im und für den Enterprise-Solution-Bereich verantwortlich. Er repräsentiert
ProSyst Software in den OSGi Core Platform und Enterprise Expert
Companion Object wird die Konver- Groups. Weiterhin ist er Committer in der OSGi-basierten Open Source
tierungsfunktion toRichBundleContext Distribution ModuleFusion. Seine Hauptinteressen sind modulare Pro-
definiert. Man beachte das Schlüssel- grammierung und Sprachendesign.
wort implicit. Die Klasse selbst hat den zu
wrappenden BundleContext als Class-
Links & Literatur
Parameter und stellt die DSL-Methoden
zur Verfügung. Voilà! [1] ScalaModules: http://scalamodules.org/
[2] Neil Bartletts Blog: http://neilbartlett.name/blog/2007/04/06/
Resümee an-osgi-bundle-built-in-scala/
[3] BND: http://aqute.biz/Code/Bnd
Wir haben gezeigt, dass wir Scala ver-
[4] Ant: http://ant.apache.org/
wenden können, um OSGi Bundles
[5] Maven: http://maven.apache.org/
entwickeln zu können. Dazu müssen
[6] Eclipse PDE: http://eclipse.org/pde/
wir nur OSGi-fi zierte Scala Libraries
[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-
Mehr zum Thema Scala bundle-plugin-bnd.html
[9] ScalaModules-Downloads: http://github.com/hseeberger/scalamodules/
Interview mit Scala Mastermind downloads
Martin Odersky: [10] Scala Libraries als OSGi Bundles: http://github.com/hseeberger/scala-lang-ogi/
www.jaxenter.de/news/47686 [11] scala-tools.org Maven Repository: http://scala-tools.org/repo-releases/
JAX TV „The Challenge of [12] Details über Sprachen/DSLs: http://voelter.de/data/articles/trends2007.pdf
Scalable Languages“ von
[13] ScalaModules-Downloads: http://github.com/hseeberger/scalamodules/
Martin Odersky: downloads
www.jaxenter.de/news/47263
[14] BindForge: http://bindforge.org/
Anzeige