Java Blend

JVM-Sprachen im Mix

Eckard Buchner
Scala kann mehr

Scala bietet eine ganze Reihe weiterer Operationen auf Listen an: Traversing, Mapping, Filtering, Folding und Reducing [10]. Diese Methoden erwarten die Funktion, die sie ausführen sollen, als Argument. Hier als Beispiel die Definition von scala.List.map()

map [B](f : (A) => B) : List[B]

Die Funktion f wird auf jedes Element der List angewandt. Um map() aus einer anderen Sprache aufzurufen, schauen wir uns die Methode mit dem Decompiler (javap) an:

public final scala.Seq map(scala.Function1);

Als Parameter wird ein Objekt vom Typ scala.Function1 erwartet, als Rückgabewert ein Objekt aus den Scala-Collections. Ohne auf Details einzugehen: In anderen Sprachen ein Objekt von diesem Typ als Parameter bereitzustellen oder den Rückgabewert zu verarbeiten, ist mühsam. Wir werden das später bei der Diskussion der Scala Traits noch sehen. Eine weitere Besonderheit kommt ins Spiel, wenn wir aus anderen Sprachen Elemente in eine Scala-Liste einfügen wollen. Scala bietet dafür Operatoren mit eigentlich nicht Java-konformen Namen wie „::“oder „+=“. Im Bytecode erzeugt der Compiler daraus die Methoden $colon$colon() und $plus$eq(). Solche Operatoren findet man im Scala API häufig. In Java z. B. muss man in so einem Fall schreiben:

import scala.collection.mutable.ListBuffer;
...
ListBuffer buffer = new ListBuffer();
buffer.$plus$eq("new element");

Die Eleganz der Scala-Syntax geht damit natürlich verloren. Eine Liste der Operatoren mit den äquivalenten Namen in Java finden Sie z. B. unter [11].

Nicht die Bohne?

Die Konventionen für Getter und Setter von Java Beans begegnen uns an vielen Stellen, z. B. in der JSP Expression Language [12] oder in Dependency-Injection-Frameworks wie Spring [13]. Sie sind eine wichtige Voraussetzung für die Einbindung von Code aus anderen Sprachen in diese Umgebungen. Groovy ist wie immer Vorbild und generiert zu jeder Property-Definition die Bean-konformen Methoden:

class GBean {
  def value
  boolean booleanValue
}

Daraus erzeugt der Groovy-Compiler:

public java.lang.Object getValue();
    public void setValue(java.lang.Object);
    public boolean getBooleanValue();
    public boolean isBooleanValue();
    public void setBooleanValue(boolean);

Für das boolesche Attribut erzeugt Groovy sogar zwei Lesemethoden! Aus einer Attributdeklaration var someVal = „foo“ erzeugt der Scala-Compiler

public void someVal_$eq(java.lang.String);
public java.lang.String someVal();

Deklariert man das Attribut someVal als val, dann wird nur die Methode someVal() für den lesenden Zugriff erzeugt. Diese Methodennamen weichen übrigens ab, wenn man von den neuen Sichtbarkeitsdefinitionen [14] Gebrauch macht. Bean-konforme Zugriffsmethoden werden dann zusätzlich erzeugt, wenn man die Annotation @scala.reflect.BeanProperty verwendet. Man muss dazu aber den Quellcode der Scala-Klasse besitzen, bei einer vorkompilierten Scala-Bibliothek hilft diese Option nicht.

Skripte

Für die Skripteinbindung von Groovy gibt es mehrere Alternativen. Eine ausführliche Behandlung finden Sie in „Groovy In Action“ im Kapitel „Groovy Integration“ [15]. Hier eine Übersicht der wichtigsten Punkte:

Groovy API

  • groovy.lang.GroovyShell zur Auswertung einfacher Ausdrücke und Skripte. Darauf baut auch groovy.util.Eval auf, das wir oben verwendet haben.
  • groovy.util.GroovyScriptEngine für komplexere Szenarien, wenn Skripte z. B. voneinander abhängig sind. Dabei besteht die Möglichkeit, Skripte, die sich ändern, neu zu laden.
  • groovy.lang.GrovyClassLoader ist das mächtigste Integrationswerkzeug. Damit können Sie auch Skripte und Klassen kompilieren.

Spring-Integration

  • Da Groovy-Objekte dem Java-Beans-Standard entsprechen, können Sie kompilierte Groovy-Klassen wie Java Beans in Ihrer Spring-Definitionsdatei verwenden.
  • Darüber hinaus können Sie Groovy-Skripte einbinden, die vom Spring Framework geladen und kompiliert werden. Ändert sich die Quelldatei, kann Spring sie automatisch neu kompilieren. Weitere Details finden Sie in der Spring-Dokumentation [16]. Spring unterstützt neben Groovy auch JRuby und BeanShell.

Scripting-Frameworks

  • In JSR 233 wurde ein API spezifiziert, das seit Version 6 Bestandteil des JDK ist [17]. Es bietet eine definierte Schnittstelle für die Integration beliebiger Skriptsprachen.
  • Das Bean Scripting Framework (BSF) wurde ursprünglich von IBM entwickelt. Heute ist es Bestandteil des Apache-Jakarta-Projekts [18].

Das folgende Codefragment zeigt Beispiele für die beiden Frameworks. Dabei wertet der Groovy-Interpreter das GString-Objekt aus und liefert die verwendete Groovy-Version zurück (Listing 4).

Listing 4

String groovyScript = ""Groovy Version $GroovySystem.version"";

// JSR 223
ScriptEngine engine = new ScriptEngineManager().getEngineByName("groovy");
System.out.println("JSR: " + engine.eval(groovyScript));

// BSF
BSFManager manager = new BSFManager();
System.out.println("BSF: " + 
  manager.eval("groovy", "myScript", 0, 0, groovyScript));
Geschrieben von
Eckard Buchner
Kommentare

Schreibe einen Kommentar

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