JRuby: un linguaggio dinamico per la JVM

JVM come ambiente di esecuzione
Negli ultimi anni sono nati vari linguaggi scritti in Java ed eseguibili sulla Java Virtual Machine: ci sono delle reimplementazioni di alcuni gia' esistenti, scritti in C, come per esempio JRuby, Jython, Rhino (JavaScript) e PHP (progetto Quercus). Altri linguaggi sono nati direttamente per essere eseguiti sulla JVM e i piu' famosi sono Groovy, Scala, Clojure (un dialetto di Lisp) e JavaFX.

Java e' un linguaggio di programmazione affermato, sopratutto in ambiente enterprise ed e' l'alternativa Open Source a .NET.
Aziende come Oracle e IBM hanno basato le loro soluzioni di e-business su Java e questo ci fa capire quanto importante sia.
La Java Virtual Machine e' quindi la piu' famosa VM Open Source in ambiente enterprise. Nel corso degli anni molti sviluppatori hanno utilizzato Perl per avere una produttivita' maggiore e per poter utilizzare i vari strumenti tipici di Unix. Poi abbiamo assistito alla nascita di Python e Ruby, simili al Perl ma con una sintassi piu' elegante e maggiormente orientati agli oggetti.

Negli anni sono state sviluppate tantissime librerie e framework in Java, tanto per citarne alcuni, Spring e Hibernate, fra i piu' utilizzati in campo finanziario, Java Message Service (JMS), GigaSpaces (implementazione di Tuple Space), Terracotta per i clustering al livello della JVM, Axis per i web services, Lucene per l'indicizzazione e ricerca di testi. Per i linguaggi dinamici ci sono alcune librerie alternative, ma sono del parere che per Java ce ne siano molto di piu', soprattutto per l'ambiente enterprise, dove infatti Java e .NET sono stati adottati maggiormente rispetto agli altri linguaggi dinamici. Non voglio fare l'ennesimo articolo su quale linguaggio sia meglio e quale abbia piu' librerie e framework, il concetto a cui voglio arrivare e' che abbiamo la possibilita' di usare JRuby, dinamico, moderno e produttivo non solamente con le sue funzionalita', ma anche con tutte quelle che sono disponibili per Java. Alcune volte, usando PHP, Ruby o Python, succedde di non trovare le librerie che ci servono, oppure di non trovarle all'altezza delle nostre aspettative. Tutto questo con Java e' molto piu' difficile che accada, ci sono cosi tante libreire Open Source e commerciali. JRuby puo' aiutarci quando ce ne manca una, abbiamo tutto il mondo Java a nostra disposizione.

