Java Blend

JVM-Sprachen im Mix

Eckard Buchner

Für die Java Virtual Machine gibt es mittlerweile mehrere Programmiersprachen, die Java sehr gut ergänzen bzw. sogar ersetzen können. Muss man gleich komplett umsteigen oder kann man die Vorteile mehrerer Sprachen in einem Projekt nutzen? Je mehr Verbreitung die Java-Alternativen finden, desto weniger wird man in Zukunft um eine solche Mischung herumkommen. Da aus allen Sprachen Bytecode erzeugt wird, sollte dies – in der Theorie zumindest – problemlos möglich sein. Der Artikel untersucht am Beispiel von Groovy, Scala und Java, wie das in der Praxis aussieht und welche Stolperfallen man beachten muss.

Java ist mittlerweile etabliert. Viele Entwickler haben das entsprechende Know-how, die Tools sind ausgereift, und es gibt Bibliotheken für nahezu alle Anforderungen. Nur die Sprache selbst ist etwas in die Jahre gekommen, wie man im Vergleich mit den Alternativen sieht, die für die JVM angeboten werden [1]. Groovy ist 2003 erschienen und wird unter anderem als Skriptsprache für die Java-Plattform und im Webframework Grails eingesetzt. Die Sprache lässt dem Entwickler die Wahl zwischen dynamischer und statischer Typisierung (so genannte optionale Typisierung) und bietet Neuerungen wie Closures und Metaprogrammierung. Sie ist kompakt und für Java-Entwickler leicht zu lernen. Außerdem steht eine lange Liste Groovy-basierter Frameworks zur Verfügung [2]. Während Groovy eher als Java-Erweiterung positioniert wird [3], könnte Scala langfristig sogar Java ablösen [4]. Scala ist statisch typisiert und verbindet objektorientierte und funktionale Ansätze. Der Entwickler muss sich mit einigen neuen Sprachkonzepten auseinandersetzen. Die Sprache wird seit einigen Jahren an der École Polytechnique Fédérale de Lausanne unter Leitung von Martin Odersky entwickelt. Man darf gespannt sein, wie Scala sich am Markt durchsetzt: Als prominenter Nutzer wird gern Twitter zitiert. Dort ist man bei der aus Performancegründen von Ruby auf Scala umgestiegen [5], das Frontend ist weiterhin Ruby. Ein Projekt, in dem mehrere Sprachen zum Einsatz kommen, hat seine eigenen Herausforderungen: Zum einen muss der Skill bei den Beteiligten vorhanden sein, zum anderen müssen beim Entwickeln bestimmte Dinge beachtet werden, wie der Artikel im Folgenden zeigt.

Hello All!

Beginnen wir mit einem einfachen mehrsprachigen Programm, das die Version der beteiligten Laufzeiten ausgibt (Listing 1).

Listing 1

import java.util.ResourceBundle

object SHelloAll {
  def version =
        ResourceBundle getBundle "library" getString "version.number"
}

(SHelloAll.scala)

class GHelloAll {
  static String version() {
    GroovySystem.version
  }
}
(GHelloAll.groovy)

public class JHelloAll {
    public static void main(String [] args) {
        System.out.println("Java Version  : " + JHelloAll.version());
        System.out.println("Scala Version : " + SHelloAll.version());
        System.out.println("Groovy Version: " + GHelloAll.version());
    }
    static String version() {
        return System.getProperty("java.version");
    }
}
(JHelloAll.java)

Scala muss man die Version mit einem kleinen Trick entlocken: Sie steht in einem Property-File im Scala Library Archiv. Um das Programm zu übersetzen, aktiviert man die Scala- bzw. Groovy-Plug-ins in der jeweiligen IDE. Die Beispiele im Artikel wurden mit IntelliJ IDEA (Community Edition) entwickelt, sind aber auch mit Eclipse nachvollziehbar. Nach dem Start sieht die Ausgabe zum Beispiel so aus:

Java Version  : 1.6.0_19
Scala Version : 2.7.7.final
Groovy Version: 1.7.2

Wie das auf Knopfdruck geht, obwohl drei Compiler im Spiel sind, erläutert der Kasten „Joint Compilation“. Um das Programm außerhalb der IDE zu starten, genügt es, dem Java-Interpreter die notwendigen Jar-Archive aus der Scala- bzw. Groovy-Installation mitzugeben:

set cp=.
set cp=%cp%;%scala_home%libscala-library.jar
set cp=%cp%;%groovy_home%embeddablegroovy-all-1.7.2.jar

java -classpath %cp% helloall.JHelloAll
(helloall.bat)
Joint Compilation

Betrachten wir das HelloAll-Beispiel einmal genauer: Hier sind die drei Compiler javac, scalac und groovyc beteiligt. Der Java-Compiler benötigt den Output der anderen beiden, schließlich verwendet die Java-Klasse ein Groovy- und eine Scala-Objekt. Trotzdem kann man diese Klassen in der IDE mühelos übersetzen: Der Scala-Compiler analysiert dazu auch Java-Klassen und versteht genug von der Syntax, um Abhängigkeiten zwischen den Sprachen aufzulösen. Sind die Scala Class Files erzeugt, kann der Java-Compiler wie gewohnt übersetzen [6]. Der Groovy-Compiler arbeitet etwas anders. Zunächst werden aus den Groovy-Klassen so genannte Stubs erzeugt. Anschließend wird der Java Compiler aufgerufen, um die Java-Klassen zu übersetzen. Im letzten Schritt werden dann die Groovy-Quellen komplett übersetzt [7]. Das funktioniert z. B. auch mit ANT:


(helloall.xml)

javac-Element aktiviert. Der Scala ANT Task prüft selbst, welche Java-Quellen im Source-Verzeichnis liegen und berücksichtigt sie beim Kompilieren der Scala-Quellen. Für andere Build-Tools wie Maven findet man Beispiele im Internet (Groovy: [8], Scala: [6]).

Zugegeben, unser HelloAll-Beispiel war sehr Compiler-freundlich angelegt. Mit unserem ANT-Skript könnte man auch Groovy-Quellen übersetzen, die auf Scala-Objekte zugreifen, weil groovyc erst im zweiten Schritt aufgerufen wird. Umgekehrt ist das nicht möglich, denn der Scala-Compiler ignoriert die Groovy-Quellen. Die Reihenfolge der Schritte entscheidet also darüber, welche Abhängigkeiten zwischen Groovy und Scala bestehen dürfen.

Geschrieben von
Eckard Buchner
Kommentare

Schreibe einen Kommentar

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