Ruby on Rails spaltet die Gemeinde der Webentwickler. Für die einen der Weisheit letzter Schluss, für die anderen der größte Hype aller Zeiten. JRuby bringt beide Fronten wieder an einen Tisch.
Die Reaktionen reichten von Neid bis zu willigem Konvertitentum, als David Heinemeier Hansson Ruby on Rails im Jahr 2004 in die freie Wildbahn entließ [1]. Viele Entwickler waren und sind fasziniert von der Einfachheit und den Grundprinzipien von Rails. Es wurde als Framework aus der bestehenden Webanwendung Basecamp der Firma 37Signals extrahiert und versteht sich als “Opposition Software”. Soll heißen: Das Framework bestimmt, wo der Entwickler etwas wie zu tun hat.
Was sich auf den ersten Blick als arrogante Bevormundung ausnimmt, lernt der Programmierer nach kurzer Einarbeitungszeit durchaus zu schätzen. Der Webentwickler weiß immer, an welcher Stelle er dieses oder jenes implementieren muss, ohne vorher lange nachzudenken. Das wiederum ermöglicht es ihm, sich mehr auf das Wesentliche zu konzentrieren, nämlich die Geschäftslogik der Anwendung.
Doch hält Ruby als Rails-Untersatz auch manche Überraschung für Java-Entwickler bereit. So unterstützt die aktuelle Ruby-Implementierung zwar Threads für die parallele Verarbeitung, diese laufen jedoch in ein und demselben Prozess und lassen so das Potenzial moderner Multicore-Systeme brachliegen. Java nutzt dagegen schon seit Langem Threads auf Betriebssystemebene.
Auch die auf der Sprachebene vorhandene Unicode-Unterstützung von Java, sucht man in Ruby noch vergebens. Dennoch spricht viel für die Erstellung von Anwendungen in Ruby, nicht zuletzt deswegen, weil Programmieren nach Vorstellung von Ruby-Erfinder Yukihiro Matsumoto vor allem Spaß machen soll. Umso besser, dass nun mit JRuby [2] eine Java-Implementation der Ruby-Sprache zur Verfügung steht, die das Beste beider Welten vereint.
JRuby kommt dazu
Jan Arne Petersen, Student der Universität Bonn, erstellte bereits im Jahr 2001 die erste Portierung von Ruby 1.6 in Java. Um das Rails-Framework auch unter JRuby nativ nutzen zu können, befassten sich im Jahre 2006 Thomas Enebo und Charles Nutter mit der Portierung von Ruby 1.8. Dieses Vorhaben bekam im September desselben Jahres eine neue Dynamik, als Sun Microsystems die beiden Entwickler unter Vertrag nahm und sie Vollzeit mit der Weiterentwicklung von JRuby betraute.
JRuby lässt sich unter Linux sehr einfach installieren, wenn sich schon ein Java-SDK auf dem Zielsystem befindet. Unter [2] stehen die verschiedenen Releases als Tar- oder Zip-Archive zur Verfügung. Im Rahmen dieses Artikels kam die erste Betarelease der kommenden Version 1.1 zum Einsatz.
Versteht sich mit Rubygems
Ausgepackt an einen Ort, der im Folgenden einfach über die Umgebungsvariable »JRUBY_HOME« zu erreichen ist, kann die Installation mit einigen Beispielen getestet werden, die sich im Verzeichnis »samples« befinden. Die Sequenz:
jruby $JRUBY_HOME/samples/swing2.rb
sollte ein einfaches Swing-Frame mit der Schaltfläche erzeugen. Ist diese Hürde genommen, können weitere wichtige Komponenten folgen. Ruby bringt von Haus aus ein eigenes Paketmanagement Namens Rubygem mit [3]. So sucht
jruby -S gem list r -r
zum Beispiel auf [gem.rubyforge.org] nach allen Paketen, die mit dem Buchstaben »r« anfangen. Der Befehl
jruby -S gem help commands
liefert eine Übersicht der zur Auswahl stehenden Kommandos. Die Anweisung
jruby -S gem install rake
installiert das Build-Tool »rake«, das unter Ruby die Aufgaben eines klassischen Unix-Makes erfüllt, und
jruby -S gem install -y rails
installiert das komplette Rails-Framework in der aktuellen Version mit allen abhängigen Paketen. Um auch mit Datenbanken arbeiten zu können, bietet sich unter JRuby die Verwendung des Active-Record-JDBC-Pakets an, das aus den Händen der JRuby-Kernentwickler stammt. Somit schließt
jruby -S gem install ActiveRecord-JDBC
die Installation der nötigen Komponenten ab. Alle Pakete liegen jetzt wohlgeordnet unter »$JRUBY_HOME/lib/ruby/gems/1.8/gems«.
Rails in JRuby
Genug der Vorarbeit. Schließlich muss noch der Beweis erbracht werden, dass Rails und Java unter JRuby eben nicht nur ein trautes Nebeneinander, sondern ein wirklich starkes Paar sind. Ein einfaches Rails-Projekt lässt sich in bekannter Ruby-Manier unter JRuby wie folgt erzeugen:
jruby -S rails mybooks
Im neuen Verzeichnis »mybooks« befindet sich nun das komplette Skelett der neuen Webanwendung. Ihm fehlt noch das sprichwörtliche Fleisch an den Knochen. Das lässt sich schnell ändern, indem der Programmierer folgende Entität anlegt, die in der Rail-Terminologie Modell heißt:
jruby script/generate model Book
Neben einigen anderen Dateien erzeugt der Rails-Generator die Datei »001_create_books.rb« im Verzeichnis »db/migrate« (Listing 1).
Datenbank-Migration
Eine solche als Datenbank-Migration oder kurz Migration bezeichnete Datei dient zur Versionierung des Datenbankschemas und enthält sowohl den Teil für die Erzeugung einer bestimmten Modelltabelle als auch für deren Zerstörung. Die Zeilen 4 und 5 in Listing 1 geben zwei Modellattribute an, die auf die entsprechenden Spalten in der Datenbank-Tabelle »books« verweisen.
|
Listing 1: |
|---|
01 class CreateBooks < ActiveRecord::Migration 02 def self.up 03 create_table :books do |t| 04 t.column :title, :string 05 t.column :isbn, :string 06 end 07 end 08 09 def self.down 10 drop_table :books 11 end 12 end |
Bevor der Programmierer diese Abbildung testen kann, muss er den einzigen Konfigurationsschritt ausführen, der sich in Rails nicht mit Ruby bewerkstelligen lässt: die Konfiguration der neu angelegten Datenbank. Als kleine Gedächtnisauffrischung hier die bei MySQL dafür nötigen Befehle im SQL-Monitor »mysql«:
mysql> CREATE DATABASE mybooks_development; mysql> GRANT ALL ON mybooks_development.* TO 'root'@'localhost' IDENTIFIED BY 'root';
Damit Rails zu dieser Datenbank Verbindung aufnehmen kann, steht im Verzeichnis »config/database.yml« die entsprechende Konfigurationsdatei im Yaml-Format bereit. Unter Zuhilfenahme des Active-Record-JDBC-Pakets sieht die Anbindung wie in Listing 2 aus.
Darüber hinaus muss der Rails-Entwickler in »environment.rb« im selben Verzeichnis die Zeile »require \’jdbc_adapter\’« vor der Zeile »Rails::Initializer.run do |config|« hinzufügen. Um die Datenbank mit Leben zu füllen, erzeugt
jruby -S rake db:migrate
eine neue Datenbank-Migration, die der Entwickler mit Hilfe der JRuby-Komman-dozeilen-Umgebung »console« direkt ausprobieren kann:
jruby script/console
Der Befehl lädt die aktuelle Mybooks-Umgebung. Die Kommandos in Listing 3 testen so den Objekt-Mapper Active Record. Jetzt noch kurz den Rails-Scaffold-Generator mit
jruby script/generate scaffold book
ausgeführt – und schon ist die erste Rails-Anwendung unter JRuby fertig zum Einsatz. Ein
jruby script/server
startet den Webrick-HTTP-Server, der in Rails die Aufgabe eines leichtgewichtigen Entwicklungsservers hat. Nach dem Start lässt sich unter [http://localhost:3000/books] die generierte C(reate)R(etrieve)U(pdate)D(delete)-Schnittstelle für das Bücher-Modell in Augenschein nehmen.
|
Listing 2: |
|---|
01 development: 02 adapter: jdbc 03 driver: com.mysql.jdbc.Driver 04 url: jdbc:mysql://localhost/mybooks_development 05 username: root 06 password: root |
|
Listing 3: |
|---|
01 >> b = Book.new
02 => #<Book:0xfc01db @attributes={"isbn"=>nil, "title"=>nil}, @new_record=true>
03 >> b.title = "Webanwendungen mit Ruby on Rails"
04 => "Webanwendungen mit Ruby on Rails"
05 >> b.isbn = "9783827324917"
06 => "9783827324917"
07 >> b.save
|
Java in Rails
Bis hierher sind die Unterschiede zwischen Ruby und JRuby, bis auf wenige Änderungen bei der Datenbank-Verbindung, sehr gering. Und in dieser, sehr agilen Umgebung können jetzt – dank JRuby – eigene, aber insbesondere auch fremde Java-Bibliotheken ohne großen Aufwand zum Einsatz kommen. Für das Bücher-Beispiel soll eine einfache Java-Klasse von [4] herhalten, die die Gültigkeit von ISBN-Nummern testet.
Das Java-Archiv »isbn.jar« kopiert man an die Stelle der aufrufenden Modell-Klasse unter »app/models« und erweitert die Modell-Klasse »Book« um den Code in Listing 4. Die ersten beiden Zeilen binden sowohl Java als auch das Java-Package »ISBN« ein. Innerhalb der Modell-Klasse ruft in Zeile 13 die Methode »validate_isbn« den Java-Constructor von »ISBN« auf dem Attribut »isbn« der Modell-Instanz auf.
|
Listing 4: Erweiterung von |
|---|
01 require 'java'
02 require 'isbn.jar'
03
04 class Book < ActiveRecord::Base
05 def validate
06 unless validate_isbn
07 errors.add('isbn','is invalid')
08 end
09 end
10
11 def validate_isbn
12 begin
13 isbn = com.openly.info.ISBN.new(self.isbn)
14 rescue
15 isbn = nil
16 end
17 end
18 end
|
Das Ruby-Exceptionhandling verhindert, das die Applikation bei fehlerhafter ISBN-Nummer wilde Java-Exceptions erzeugt. Validierungsmethoden sind ein Mittel, um der Rails-Applikation die Möglichkeit zu geben, auf die Eingabe von fehlerhaften Werten des Benutzers zu reagieren. Üblicherweise wird die Validate-Methode vor dem Speichern der Objektinstanz ausgeführt. Dieses Verhalten lässt sich in der Rails-Konsole beobachten (Listing 5).
|
Listing 5: Fehlermeldung in der |
|---|
01 >> b = Book.new(:title => 'Kein Buch', :isbn => '4712')
02 => #<Book:0xd849e0 @attributes={"isbn"=>"4712", "title"=>"Kein Buch"}, @new_record=true>
03 >> b.save
04 => false
05 >> b.validate
06 => ["is invalid", "is invalid"]
|
Die von Rails erzeugte Oberfläche der Anwendung meldete eine Fehleingabe etwas eindrucksvoller (Abbildung 1). Klar hätte dieses Beispiel die Validierung auch in Ruby selbst implementieren können, aber so zeigt es, wie schnell und unkompliziert sich Java-Code in JRuby on Rails integrieren lässt.

Abbildung 1: Die in Listing 5 provozierte Fehlermeldung im Webbrowser: Die ISBN-Nummer ist ungültig.
Anwendungen in Ruby on Rails lassen sich auf vielen Wegen ausliefern. Unter Rails hat sich eine Kombination aus Apache und mehreren Mongrel-Instanzen etabliert. Die Konfiguration einer solchen Umgebung ist nicht trivial und schreckt einen erfahrenen J2EE-Entwickler vermutlich eher ab. Ist er es doch gewohnt, seine Applikation als Web Application Archive, kurz WAR, einfach in einen beliebigen J2EE-kompatiblen Applikationsserver zu werfen und automatisch deployen zu lassen.
Dank JRuby steht dieser Weg nun auch Rails-Anwendungen offen. Aktuell ist für dieses Unterfangen das Plugin Goldspike in die eigene Applikation zu installieren:
jruby script/plugin install http://jruby-extras.rubyforge.org/svn/trunk/rails-integration/plugins/goldspike
Das WAR-Archiv zu erzeugen setzt in der Regel noch einen gültige Datenbank-Connector voraus. Goldspike hat für Einstellungen dieser Art die Datei »war.rb« im »config«-Verzeichnis angelegt. Für die MySQL-Anbindung ist in der Zeile
#maven_library 'mysql', 'mysql-connector-java', '5.0.4'
das Kommentarzeichen »#« zu löschen. Danach reicht der Aufruf des folgenden Rake-Ziels:
jruby -S rake war:standalone:create
Auf der Kommandozeile lässt sich mitlesen, welche Archive der Befehl zur WAR-Datei hinzupackt. Steht als J2EE-Container Apache Tomcat [5] bereit, reicht ein
cp mybooks.war $TOMCAT_HOME/webapps/.
um das Autodeployment in Gang zu setzen. Hat alles funktioniert, dann ist die installierte Rails-Applikation unter [http://localhost:8080/mybooks/books] zu erreichen.
Brücke zwischen Welten
Dieser Artikel gibt nur einen kleinen Einblick in die Möglichkeiten beim Einsatz von JRuby on Rails. Interessant ist zum Beispiel für Entwickler, die zwischen den Welten wandern, dass sie Ruby-Code innerhalb von Java über JRuby ausführen können. Das ist besonders für diejenigen spannend, die schnell über eine Session Bean einen Webservice anbieten möchten, der Daten aus einer Rails-Applikation holt. Auch Fragen rund um eine Integration des Java Message Service müssen einem zukünftigen Artikel vorbehalten bleiben.
Für Puristen bedeuten die hier beschriebenen Möglichkeiten einer Interaktion von Java und Ruby sicherlich eine Verwässerung des reinen Ruby- oder Java-Gedankens – je nach Perspektive. Niemand sollte aber dabei vergessen, dass viele Projekte in der echten IT-Welt Lösungsansätze wie die hier skizzierten benötigen. Zum Beispiel, um Altsysteme oder teuer eingekaufte Bibliotheken auch in agilen Entwicklungsumfeldern, wie Rails sie von Haus aus unterstützt, weiterhin verwenden zu können.
Wahlfreiheit für Webentwickler
Vielleicht fällt auch dem einen oder anderen Java-Entwickler der Blick über den Tellerrand hin zu Ruby on Rails leichter, wenn er weiterhin seine altbewährte Toolchain mitnehmen darf. Interessant ist nicht nur, dass Sun Microsystems mit Netbeans [6] bereits die erste IDE-Unterstützung von JRuby im Programm hat, sondern dass auch Oracle mit Mix [7] die erste größere JRuby-Anwendung betreibt. (ofr)
|
Infos |
|---|
|
[1] Armin Röhrl, Stefan Schmiedl, “Webanwendungen mit Ruby und Rails”: Linux-Magazin 12/04, S. 100 [2] JRuby: [http://jruby.codehaus.org] [3] O. Frommel, “Ruby-Module managen mit Rubygems”: Linux-Magazin 03/07, S. 114 [4] ISBN-Tools: [http://isbntools.com] [5] Apache Tomcat: [http://tomcat.apache.org] [6] Netbeans-JRuby-Pack: [http://www.netbeans.org/products/ruby] [7] Oracle Mix: [https://mix.oracle.com] |
|
Der Autor |
|---|
|
Ramon Wartala ist IT-Leiter beim Online-Vermarkter Orangemedia.de in Hamburg und Mitautor von “Webanwendungen mit Ruby on Rails”, erschienen im Verlag Addison-Wesley. |