Molte aziende hanno i loro software scritti in Java, quindi per estenderli ed integrarli ci vuole lo stesso Java o trovare delle soluzioni per usare quelli esistenti. Per questa ragione sono nati linguaggi come Jython e JRuby. Utilizzando Jython e JRuby oltre che avere i benefici di quei linguaggi dinamici possiamo appoggiarci ad una piattaforma stabile ed affidabile, con tante librerie e framework disponibili, ma senza avere gli oneri che lo sviluppo per Java comporta. In poche parole utilizzare il meglio dei due mondi. Un problema dei linguaggi dinamici come Ruby e compagni, e' la difficolta' di farsi accettare in ambienti corporativi, dove regnano sovrani .NET (di solito C#) e Java. La possibilita' di asserire che JRuby viene eseguito sulla JVM e che le applicazioni web possono essere installate sul server applicativo gia` installato in azienda, puo' aprire porte che altrimenti sarebbero chiuse.

Un altro scopo per il quale mi sono interessato a JRuby e` quello didattico. Utilizzando le librerie Java vi da la possibilita` di impararle, di tenervi in contatto con questo mondo parallelo e magari di scrivere una parte dei vostri programmi in Java.

In questo articolo vi mostrero' JRuby. Perche' JRuby invece di Jython? Pur amando Python devo dire che la popolarita' di Ruby e' dovuta al suo framewrok piu' famoso, Ruby on Rails. Ruby on Rails ha portato una forte innovazione nel modo di sviluppare le applicazioni web, integrando tutti gli strumenti necessari per lo sviluppo delle applicazioni con interfaccia web allo stato dell'arte. Grazie a questa popolarita' molte anziende stanno integrando e portando le lo applicazioni J2EE su Ruby on Rails, almeno il front end e spesso comunicando con la business logic via web services. Con JRuby e' possibile comunicare direttamente con le applicazioni legacy, visto che, come Java, viene eseguito sulla JVM. JRuby puo' essere comodo agli sviluppatori, che non vogliono rinunciare a sviluppare in un ambiente tipicamente Java. Molte aziende hanno delle policy IT molto rigide e per cambiare un application server non e' molto semplice, implica discussioni, riunioni, scrittura di nuove policy, test e messa in produzione. Voglio farvi vedere come installare JRuby, provare una applicazione gia' esistente sul server di sviluppo e come fare il deployment su un Java Servlet Container come Tomcat.

Deployment di una applicazione Ruby on Rails su Tomcat

Ci sono i pacchetti gia' disponibili per varie distribuzioni Linux, ma vi consiglio di installare JRuby manualmente, visto che e' molto semplice ed avrete il pieno controllo. Scaricate jruby: http://jruby.org/download decomprimetelo nella vostra home directory:


tar xzvf jruby-bin-1.4.0RC1.tar.gz

Nel vostro profilo (~/.profile), dichiarate JRUBY_HOME ed aggiungete la bin directory di JRuby alla vostra path.


export JRUBY_HOME=~/jruby
export PATH=$JRUBY_HOME/bin:$PATH

Ovviamente dovete avere Java installato nel vostro sistema. Con il comando jruby -v potete vedere se lo avete installato corretamente e visualizzare la sua versione. Ora dovete installare Ruby on Rails come dobbiamo fare, di solito, con Ruby. Questo e' il comando:


jruby -S gem install mongrel activerecord-jdbcmysql-adapter rails

Avrete notato che la gem activerecord-jdbcmysql-adapter e' diversa dalla solita installazione di Rails, infatti e' uno de progetti principali di JRuby, e' la reimplementazione di ActiveRecord per utilizzare JDBC per la connessione ai database. Su Windows ci sono dei problemi tra la gem mysql ed il client MySql 5.1, infatti o dovuto installare la versione 5.0, JDBC non ha di questi problemi basta compiare in $JRUBY_HOME/ il MySQL Connector/J. Ora possiamo installare l'applicazione con Ruby on Rails. Invece di creare la solita applicazione demo, voglio mostrarvi come installare Fat Free CRM, una applicazione gia' esistente, sviluppata con Rubu on Rails. Scaricate Fat Free CRM da github (io ho scaricato la versione 0.9.8), decomprimetela e rinominate la directory fat_free_crm. Ora dobbiamo creare due database, uno per lo sviluppo ed uno per la produzione:


mysqladmin -u root -p create fat_free_crm_development
mysqladmin -u root -p create fat_free_crm_production

Dovreste avere la directory della applicazione con il nome fat_free_crm, entrateci dentro e copiate il file di configurazione del database di esempio per MySql:


cp conf/database.mysql.yml conf/database.yml

Configurate i parametri per la connessione al database, qui sotto trovate un esempio:


development:
adapter: jdbcmysql
encoding: utf8
database: fat_free_crm_development
pool: 5
username: root
password: vostra_password
socket: /tmp/mysql.sock

production:
adapter: jdbcmysql
encoding: utf8
database: fat_free_crm_production
pool: 5
username: root
password: vostra_password
socket: /tmp/mysql.sock

Ovviamente non dovete usare l'utente di root come utente in produzione, qui e' utilizzato solamente come esempio. Ora possiamo migrare il database di sviluppo:


rake db:migrate

L'applicazione puo' essere eseguita su Mogrel, come facciamo di solito con Rails durante lo sviluppo:


jruby -S script/server

Se visitiamo http://localhost:3000 possiamo vedere la pagina di login del CRM. La differenza principale, e' che Mogrel viene eseguito senza apparenti differenze con Ruby, ma in questo caso viene eseguito sulla JVM. A questo punto possiamo mettere in produzione l'applicazione su Tomcat. Dobbiamo avere installato il supporto per OpenSSL e per una gem che viene utilizzata da warble:


jruby -S gem install jruby-openssl faker

Come saprete, per fare il deployment di una applicazione web su un Java application server dobbiamo creare un war file, copiarlo nella directory che contiene le applicazioni web, su Tomcat si chiama webapps, e poi dare il comando per il deployment o riavviare il server. La gem utilizzata per creare un war con JRuby e' warbler, quindi installiamola:


jruby -S gem install warbler

Ci samo quasi, ma conviene installare warbler come plugin, perche' possiamo avere alcuni comandi utili durante la creazione dei file war:


warble pluginize

Creiamo il file di configurazione per warbler (config/warbler.rb):


warble config

Il file diconfigurazione c serve principalmente per dire a warble quali gem includere, nel nostro caso, accertiamoci che le seguaenti linee siano decommentate:


config.gems += ["activerecord-jdbcmysql-adapter", "jruby-openssl"]
config.gem_dependencies = true

Il file di configurazione e' ampiamente documentato nei commenti. A questo puntosiamo pronti per creare semplicemente il war file con:


warble

Ora, nella root del vostro progetto, vedrete il war file contentente l'applicazione RAils: fat_free_crm.war. L'applicazione in produzione avra' bisogno del suo database, quindi facciamo la migrazione:


jruby -S rake db:migrate RAILS_ENV=production

Copiate il file nella directory webapps di Tomcat e riavviatelo:


cp /home/virtualbox/fat_free_crm/fat_free_crm.war /opt/tomcat/webapps/
/opt/tomcat/bin/shutdown.sh
/opt/tomcat/bin/startup.sh

Potete vedere l'applicazione funzionante su Tomcat sulla porta 8080: http://localhost:8080. Le possibilita' dove fare il deployment applicazioni con JRuby sono molte, lo stesso Mongrel ed i vari server come Tomcat, GlassFish, Jetty ed altri. E' possibile avere applicazioni Ruby on Rails su cluster basati sulle tecnologie Java, quindi il mito che Rails non e' scalabile non e' piu' sostenibile. Se non vi piace lavorare a linea di comando o volete una IDE completa basata su JRuby, che vi permetta di provare le vostre applicazioni su GlassFish anche in development, potete utilizzare NetBean per Ruby.

Un altro campo dove JRuby ci puo' aiutare e' lo sviluppo di applicazioni desktop. Ci sono molti toolkit grafici, anche multi piattaforma, ma Java eccelle proprio in questo campo, con Swing e SWT. Quindi se non volete utilizzare i binding per GTK+ o FOX Toolkit, potete sviluppare una applicazione desktop richiamando direttamente le classi come fareste con Java. Ovviamente la sintassi e' leggermente diversa e dovete sapere come implementare i Java listener con JRuby, ma a parte questo e' piu' semplice di creare una applicazione Java pura. Il vantaggio di usare un linguaggio dinamico puo' essere dimostrata con jirb, l'inerprete a linea di comando, basta scrivere qualche libreria ed in modo dinamico possiamo visualizzare una finestra con Swing. Qui potete vedere un esempio dei comandi che ho inserito nella mia console:


riccardotacconi ~>jirb
irb(main):001:0> include Java
=> Object
irb(main):002:0> import javax.swing.JFrame
=> Java::JavaxSwing::JFrame
irb(main):005:0* frame = JFrame.new "JRuby Message"
=> #>
irb(main):007:0> frame.pack
=> nil
irb(main):008:0> frame.visible = true
=> true
irb(main):009:0>

Alla fine dei comandi, jirb mi ha creato un finestra con Swing. Come vedete dobbiamo prima includere Java e dopo possiamo dichiarare degli oggetti con delle classi non Ruby, ma Java. Come vi ho detto, la sintassi per definire gli eventi con JRuby e' differente da Java, ma ci vuole poco per imparare con JRuby, nel listato 1, potete vedere come definirli.


# listato 1
include Java
import javax.swing.JFrame

frame = JFrame.new
frame.default_close_operation = JFrame::EXIT_ON_CLOSE

# creo un menu Swing
barra = javax.swing.JMenuBar.new
menu = javax.swing.JMenu.new "File"
item = javax.swing.JMenuItem.new "Open"

# listener Java. Questo e' il modo 'the Ruby way'
# dove il blocco che gestisce gli eventi sta all'interno delle parentesi tonde
menu.add_menu_listener(javax.swing.event.MenuListener.impl do |method, evt|
puts evt.class
case method.to_s
when "menuDeselected"
puts 'hidden'
when "menuSelected"
puts 'visible'
end
end)

# aggiungo il menu e visualizzo la finestra
menu.add item
barra.add menu
frame.jmenu_bar = barra
frame.pack
frame.visible = true

Note storiche
Anche se di solito la storia di un progretto viene subito dopo l'introduzione, od addirittuara al suo interno, ho preferito metterla alla fine, sperando di avervi stimolato dopo le dimostrazioni pratiche. Il progetto e' nato nel 2001 da Jan Arne Peterson. All'inizio le prestazioni erano veramente pessime, ma poi sono migliorate in futuro. Al suo inizio il progetto ha focalizzato i suoi sforzi sulla compatibilita' e dopo aver convertito ActiveRecord ad ActiveRecord-JDBC, quindi passando dalla connettivita` scritta in C a quella di Java, ovvero JDBC, JRuby e` stato migliorato anche per le prestazioni, a tal punto che risulta essere piu` performate rispetto all'interprete standard, MRI.Nel 2006 Sun assume due sviluppatori di JRuby, Charles Nutter, Thomas Enebo, aumentatndo gli sforzi e la credibilita` del progetto. Nel 2009 Charles Nutter, Thomas Enebo lasciano Sun, vista l'incertezza dopo l'acquisto da parte di Oracle, e vanno a lavorare per Engine Yard, nota azienda di hosting per Ruby. Un'altra azienda dietro a JRuby e` la ThoughtWorks, l'azienda dove Martin Fowler e` Chief Scientist. Ola Bini [5] fa parte di ThoughtWorks ed e` uno sviluppatore di JRuby, il quale ha tenuto parte a molti 'talk' su JRuby, anche a Google. Tra gli esempi di applicazioni commerciali scritte in JRuby voglio citare Mingle, un sotware per la gestione di progetti agili. Alla fine del 2009 JRuby e` compatibile con JRuby 1.8.7 e sara` presto compatibile con la nuova versione 1.9.x.

Webografia
[1] http://en.wikipedia.org/wiki/List_of_JVM_languages - Lista dei linguaggi per la JVM (inglese)
[2] http://localhost:3000 - Download di JRuby
[3] http://dev.mysql.com/downloads/connector/j/5.1.html - MySQL Connector/J
[4] http://github.com/michaeldv/fat_free_crm/downloads - Fat Free CRM
[5] http://blog.emptyway.com/2008/04/08/120-seconds-guide-to-jruby-on-rails/ - Installare, creare ed eseguire una applicazione Ruby on Rails su JRuby (inglese).
[6] http://blog.nicksieger.com/articles/2007/09/04/warbler-a-little-birdie-t... - Note introduttive su come utilizzare warbler, direttamente dal suo creatore, Nick Sieger (inglese).
[5] http://www.youtube.com/watch?v=PfnP-8XbJao - Google Tech Talks: Ola Bini spiega JRuby (inglese).
[6] http://www.youtube.com/watch?v=pHMpf6hx8Ek - ?????

Bibliografia
Justin Edelson, Henry Liu, 'JRuby Cookbook, 1st edition', O'Reilly Media Inc, 2008.

Ol Bini, 'Practical JRuby on Rails Web 2.0 Projects: Bringing Ruby on Rails to Java', Apress 2007.

________________

""