instant jruby & derby environment für eine RoR Anwendung

Als angestammter Java-Entwickler geht es mir oftmals schwer von der Hand, einer Ruby on Rails (RoR) Anwendung mit relativ wenig Aufwand eine brauchbare Laufzeitumgebung zu bieten.
Normalerweise sollte das OS (MacOS 10.5.6) alles Brauchbare bieten. So ist oftmals eine Rails-Version installiert und auch das (standardmäßig genutzte) SQlite 3 ist vorhanden.
Dennoch sind es oftmals Plugins (spezielle Rails Version / spezielle gems), welche einen zusätzlichen Aufwand benötigen.
Nicht zu vergessen, dass RoR nicht auf allen Systemen vorinstalliert ist und dementsprechend ein interessierter Entwicklung von einem Out-of-the-Box Erlebnis weit entfernt ist.
Sehen wir den Tatsachen ins Auge… die Wahrscheinlichkeit eine installierte JVM vorzufinden ist (noch?) deutlich höher, als eine Lauffähige Ruby-Installation.
Was liegt also näher, als die benötigte Umgebung auf Java fußen zu lassen.
Hierzu werden verwendet:

  • jRuby in Version 1.1.5 (http://jruby.codehaus.org)
  • Derby-DB in Version 10.4.2.0 (http://db.apache.org/derby)
  • weiterhin wird eine installierte JVM (>1.5) vorrausgesetzt

 

Alles weitere wird mit Hilfe von shell-Scripten bewerkstelligt. Wobei momentan nur Unix-Scripte benutzt werden. Eine Portierung auf Windows sollte aber nur eine Sache von Minuten sein.
Es liegt eine RoR-Anwendung in einem Entwicklungs-Status vor. Diese wurde bisher in einem Netbeans-Enviroment mit einer SQlite-DB betrieben.
Das Verzeichnis ist folgendermaßen aufgebaut:

ROOT
|
|- microblog (dies ist unsere RoR-Anwendung)
|
|- derby (derby-installtion - es werden jeweils das bin und lib Verzeichnis benötigt)
| |-bin
| |-lib
|
|- jruby (jruby-installtion - es werden jeweils das bin und lib Verzeichnis benötigt)
| |-bin
| |-lib

Das Hauptproblem besteht darin, dass alle benötigten gems in das entsprechende Unterverzeichnis installiert werden müssen.
Weiterhin muss die Derby-DB mit dem entsprechenden Rake-Task auf mit der aktuellen Schema-Datei instanziiert werden.
Zuletzt sollen die vorhandenen User-Daten in die Derby-DB eingefügt werden.

  1. Anpassen der database.yml
    Wir nutzen weiterhin eine jdbc-Connection. Allerdings ändert sich der Treiber auf den der Derby-DB:
    database.yml

    development:
    adapter: jdbc
    driver: org.apache.derby.jdbc.ClientDriver
    url: jdbc:derby://localhost/microblog_development;create=true
    encoding: utf8
    pool: 5
    username: microblog
    password: microblog
    host: localhost
  2. Export der alten DB-Daten:
    Wir benutzen hierzu das Tool sqlitebrowser (http://sqlitebrowser.sourceforge.net) und erzeugen uns so einen SQL-Dump der alten SQLite-DB. Wir benutzen hierbei nur die SQL-Inserts für den User-Import. Diese speichern wir in die Datei:
    microblog/db/microblog.sql
  3. Für den Import erstellen wir einen Rake-Task:
    microblog/lib/tasks/sql-import.rake

    namespace :microblog do
    desc 'Import old SQL Data'
    task :sqlimport => :environment do
    dbConn = ActiveRecord::Base.establish_connection :development
    sql = File.open("db/microblog.sql").read
    sql.split(';').each do |sql_statement|
    dbConn.connection.execute(sql_statement)
    end
    puts "imported user data '#{Time.now}' "
    end
    end
  4. Erstellen des Setup-Scriptes:
    Folgende Schritte sind notwendig:

    1. Setzen aller benötiger Verzeichnisse
    2. installieren aller benötigter gems
    3. Starten des Derby-DB-Servers
    4. Rake db:migrate
    5. import der alten Daten
    6. Beenden des Derby-DB-Servers

    Das Script sieht wie folgt aus:
    jruby-setup.sh

    #!/bin/sh
    BASE_DIR=`pwd`
    CP=".:$BASE_DIR/jruby/lib/*:$BASE_DIR/derby/lib/derbyclient.jar"
    JAVA_OPTS="-Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriver"
    JRUBY="$BASE_DIR/jruby/bin/jruby"
    DERBY_HOME=`cd derby && pwd`
    export DERBY_HOME=$DERBY_HOME
    cd $BASE_DIR
    echo "setting up jgems..."
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem update --system
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install jruby-openssl --no-rdoc --no-ri
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install -v=2.2.2 rails --no-rdoc --no-ri
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install activerecord-jdbc-adapter activerecord-jdbcderby-adapter --no-rdoc --no-ri
    echo "starting derby..."
    $BASE_DIR/derby/bin/startNetworkServer &
    echo "setting up derby..."
    cd microblog
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/rake db:migrate
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/rake microblog:sqlimport
    cd $BASE_DIR
    echo "stopping derby..."
    $BASE_DIR/derby/bin/stopNetworkServer &

    Es ist zu erwähnen, dass es notwendig ist, jeweils auf die entsprechende jRuby-Installation zu verweisen.
    Weiterhin benötigt jRuby den entsprechenden derbyClientDriver, welcher in die (von jRuby später verwendete) JAVA_OPTS-Variabel eingetragen wird.
    Ebenfalls musst der Classpath soweit angepasst werden, dass sowohl jRuby, als auch Derby über die notwendigen Bibliotheken verfügen.
    Als letztes ist noch erwähnenswert, dass die beiden Rake-Tasks jeweils aus dem App-Verzeichnis ausgeführt werden.

  5. Das Start-Script.
    Letzendlich sind auch zum eigentlichen Betrieb des Servers Anpassungen notwendig, da auch hier die jRuby-Instanz mit den verwendeten gems benutzt werden sollen.
    Das Script sieht wie folgt aus:
    run.sh

    #!/bin/sh
    BASE_DIR=`pwd`
    CP=".:$BASE_DIR/jruby/lib/*:$BASE_DIR/derby/lib/derbyclient.jar"
    JAVA_OPTS="-Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriver"
    JRUBY="$BASE_DIR/jruby/bin/jruby"
    export BASE_DIR=$BASE_DIR
    export JRUBY=$JRUBY
    DERBY_HOME=`cd derby && pwd`
    export DERBY_HOME=$DERBY_HOME
    cd $BASE_DIR
    echo "starting derby..."
    $BASE_DIR/derby/bin/startNetworkServer &
    echo "setting up derby..."
    cd microblog
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/rake db:migrate
    echo "starting microblog"
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/microblog/script/server
    echo "stopping derby..."
    $BASE_DIR/derby/bin/stopNetworkServer &

    Es entspricht also einer abgespeckten Variante des Setup-Scriptes. Hierbei wird auch immer ein db:migrate aufgerufen, für den Fall, dass sich die DB-Struktur in der Zwischenzeit geändert haben sollte.

  6. Auslieferung ;-).
    Derby und jRuby belegen knapp 80 MB sodass es notwendig ist, die Dateigröße für den Transport zu verringern.
    Zuallererst sollten die benötigten gems am besten immer online bezogen werden, sodass man hier ein paar MB sparen kann.
    Weiterhin benutzen wir Jar um die vorhandenen Dateien auf ein 13 MB-Archiv zu packen.
    Die veränderten Scripte sehen wie folgt aus:
    Zuerst das Script, welches die vorhandenen Dateien packt:
    pack.sh

    #!/bin/sh
    find . -name '*.DS_Store' -type f -delete
    jar -cvf statusQ-runtime.jar derby/ jruby/ run.sh pack.sh microblog/db/microblog.sql microblog/lib/tasks/sql-import.rake
    rm -R jruby
    rm -R derby
    rm run.sh
    rm microblog/db/microblog.sql
    rm microblog/lib/tasks/sql-import.rake
    rm pack.sh

    Und nun das geänderte jruby-setup.sh Script, welches vor dem eigentlichen Setup noch für das Entpacken aller Dateien verantwortlich ist:
    jruby-setup.sh

    #!/bin/sh
    jar -xvf statusQ-runtime.jar
    rm -R META-INF
    chmod +x run.sh
    chmod +x setup.sh
    chmod +x pack.sh
    chmod +x jruby/bin/jruby
    chmod +x derby/bin/startNetworkServer
    chmod +x derby/bin/stopNetworkServer
    BASE_DIR=`pwd`
    CP=".:$BASE_DIR/jruby/lib/*:$BASE_DIR/derby/lib/derbyclient.jar"
    JAVA_OPTS="-Djdbc.drivers=org.apache.derby.jdbc.EmbeddedDriver"
    JRUBY="$BASE_DIR/jruby/bin/jruby"
    DERBY_HOME=`cd derby && pwd`
    export DERBY_HOME=$DERBY_HOME
    cd $BASE_DIR
    echo "setting up jgems..."
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem update --system
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install jruby-openssl --no-rdoc --no-ri
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install -v=2.2.2 rails --no-rdoc --no-ri
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/jgem install activerecord-jdbc-adapter activerecord-jdbcderby-adapter --no-rdoc --no-ri
    echo "starting derby..."
    $BASE_DIR/derby/bin/startNetworkServer &
    echo "setting up derby..."
    cd microblog
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/rake db:migrate
    $BASE_DIR/jruby/bin/jruby $BASE_DIR/jruby/bin/rake microblog:sqlimport
    cd $BASE_DIR
    echo "stopping derby..."
    $BASE_DIR/derby/bin/stopNetworkServer &

Als nächstes sollte die Scripte auf Windows portiert werden.
Weiterhin wäre es interessant, die Derby/jRuby Binaries jeweils direkt online zu beziehen.

Leave a Reply