Spring Roo è uno strumento web-RAD per applicazioni Java EE basate su Spring: permette di scrivere velocemente il prototipo di una applicazione web e di un web-CRUD in meno di 10 minuti. Se a questo aggiungiamo che si integra facilmente con Cloud Foundry di VMware’ bè le ragioni per prenderlo in considerazione ci sono tutte.
Nuove funzionalità per Spring Roo
Dalla nuova versione di Spring Roo, 1.2.0, sono state introdotte delle funzionalità molto importanti che permettono di avere un approccio “più pragmatico”, quali:
- incremental DataBase Reverse Engineering (DBRE);
- supporto per JSF tramite PrimeFaces;
- supporto al progetto multi-modulo.
Il supporto per le JSF tramite PrimeFaces è importante per poter usare Roo con le nuove tecnologie vista; purtroppo però questo plugin non sembra ancora al livello del plugin per le JSP.
Per quanto riguarda le altre due migliorie, esse sono molto utili e permettono di avere un approccio più pragmatico nella creazione di un progetto Java EE.
Infatti appare poco realistico il dover creare a mano gli entity beans tramite i comandi entity e field; invece è più corretto creare dapprima il database, e poi effettuare un reverse engineering ottenendo gli entity bean risultanti.
Il plugin DBRE di Spring Roo permette non solo di effettuare il reverse engineering “a freddo”, cioè alla creazione del progetto, ma permette anche di tenere aggiornato il progetto a seguito di cambiamenti dello schema del DB. In pratica, se si aggiunge una colonna a una tabella Roo, se ne accorge e fa la stessa modifica sul codice Java.
Il supporto multi-modulo è molto utile per poter organizzare in modo razionale un progetto multi-layer: infatti per convenzione un progetto Java EE è diviso almeno nei moduli di core e web.
Core è il modulo in cui sono contenute tutte le classi che permettono l’accesso al DB; inoltre sono contenute anche le funzionalità di base sul DB. Inoltre in questo modulo vengono implementati i servizi relativi agli entity bean.
Web: è la parte dove si trovano le pagine web.
Questo schema riflette l’architettura tipica di un progetto Spring Roo. Ci sembra quindi opportuno seguire la stessa demarcazione anche nella organizzazione dei sotto-moduli Maven del progetto.
Esempio di utilizzo delle nuove funzionalità di Spring Roo
Supponiamo di dover implementare un sito web di prenotazione a un ristorante. Quello che vogliamo fare è un prototipo che implementi solamente il CRUD sul database già preesistente. Supponiamo, in maniera molto lineare, che il DB sia un server MySQL.
Il progetto sarà diviso in:
- modulo principale: è un progetto di tipo POM;
- modulo di persistenza e servizi: è un progetto di tipo JAR;
- modulo web: è di tipo WAR.
Creazione di un progetto modulare
Supponiamo di avere le tabelle già create dentro un databaes MySQL. Adesso iniziamo a creare il nostro progetto Java EE sul DB preesistente. Per creare un progetto modulare basta usare il comando module. Creiamo dapprima il progetto root di tipo POM, poi subito dopo creiamo il modulo core:
roo> project --topLevelPackage org.mokabyte --packaging POM
roo> module create --moduleName core --topLevelPackage ~.core
A questo punto definiamo il database da usare tramite il seguente comando:
roo> jpa setup --provider HIBERNATE --database MYSQL --hostName localhost
--userName root --password 12qwas --databaseName mokabyte
Adesso occorre effettuare il reverse engineering dal DB (durante tutte le operazioni che seguono il DB deve essere acceso e accessibile).
Installazione dei driver per MySQL
Prima di poter effettuare il reverse engineering da un database è necessario installare i driver e i moduli OSGi che servono a Roo per integrarlo. Questo processo è ben documentato ed è automatico per i database OpenSource; ovviamente, per database proprietari, come Oracle, il driver non è presente nei repository Maven di SpringSource, quindi è necessario fare dei passi a mano (peraltro molto semplici e ben documentati).
Prima di tutto occorre eseguire il comando di introspezione del database per poter capire che tipo di DB è (ecco perchè il DB deve essere acceso):
roo> database introspect --schema no-schema-required
Located add-on that may offer this JDBC driver
1 found, sorted by rank; T = trusted developer; R = Roo 1.1 compatible
ID T R DESCRIPTION -------------------------------------------------------------
01 Y Y 5.1.13.0001 #jdbcdriver driverclass:com.mysql.jdbc.Driver. This...
--------------------------------------------------------------------------------
[HINT] use 'addon info id --searchResultId ..' to see details about a search result
[HINT] use 'addon install id --searchResultId ..' to install a specific search result, or
[HINT] use 'addon install bundle --bundleSymbolicName TAB' to install a specific add-on version
JDBC driver not available for 'com.mysql.jdbc.Driver'
Roo “ha capito” che abbiamo a che fare con MySql, e adesso occorre aggiungere il driver trovato tramite il comando:
addon install id --searchResultId 01
Invece il comando :
addon info id --searchResultId 01
restituisce le informazioni sulla versione del driver disponibile.
Ora il driver per MySql è installato correttamente, quindi possiamo inviare il comando di reverse engineering:
core roo> database reverse engineer --schema mokabyte --package ~.DB --testAutomatically
Created core|SRC_MAIN_RESOURCES/dbre.xml
Updated core|ROOT/pom.xml
Updated core|SRC_MAIN_RESOURCES/META-INF/persistence.xml
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/Menu.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/Ordinazioni.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/OrdinazioniPietanza.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/Pietanze.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/PietanzeMenu.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/Tavoli.java
Created core|SRC_MAIN_JAVA/org/mokabyte/core/DB/TipoPietanza.java
Created core|SRC_TEST_JAVA/org/mokabyte/core/DB
Created core|SRC_TEST_JAVA/org/mokabyte/core/DB/MenuDataOnDemand.java
Created core|SRC_TEST_JAVA/org/mokabyte/core/DB/MenuIntegrationTest.java
...
A questo punto abbiamo già pronta la parte CRUD e lo scheletro del progetto Java EE senza dover scrivere neanche una riga di codice!
Finders e Web
Aggiungiamo dei “finders” opportuni agli entity beans trovati. Per esempio, dalla tabella delle Pietanze, vogliamo un metodo di ricerca che ci restituisca tutte le pietanze per nome:
finder add --finderName findPietanzesByNomeLike --class ~.DB.Pietanze
oppure anche:
finder add --finderName findPietanzesByNomeEquals --class ~.DB.Pietanze
In base al nome del finder (il nome è convenzionale), Roo capisce che tipo di finder vogliamo creare, e scriverà la query correttamente per noi. I finders vengono aggiunti all’entity bean tramite annotazioni specifiche che permettono di arricchire l’entity bean.
Servizi
Una volta creati i finders, possiamo creare i nostri servizi. Per esempio creiamo il nostro servizio per Pietanze:
service roo> service --interface ~.service.PietanzeService --entity ~.DB.Pietanze
Allo stesso modo creiamo il layer web e aggiungiamo il CRUD basato su JSP con gli stessi comandi che abbiamo visto nell’esempio precedente. Allegato a questo articolo (menu in a destra a lato della pagina) troverete gli script MySQL per creare il database di questo esempio e lo script roo “loggato” da Roo stesso.
Test
Spring Roo permette anche la creazione e l’esecuzione automatica dei test sia a livello DB (nel modulo della persistenza) che a livello web, tramite la libreria Selenium che permette di simulare l’utilizzo delle pagine web. Per creare i test unitari e di integrazione basta creare gli entity con il parametro
--testAutomatically
da dare al comando di reverse engineering del DB.
Per ogni entity bean, Roo genera i file DataOnDemand e IntegrationTest che servono per effettuare il test CRUD sull’entity bean e per implementare dei test di integrazione più specifici per il progetto (qui è lo sviluppatore che scrive i propri test di integrazione).
Per esempio Roo ha creato i file PietanzeDataOnDemand.java e PietanzeIntegrationTest.java. I test vengono eseguiti automaticamente da maven. Per la parte web possiamo generare automaticamente uno scaffold via web:
roo>controller scaffold ~.web.ScaffondController
Il controller viene creato utilizzando il supporto REST, e possono essere utilizzati come template per implementare un proprio controller. Ora agganciamoci un test Selenium:
roo>selenium test -controller ~.web.ScaffonldController
ed eseguiamo i test:
roo>perform test
Cloud Foundry
Cloud Foundry è un nuovo PaaS (Platform as a Service) open source rilasciato da VMware. Con Spring Roo è possibile eseguire dei comandi direttamente dalla propria shell: in questa maniera le funzionalità di Cloud Foundry sono immediatamente disponibili. Ciò che si può fare è: loggarsi alla shell di Cloud Foundry, vedere quali sono i servizi installati, effettuare il deploy di un servizio e raccogliere statistiche.
Prima di tutto occorre installare l’add-on per Cloud Foundry tramite i seguenti comandi:
pgp automatic trust
addon install bundle --bundleSymbolicName org.springframework.roo.addon.cloud.foundry
Dopo aver installato l’add-on, è necessario loggarsi alla propria cloud tramite il comando login:
cloud foundry login
Questo comando prende tre parametri in input: email, password, cloudControllerUrl (URL del controller di cloud foundry). email e password corrispondono alle proprie credenziali, e vengono formite solamente la prima volta che ci si connette alla Cloud Foundry. Invece l’Url del controller della Cloud Foundry non è obbligatorio, ma è necessario inserirla per utilizzare una propria cloud foundry locale privata invece di quella fornita di default da VMware (api.cloudfoundry.com).
Per vedere i comandi disponibili per accedere alla Cloud Foundry occorre scrivere cloud foundry e poi premere TAB: nella shell di Roo comparirà la seguente lista di comandi:
roo> cloud foundry
cloud foundry bind cloud foundry clear cloud foundry create
cloud foundry delete cloud foundry deploy cloud foundry files
cloud foundry info cloud foundry list cloud foundry login
cloud foundry map cloud foundry restart cloud foundry start
cloud foundry stop cloud foundry unbind cloud foundry unmap
cloud foundry update cloud foundry view
Per vedere le informazioni associate alla nostra istanza di Cloud Foundry, digitate il comando info:
roo> cloud foundry info
VMwarès Cloud Application Platform
For support visit support@cloudfoundry.com
Target: http://api.cloudfoundry.com (0.999)
User: my-mail@gmail.com
Usage: Memory (0MB of 2048MB total)
Services (0 of 16 total)
Apps (0 of 20 total)
Il comando info ci dà informazioni sull’uso della memoria, il numero di applicazioni ditribuite e il numero di servizi che stanno in esecuzione. Inoltre viene specificato il limite di memoria imposto: 2 gigabyte.
Il deploy del WAR
Una volta loggati alla propria Cloud Foundry, possiamo effettuare il deploy di un WAR tramite il comando:
cloud foundry deploy
I parametri da dare al comando di deploy sono: appName, path, url e quantità di memoria da poter usare. Se il WAR dell’applicazione non è ancora disponibile, allora Roo lo creerà utilizzando Maven come configurato dal progetto Roo. Ecco un esempio:
cloud foundry deploy --appName my-web-app --path
/target/my-web-app-0.1.0.BUILD-SNAPSHOT.war --memory 512MB
Una volta creata l’applicazione, essa è visibile tramite il comando:
cloud foundry list apps
Su una instanza di Cloud Foundry, possiamo utilizzare un numero limitato di servizi, come per esempio: MySQL, MongoDB Redis e RabbitMQ. Per sapere la lista di servizi supportati (application service) basta digitare il comando:
cloud foundry list service
Per ora la lista di servizi supportati è limitata, ma in futuro verranno inclusi sempre nuovi servizi. Per quanto riguarda la tecnologia Java, possiamo quindi usare solamente il database MySQL come supporto SQL (su Cloud Foundry possiamo installare non solo applicazioni Java, ma anche applicazioni scritte in altri linguaggi, come Scala, Ruby e altri), quindi nel nostro progetto Roo dobbiamo per forza scegliere MySql come provider di persistenza Sql:
persistence setup --database MYSQL --provider HIBERNATE
In questo esempio abbiamo scelto di usare Hibernate, ma avremmo potuto anche usare EclipseLink. Una volta certi che il nostro WAR utilizzi MySql, creiamo il servizio MySql e leghiamolo alla nostra applicazioni web:
cloud foundry create service --serviceName my-web-app-DB --serviceType mysql
cloud foundry bind service --appName my-web-app --serviceName my-web-app-DB
Tramite il primo comando abbiamo creato il servizio MySql (e chiamato my-web-app-DB), e tramite il secondo comando l’abbiamo legato alla nostra applicazione (e reso disponibile all’interno del Cloud Foundry).
A questo punto possiamo far partire la nostra applicazione web tramite il comando:
cloud foundry start app --appName my-wen-app
Ed infine ecco la lista di applicazioni installate:
roo> cloud foundry list apps
================================= Applications =================================
Name Status Instances Services URLs
---- ------ --------- -------- ----
my-web-app STARTED 1 my-web-app-DB my-web-app.cloudfoundry.com
roo> cloud foundry list services
================== System Services ===================
Service Version Description
------- ------- -----------
mongodb 1.8 MongoDB NoSQL store
redis 2.2 Redis key-value store service
mysql 5.1 MySQL database service
= Provisioned Services =
Name Service
---- -------
my-web-app-DB mysql
Conclusioni
Abbiamo concluso questa serie di articoli introduttivi a Spring Roo: abbiamo cercato di metterne in evidenza i benefici che possiamo guadagnare da questo strumento. In conclusione non c’è nulla che non si possa fare senza Spring Roo: è sempre possibile scrivere un prototipo velocemente senza utilizzare Spring Roo, così come è sempre possibile usare i comandi di Cloud Foundry senza utilizzare la shell di Roo.
Quindi Spring Roo non aggiunge nulla di nuovo a quello che potevamo fare già prima, non solo: Spring Roo non è da usare per imparare tecnologie nuove. Quindi non è affatto uno strumento didattico: al contrario, occorre essere esperti delle tecnologie che stiamo usando per poterle poi utilizzare al meglio dentro la schell di Spring Roo.
Quindi perchè usare Spring Roo? La risposta sta nella possibilità di poter automatizzare i primi passi di scrittura di un prototipo (o di una applicazione finita) Java EE basata su Spring e di poter utilizzare assieme diverse tecnologie senza alcun bisogno di scrivere codice e/o configurazioni personalizzate, e quindi senza doversi reinventare ogni volta delle proprie convenzioni ma utilizzando quelle standard stabilite proprio dagli autori di Spring Framework.
Riferimenti
[1] Search Software Quality
http://searchsoftwarequality.techtarget.com/definition/rapid-application-development
[2] Wikipedia sul “convention over configuration” principle
http://en.wikipedia.org/wiki/Convention_over_configuration
[3] Wikipedia propone una lista di strumenti RAD
http://en.wikipedia.org/wiki/List_of_rapid_application_development_tools
[4] Wikipedia sul “delegation pattern”, utilizzato per implementare il JpaRepository
http://en.wikipedia.org/wiki/Delegation_pattern
[5] La libreria Spring Data è un progetto che contiene tutti i sotto progetti che permettono l’accesso a data storage di diverso tipo e tramite specifiche tecniche, tra i quali JDBC, JPA, MongoDB, Hadoop, Neo4j, etc…
http://www.springsource.org/spring-data
[6] MongoDB home page
[7] Home Pages di diverse tecnologie web:
Prime Faces
Vaadin
Spring Web Flow: che è una estenzione di Spring MVC. Supporta le JSP, JSF e le Portlet.
http://www.springsource.org/spring-web-flow
Progetto Spring-Flex per il supporto ad Adobe Flex
http://www.springsource.org/spring-flex
[8] Sono da leggere una serie di articoli sul sito dell’IBM su Spring Roo che trattano di temi quali: come scrivere degli add-ons o come integrare Roo con Clound Foundry.
Building from source
http://www.ibm.com/developerworks/opensource/library/os-springroo1/index.html
Developing an application with Spring Roo
http://www.ibm.com/developerworks/opensource/library/os-springroo2/index.html
Developing Spring Roo add-ons
http://www.ibm.com/developerworks/opensource/library/os-springroo3/index.html
Rapid application development in cloud with Spring Roo and Cloud Foundry
http://www.ibm.com/developerworks/opensource/library/os-springroo4/index.html
[9] Twitter su Spring Roo
https://twitter.com/#!/SpringRoo
[10] Aspectj sul Web.
AspectJ era un vecchio progetto di Xerox, poi donato a Eclipse: è stato il primo progetto Java di implementazione del paradigma degli aspetti (AOP: Aspect Oriented Programming). Attualmente il leader del progetto AspectJ è Adrian Colyer, CTO di SpringSource.
http://www.eclipse.org/aspectj/doc/next/progguide/index.html
http://it.wikipedia.org/wiki/AspectJ
http://en.wikipedia.org/wiki/PARC_%28company%29
Michele Mazzei si è laureato in Scienze dell’Informazione nell’ormai lontano 1998. Si occupa di progettazione e scrittura di software in Java/Java EE e in C/C++ sul mondo Linux. Lavora a Roma in ambito spaziale maturando esperienze in ambito OGC, GIS, Map Server, Payload Data Ground Segment (PDGS). Si interessa di tecnologie web basate su Java/Java EE, ma anche di tecnologie C/C++ del mondo Linux.