Prosegue la trattazione sul famoso tool di build fatto in Java: questo mese presentiamo un file di esempio completo con il quale realizzare le più comuni operazioni durante lo sviluppo di un progetto JavaEE.
Dopo l‘articolo introduttivo del mese scorso, proseguiamo questo mese con la presentazione di un file di build di esempio che raccoglie le più comuni operazioni necessarie durante lo sviluppo di un progetto JavaEE. Non abbiamo certamente la pretesa di presentare una soluzione univer-sale adatta a ogni programmatore e ogni caso specifico, ma piuttosto fornire gli spunti da cui poi partire per creare file di build personalizzati e specifici per le varie esigenze.
Un build.xml per tutte le stagioni
Di seguito riporto un esempio di file build.xml utilizzato in alcuni dei progetti JavaEE sui quali ho lavorato: non ho la pretesa di fornire la risposta a tutte le esigenze di ogni program-matore che leggerà questo articolo, ma piuttosto fornire una base (già piuttosto completa a dire il vero) dalla quale partire per la realizzazione di build file personalizzati più potenti e specifici.
I target contenuti nel file permettono la compilazione, il build globale e il deploy di una ap-plicazione EJB, e forniscono anche la possibilità di eseguire le invocazioni di sessions ed enti-ties da parte di client standalone.
Per prima cosa vediamo pezzo per pezzo i passaggi più importanti del file. In allegato il letto-re potrà trovare il file completo.
Inizializzazione: definizione delle variabili di lavoro
Il file come al solito inizia con l‘intestazione XML e il nome del progetto Ant
ÃÂ
dove viene definito il target di default e la directory radice del progetto: definire questa posi-zioneÃÂ è utile perché permette di semplificare e in qualche modo automatizzare il processo di composizione delle varie variabili necessarie per le operazioni di compilazione, build, deploy ed esecuzione finale.
A partire dalla directory base di progetto, come si puà notare, si possono comporre tutte le localizzazioni delle altre directory:
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
Le definizioni appena viste mappano quindi una struttura di directory di progetto ben preci-sa, che in questo caso è organizzata in qusto modo:
– directoy_radice_progetto
ÃÂ –ÃÂ src: la directory con i sorgenti.
ÃÂ –ÃÂ classes: la directory con i compilati.
ÃÂ –ÃÂ resources: la directory contenente risorse di vario tipo da cui accingere per compilare.
ÃÂ –ÃÂ releases: la directory con i build di progetto.
ÃÂ –ÃÂ temp: una directory di appoggio utile per le fasi intermedi di produzione.
ÃÂ –ÃÂ lib: una directory dove sono posizionate tutte le librerie di progetto necessarie per le fasi di compilazione e build.
Parlando di configurazione di lavoro utile provvedere anche a impostare i vari parametri re-lativi alla connessione JDBC verso il database utilizzato nel progetto.
Questa sezione è utile per automatizzare la creazione e popolamento del db utilizzato dalla applicazione (si veda il target successivo “create-db”).
Di seguito è riportato il blocco con la configurazione per la connessioneÃÂ JDBC:
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
Si noti il riferimento al driver JDBC che deve essere inserito nel classpath del runtime Ant (in questo caso il driver verrà inserito nella directory lib utilizzata per comporre il classpath).
Per quanto concerne il deploy in ambito enterprise, può essere utile definire il nome dell‘ar-chivio che verrà creato durante la fase di build: in questo caso si è deciso quindi di definire una variabile apposita
Volendo deployare in un application server come JBoss o Tomcat, dove il deploy può essere fatto con una semplice operazione di copia, è necessario definire dove copiare i file di build; questa cosa si può ottenere banalmente definendo in una variabile il path assoluto, come ad esempio:
ÃÂ ÃÂ ÃÂ
Una alternativa più elegante (ma che richiede unaÃÂ opportuna configurazione della shell di esecuzione), prevede l‘utilizzo della proprietà “env” che è associata al set di variabili di am-biente:
ÃÂ ÃÂ
ÃÂ
Setup dell‘ambiente
Spesso possono risultare drammaticamente utili alcuni task che effettuano alcune operazioni di preconfigurazione dell‘ambiente di lavoro, specialmente in quei casi in cui si lavora in un team e si condivide il progetto su un repository CVS: alla prima operazione di checkout fra i vari file il nuovo membro del team si troverà anche tutte le risorse necessarie per configurare la propria piattaforma di lavoro (librerie, ma anche file di configurazione dell‘application server, script di creazione SQL, etc..).
Molto comodo in questo contesto è il seguente target che si connette al database e tramite uno script SQL, recuperato dalla directory di risorse (${basedir}/sql), esegue una inizializza-zione delle tabelle.
Di fatto non ci sono limiti alle operazioni che si possono eseguire sul database con questa tecnica dato che nel file SQL è possibile inserire un numero arbitrario di operazioni (di crea-zione, di popolamento, cancellazione).
ÃÂ
ÃÂÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂÃÂ ÃÂ ÃÂ url="${db.jdbc.url}"
ÃÂ ÃÂ ÃÂ userid="${db.userid}"
ÃÂ ÃÂ ÃÂ password="${db.password}"
ÃÂ ÃÂ ÃÂ src="${basedir}/sql/${sql.createDB}">
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
Accanto alle operazioni di creazioni delle tabelle nel database, spesso è necessario configura-re l‘application server per consentire la connessione al database. In JBoss questa operazioneÃÂ è molto semplice e corrisponde a copiare un file XML (il datasource file) nella directory di deploy.
Anche se per la sua semplicità questa operazione potrebbe essere eseguita manualmente, per evitare dimenticanze (specie nei nuovi membri del team appena arrivati), ho introdotto nel mio file di build questo semplice target:
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
Ovviamente una organizzazione comoda potrebbe essere quella di riunire tutti i task di setup in modo piuttosto semplice, tramite la composizione delle dipendenze:
ÃÂ
Compilazione
Un target classico e praticamente omnipresente: quello della compilazione. Molto utile il ri-ferimento alla dir client di JBoss che consente di risolvere ogni riferimento a API e librerie di EJB ma non solo; chiunque abbia in qualche modo sviluppato applicazioni EJB, sa che la ri-soluzione delle varie librerie client EJB-JavaEE non è mai una cosa semplice, e quindi ap-prezzerà certamente la soluzione adottata, efficace quanto semplice.
ÃÂ
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂÃÂ ÃÂ ÃÂ destdir="${classes.dir}"
ÃÂ ÃÂ ÃÂ debug="on"
ÃÂ ÃÂ ÃÂ deprecation="on"
ÃÂ ÃÂ ÃÂ optimize="off"
ÃÂ ÃÂ >
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
Creazione dell‘archivio jar e deploy
Questo target crea il file jar di deploy (quindi in questo caso si fa esplicito riferimento ad una applicazione EJB) tramite il quale è possibile eseguire poi il deploy della applicazione. Si noti come sia possibile, anche se non necessario, eliminare i riferimenti alle classi che non appar-tengono alla parte server (sono le classi client di test):
ÃÂ
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
ÃÂ
si noti che questo target porta alla creazione dell‘archivio utilizzando come nome quanto de-finito nella variabile ${archive.name}.
Si noti anche la presenza del sotto-tag zipfileset che consente di creare un set di risorse da inserire nell‘archivio: in questo caso si tratta dei vari deploy descpritor file (in formato XML), che verranno inseriti, come da specifica, nell‘archivio jar nella sotto dir META-INF.
Infine il seguente target permette di eseguire il deploy della applicazione in JBoss della applicazione (in questo caso il deploy si riduce ad una semplice operazione di copia nella cartella di deploy dell‘application server):
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
Esecuzione del client EJB
Una operazione banale ma spesso piuttosto macchinosa è quella che prepara la configurazio-ne dell‘ambiente di esecuzione del client per la connessione a componenti EJB remoti. In questo caso la difficoltà (o meglio la scomodità ) consiste nel comporre il classpath con tutte le librerie necessarie per risolvere le classi EJBÃÂ (i packages javax.ejb.*) e per la connessione al JNDI context.
Anche in questo caso Ant, grazie all‘utilizzo delle variabili definite nela target init, permette di risolvere brillantemente e con poco lavoro questo problema: di fatto prendendo come ba-se la directory di installazione di JBoss, il classpath viene composto con quanto trovato nella directoryÃÂ JBOSS_HOME/client:
ÃÂ
ÃÂ
ÃÂ
ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ ÃÂ
ÃÂ ÃÂ
ÃÂ
ÃÂ
Infine non dimenticare di pulire
E‘ buona cosa non dimenticare di definire il target che pulisce la directory di build, elimi-nando l‘archivio jar. Si potrebbe estendere con successo facendo anche eliminare il contenu-to della directory di compilazione:
ÃÂ
ÃÂ ÃÂ
ÃÂ
ÃÂ
Infine il target che non dovrebbe mancare mai: quello che fa tutto, ovviamente opportuna-mente configurato:
ÃÂ
ÃÂ
ÃÂ
Conclusione
Come si è visto con una saggia organizzazioneÃÂ delle directory di progetto parallelamente ad un accorta sezione di inizializzazione delle variabili di progetto,ÃÂ si può utilizzare Ant per e-seguire in maniera estremamente semplice le comuni operazioni di sviluppo JavaEE (ma non solo).
Sebbene sia sempre stato un grande fan dei più moderni e avanzati IDE Java, ritengo che questo tool, corredato di un buon file di build, rappresenti un indispensabile strumento di lavoro per ogni programmatore: Ant non deve certo sostituire prodotti come JDeveloper, Studio Creator, Eclipse, Netbeans o JBuilder, ma deve invece essere usato congiuntamente a tali strumenti avanzati sia per semplificare il lavoro sia per ridurre la dipendenza da tali pro-dotti.
In allegato (nel menu in alto a sinistra) il lettore troverà un archivio con una serie di directory a formare la struttura di base del progetto come presentata in questoÃÂ articolo. Si controlli il file build.