Java-6-Scripting mit JRuby
Java 6 enthält eine Schnittstelle für den Einsatz von Script-Sprachen auf der JVM. heise Developer zeigt am Beispiel von JRuby, wie man mit ihr auf Java-Bibliotheken zugreifen kann, was die Wiederverwendung von Java-Bibliotheken erleichtert.
- Heiko W. Rupp
Java 6 enthält eine Schnittstelle für den Einsatz von Script-Sprachen auf der Java Virtual Machine (JVM). Mit ihr lassen sich generisch Scripts in Sprachen wie Ruby und JavaScript aus Java-Programmen heraus aufrufen, und man kann damit von den Sprachen aus auf Java-Bibliotheken zugreifen, was die Wiederverwendung von Java-Bibliotheken erleichtert. heise Developer zeigt das Vorgehen am Beispiel von JRuby.
Oftmals stehen Entwickler vor der Situation, dass Java-Projekte mit Code aus anderen Programmiersprachen interagieren müssen. Das kann beispielsweise der Fall sein, wenn ein Systemmanagementwerkzeug in Java geschrieben ist, die Administratoren Erweiterungen aber lieber in Ruby oder Python schreiben wollen. Es gibt zwar den Weg, Programme oder Scripts via java.lang.Runtime.exec()
aufzurufen. Das ist aber aufwendig und wenig performant, wenn das Script häufiger interagieren soll. Außerdem ist das Übergeben und Auslesen von Parametern und Rückgabewerten mühsam.
Vor JDK 6, Codename Mustang, gab es einige proprietäre Optionen, Script-Sprachen aus Java heraus aufzurufen. Da die Java Virtual Machine (JVM) schon lange nicht mehr nur eine Umgebung für die Programmiersprache Java bereitstellt, sondern sie auch viele andere Sprachen als Ablaufumgebung nutzen, lag es nahe, das Einbinden der Sprachen von Java aus zu vereinheitlichen.
Der JSR 223 führt mit javax.script
ein Paket ein, das die Aufrufe dieser Sprachen in einer generischen Form erlaubt. Das prinzipielle Vorgehen ist immer dasselbe (Pseudocode):
1: ScriptEngineManager m = new ScriptEngineManager(); // Manager erzeugen
2: ScriptEngine engine = m.getEngineByXXX(); // Spezielle Engine
// laden
3: engine.eval(); // Skript ausführen
Der große Charme, die API des JSR 223 zu nutzen, liegt darin, dass das Vorgehen unabhängig von der eigentlichen Script-Sprache ist.
Eine Engine lässt sich auf unterschiedliche Weise suchen:
- nach Namen mit
getEngineByName(String name)
. Hier sucht man die Engine nach dem registrierten Namen der Script-Sprache; etwagetEngineByName("jruby");
für JRuby odergetEngineByName("JavaScript");
für JavaScript. - nach Dateinamenerweiterung mit
getEngingeByExtension(String extension)
. Man sucht nach dem Suffix des Dateinamens (zum Beispiel.js
oder.rb
). - nach Mime-Typ. Das erlaubt, die Engine nach dem passenden Mime-Typ zu suchen. Dies ist allerdings nur in den wenigen Fällen sinnvoll, in denen eine Sprache einen registrierten Mime-Typ hat (etwa für JavaScript).
Damit das für eine Sprache funktionieren kann, muss eine Engine vorhanden sein, welche die Namen und Dateisuffixe registriert und die Brücke in die jeweilige Script-Sprache bietet. Mustang enthält mit der Rhino-Engine eine für JavaScript – andere Engines findet man unter hier, wobei manche recht alt sind wie die der Ruby-Implementierung für Java, JRuby. Man ist mit dem Download von der Projektseite besser bedient, da seit JRuby 1.4 die Integration Teil des JRuby-Downloads (jruby-complete.jar
) ist, sodass man recht schnell loslegen kann.
Benutzern der JVM von Apple steht standardmäßig auch AppleScript als Script-Sprache zur Verfügung. Für Benutzer des Open JDK sieht die Welt leider anders aus: in einigen Versionen fehlt die Rhino-Engine, da Sun sie anscheinend aufgrund von Bedenken zur Lizenzierung herausgenommen hat. Hier lässt sich die Engine herunterladen und im Classpath installieren.
Generell lässt sich das Vorhandensein einer Script-Sprache über das Programm jrunscript
herausfinden:
jrunscript -l <sprache> -e "Script-Ausdruck"
Ist die Sprache vorhanden, wird der Script-Ausdruck ausgewertet, ansonsten erhält man eine Fehlermeldung. Für die Sprache kann man sowohl den Namen als auch die Erweiterung verwenden, beispielsweise jrunscript -l js -e "1+1"
. Eine ausführliche Liste verfügbarer Sprachen findet sich unter hier.