Sei sulla pagina 1di 52

www.infomedia.

it EDITORIALE

JAVA Journal MySQL


sotto l’ombrello di
BIMESTRALE - ANNO 2 - N.5

DIRETTORE RESPONSABILE
MARIALETIZIA MARI

EDITORIAL BOARD
STEFANO SANNA, MICHELE SCIABARRÀ,
F A B I O S T A R O , TO N Y M O B I L Y
Sun Microsystems
COLLABORATORI
STEFANO SANNA
MICHELE SCIABARRÀ
RICCARDO SOLIMENA
FA B I O S T A R O

Tra metà Gennaio e fine Febbraio, Sun Microsystems ha perfezionato l’acquisizione


di MySQL AB, il noto produttore del diffuso DBMS dual-license MySQL, con un
investimento di circa 1 miliardo di dollari.

Con questa acquisizione, MySQL AB è a tutti gli effetti una business unit di Sun
GRUPPO EDITORIALE INFOMEDIA SRL
V I A V A L D E R A P. 1 1 6 Microsystems, e potrà avvalersi del peso di Sun per far crescere ulteriormente il
5 6 0 3 8 PO N S A C C O ( P I ) I T A L I A prodotto, in termini di marketing e di servizi.
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2
INFORMAZIONI@GRUPPOINFOMEDIA.IT Sun, invece, oltre ad ampliare il portfolio dei propri prodotti, si posiziona giusto
W W W. I N F O M E D I A . I T
dietro la “M” dell’acronimo LAMP, una posizione decisamente centrale nel mondo
DIREZIONE del software open source.
N A T A L E FI N O E sul Nasdaq il valore del titolo Sun (il cui simbolo, guarda caso, è JAVA) giusto in
concomitanza dell’intera operazione ha avuto un rialzo.
CONTATTI
TE C H N I C A L B O O K Se da un punto di vista del licensing e di ciò che riguarda la programmazione con
(BOOK@GRUPPOINFOMEDIA.IT) MySQL non ci sono novità di sorta, ciò che verrà potenziato è il supporto tecnico, che
MARKETING & ADVERTISING Sun offre in modalità 24x7 per l’intero portfolio di prodotti MySQL.
SEGRETERIA: 0587736460
(MARKETING@GRUPPOINFOMEDIA.IT) In sintesi un robusto supporto commerciale per un prodotto software open source.
AMMINISTRAZIONE Indispensabile in ambienti con applicazioni mission-critical basate su MySQL.
(AMMINISTRAZIONE@GRUPPOINFOMEDIA.IT)

SEGRETERIA Oltre al supporto tecnico, l’acquisizione potrà far convergere più speditamente
(INFORMAZIONI@GRUPPOINFOMEDIA.IT) MySQL verso importanti tappe per applicazioni di fascia alta (dallo sviluppo di
nuovi engine, al supporto multicore spinto, all’interoperabilità, alla sincronizzazione
GRAFICA distribuita dei dati, e via dicendo).
(GRAFICA@GRUPPOINFOMEDIA.IT)

UFFICIO ABBONAMENTI Per quanto riguarda Java in particolare, ci auguriamo che la maggiore affinità
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2 tra Sun, MySQL AB e le relative community permetta di sviluppare sempre più
ABBONAMENTI@INFOMEDIA.IT strumenti evoluti e tecnologie per poter far interagire in modo ancor più efficiente e
W W W. I N F O M E D I A . I T ottimizzato le applicazioni Java con basi di dati basate (anche) su MySQL.
JAVA E TUTTI I MARCHI DERIVATI
Con questo passo Sun (che già supporta direttamente PostgresSQL) si propone
SONO MARCHI O MARCHI REGISTRATI
DI SUN MICROSYSTEMS, INC. NEGLI sempre più come player nel mondo data center, e MySQL (con 55.000 download al
U S A E I N A L T R I PA E S I . I L G R U P P O giorno) è un’importante pedina per consolidare ulteriormente questa posizione.
EDITORIALE INFOMEDIA È INDIPEN-
DENTE DA SUN MICROSYSTEMS, INC.
La redazione di Java Journal
JAVA JOURNAL È UNA RIVISTA DEL
GRUPPO EDITORIALE INFOMEDIA SRL
DIREZIONE E AMMINISTRAZIONE:
V I A V A L D E R A P. 1 1 6 - P O N S A C C O ( P I )
R E G I S T R A Z I O N E P R E S S O I L TR I B U N A L E
DI PISA N.19/06 DEL 5/9/2006

n.5 - novembre/febbraio 2008 3


“Architetture Enterprise
Metodologie di disegno e progettazione”
di Alessandro Sinibaldi
Anno 2008
350 pagine, formato 17x24 cm
ISBN 9788881500352

solo
49,00
Eu ro

Se siete tra quelle persone a cui è sempre piaciuto smontare le cose per vedere come sono
fa�e, allora questo libro è per voi. Fare gli archite�, di qualsiasi campo si tra�, vuol dire
cercare di coniugare due aspe�: uno tecnico e uno crea�vo.
Quello tecnico, perché l’archite�o pensa alla stru�ura delle cose, a come sono composte
da par� più piccole e a come queste interagiscono fra loro per far muovere un corpo com-
plesso. Tu�o questo mi è sempre sembrato affascinante. L’aspe�o crea�vo è dovuto al fa�o
che un archite�o, quando è mol� anni che fa il suo lavoro, sviluppa una specie di senso
este�co di quello che fa. Vedere le cose muoversi in armonia ed evolvere è sicuramente
una grossa soddisfazione. L’importante è capire i principi fondamentali del funzionamento,
poi, i pezzi possono essere assembla� in miliardi di modi diversi e dar vita ad un numero,
ancora maggiore, di situazioni e stru�ure diverse. Lo stesso accade ad un archite�o IT.

“Architetture Enterprise”
Ordinalo su

www.shopinfomedia.com
JAVA Journal numero 5

SOMMARIO Novembre/Febbraio 2008

Speciale JBoss Seam


Intervista a Fabio Staro su JBoss Seam
di Michele Sciabarrà 9
JBoss Seam: un framework per il Web 2.0
di Fabio Staro 11

Educational
DAO Generator
di Riccardo Solimena 23

Focus
JPA: JAVA Persistence API - Seconda parte
di Fabio Staro 38

Rubriche

Community Watch
Intervista al JAVA User Group Torino
di Stefano Sanna 46

n.5 novembre/febbraio 2008


IN VETRINA

Java Pocket Guide Core Servlets and JavaServer Value Pack: Absolute Java
Cookbook, Second Edition Pages, Volume 2 - Advanced (Int Ed) with Practical
di R. Liguori e P. Liguori Technologies 2nd Edition Debugging in Java
O’ Reilly di M. Hall, L. Brown e Y. Chaikin di W. Savitch e Ann Ford
191 pp - euro 20,95 Addison Wesley Addison Wesley
ISBN 9780596514198 736 pp - euro 44,95 Value pack - euro 83,95
ISBN 9780131482609 ISBN 9781405825054

Programming with Alice and Java Software Solutions. JavaFX Script: Dynamic
Java. International Edition Foundations of Program Java Scripting for Rich
di J. Lewis e P. DePasquale Design: International Internet/Client-side
Addison Wesley Edition (VI) Applications
360 pp - euro 75,95 di J. Lewis e W. Loftus di J. Weaver
ISBN 9780321549358 Addison Wesley Apress
832 pp - euro 74,95 216 pp - euro 38,90
ISBN 9780321549341 ISBN 9781590599457

Pro NetBeans IDE 6: Rich Client The Ruby Programming Language AJAX, RIA and Web
Platform Edition di D. Flanagan e Y. Matsumoto Development
di A. Myatt O’ Reilly di di P. Deitel e H. Deitel
Apress 444 pp - 39,00 euro Prentice Hall
491 pp - euro 55,00 ISBN 9780596516178 1040 pp - 52,95 euro
ISBN 9781590598955 ISBN 9780131587380

JAVA JOURNAL > n.5 novembre/febbraio 2008


6
JAVA JOURNAL 5

The Art & Science of Apache. Codice e comandi UML Distilled


Javascript essenziali di M. Fowler
di C. Adams di D. Lopez - J. Blanco Pearson Education Italia
Sitepoint Pearson Education Italia 162 pp - euro 25,00
258 pp - euro 43,50 240 pp - euro 12,00 ISBN 9788871922072
ISBN 9780980285840 ISBN 9788871924021

Scrivi a book@infomedia.it specificando nell’oggetto della e-mail:


IN VETRINA Java Journal n. 5
oppure inviaci il coupon al numero di fax 0587/732232
Potrai acquistare i libri qui riportati con uno SCONTO ECCEZIONALE
del 10% anche se acquisti solo un libro
oppure del 20% se acquisti 3 libri

Web: http://book.infomedia.it • E-mail: book@gruppoinfomedia.it


Tel: 0587-736460 • Fax: 0587-732232
NOME COGNOME CODICE CLIENTE
INDIRIZZO CAP CITTA’ PROV.
TELEFONO FAX E-MAIL
ANAGRAFICI

DITTA CODICE FISCALE


INTESTAZIONE FATTURA P.IVA
DATI

Garanzia di riservatezza - Il Gruppo Editoriale Infomedia garantisce la massima riservatezza dei dati da Lei forniti e la possibilità di richiederne gratuitamente la rettifica o la cancellazione scrivendo a: Responsabile Dati - Gruppo Editoriale
Infomedia Srl, V. Valdera P. 116, 56038 PONSACCO (PI). Le informazioni custodite nel nostro archivio verranno utilizzate al solo scopo di inviarle proposte commerciali, in conformità alla legge 196/03 sulla tutela dei dati personali.

TITOLO CODICE ISBN PREZZO QUANTITA’


ORDINE

Le spese di spedizione sono soggette a variazioni in base alle tariffe postali. Per i pagamenti con assegno, c/c postale e bonifico bancario consigliamo di chiedere conferma in redazione oppure consultare il sito Internet.
PER POSTA: + 3,00 Euro A MEZZO CORRIERE: + 7,00 Euro
ALLEGO ASSEGNO BANCARIO INTESTATO A “GRUPPO EDITORIALE INFOMEDIA SRL” - NON TRASFERIBILE
CONTRASSEGNO (solo per spedizione a mezzo Posta): + 8,00 Euro
ALLEGO VERSAMENTO SU C/C POSTALE N.14291561 INTESTATO A “GRUPPO EDITORIALE INFOMEDIA SRL - PONSACCO” - CODICE IBAN: IT84X0760114000000014291561 - Indicare la causale del versamento
E PAGAMENTO
SPEDIZIONE

ALLEGO FOTOCOPIA DEL BONIFICO BANCARIO SU C/C 000000014804 CAB 25200 ABI 01030 CIN “A” - MONTE DEI PASCHI DI SIENA, AGENZIA DI PERIGNANO - CODICE IBAN: IT84A0103025200000000014804
CARTA DI CREDITO VISA/MASTERCARD/CARTASI’ N. SCADENZA CODICE DI SICUREZZA “CV2”
TITOLARE _______________________________________________
NATO IL FIRMA _______________________________________________________

SI, mi voglio iscrivere gratuitamente alla newsletter Infomedia che mi tiene aggiornato sui prossimi argomenti delle mie riviste di programmazione e mi informa delle offerte, le nuove uscite e le prossime pubblicazioni. Posso
annullare la mia iscrizione in qualsiasi momento alla pagina: www.infomedia.it/newsletter.php. Questo è il mio indirizzo di posta elettronica: ______________________________________________
JAVA Journal JBOSS Seam speciale

Intervista a
Fabio Staro su
JBoss Seam

>> di Michele Sciabarrà (michele.sciabarra@javajournal.it)

Ciao Fabio, per prima cosa una breve presenta- ticolo di approfondimento su Seam?
zione. Ci parli un attimo di te?

JBoss Seam è un application framework per Java En-


Lavoro presso la Direzione Ricerca & Innovazione di terprise Edition versione 5 (JEE 5). Il framework for-
Engineering Ingegneria Informatica S.p.A. nisce un modello a componenti uniforme dove non vi
Nella direzione vi sono vari centri di eccellenza (in è una distinzione tra i componenti del presentation tier
particolare per le piattaforme JEE ed Oracle oltre ad ed i componenti della business logic.
un centro di competenza specifico sui temi dell’Ac-
cessibilità).
Presso la direzione sono responsabile tecnico per i Nella versione 5 della Enterprise Edition di Java il
progetti Java. Il progetto che seguo attualmente è per framework Java Server Faces (JSF) e la tecnologia
un cliente istituzionale dove stiamo usando tecnolo- EJB 3.0 costituiscono le feature principali e maggior-
gie all’avanguardia(JSF e Shale-Clay con il vincolo mente innovative. JSF è un framework per il presen-
dell’accessibilità…). tation tier basato su un modello di componenti e di
eventi attraverso i quali sono descritti gli elementi
della user interface e l’interazione con l’utente; vice-
So che ti occupi di JBoss Seam. Ci spieghi bre- versa la tecnologia EJB 3.0 consente la programma-
vemente cos’è questo framework, prima di la- zione di componenti server side dedicati alla business lo-
sciare i lettori di Java Journal alla lettura dell’ar- gic e alla persistenza dei dati. Le due tecnologie sono
eccellenti nei “relativi tier” e sono necessariamente
complementari in una complessa applicazione di li-
vello enterprise. Tuttavia, nella specifica JEE 5, non è
presente uno standard per integrare i due mondi.
JBOSS SEAM
è un application E quindi cosa succede in JBoss Seam?

framework per
Seam risolve questo limite unificando i modelli a
Java Enterprise Edition componente di JSF e degli EJB 3.0 eliminando di fat-
to il codice di integrazione, il cosiddetto “glue code”,
tra le tecnologie. Tanto per essere chiari, in Seam un
action listener JSF può essere, ed anzi lo è solitamente,

n.5 - novembre/febbraio 2008 9


speciale JBOSS Seam JAVA Journal

un EJB di tipo session … business di tipo “long running” dove lo stato è gestito e
reso persistente da un motore di BPM (business process
management). Una business process interaction può coin-
Ma non va contro alcune delle best practice? volgere più utenti e lo stato è condiviso tra questi in un
modo ben definito.

Si, quanto precedentemente affermato è sostanzialmente


in contrasto con il principio, presente nelle principali ar- In cosa si differenzia da SpringFramework?
chitetture J2EE, di “accoppiamento debole” tra i diversi
tier applicativi. Tuttavia gli EJB 3.0 hanno rivoluzionato la
natura dei componenti EJB. Se prima un componente EJB La differenza principale tra l’application framework JBoss
versione 2.x era un “corse-grained heavyweight object” Seam e Spring è che il primo è realizzato “specificatamen-
ora un EJB 3.0 è diventato un “fine-grained object”, non te” per la versione 5 della enterprise edition di Java dove
più complesso di un normale bean java con la presenza di Java Server Faces e gli EJB 3.0 costituiscono le tecnolo-
annotazioni. gie di riferimento (sebbene già con Seam versione 1.1 era
possibile installare applicazioni Seam che usano semplici
POJO su application server J2EE 1.4).
Come fa allora Seam a implementare questa “unifica-
zione”? Un componente Seam è un POJO, acronimo di “Plain Old
Java Objects”, e quindi può essere un semplice bean java o
un EJB 3.0. Tuttavia Seam è stato progettato avendo pre-
I concetti fondamentali in Seam sono le nozioni di contesto sente la nuova specifica per gli EJB offrendo di conseguen-
e di componente. za una completa integrazione tra la tecnologia EJB e JSF.
I componenti sono oggetti stateful, solitamente EJB 3.0
ma anche semplici POJO, presenti in un contesto. Seam Seam presenta una serie di “feature” innovative. A titolo
estende il “context model” definito nella specifica delle di esempio: in Seam oltre ai concetti di Inversion of Con-
Servlet Java ed aggiunge ai noti contesti della request, del- trol (IoC) e di dependency injection, concetti di cui Spring
la session e della application i contesti conversation e bu- è principale portavoce, introduce il concetto di Bijection.
siness process.
Le caratteristiche che contraddistinguono la Bijection ri-
spetto all’IoC sono la:

§ contestualità: la bijection consente di assemblare


Una conversazione componenti presenti nei differenti contesti;
in Seam è una unità di § bidirezionalità: i valori delle variabili di contesto
sono injected negli attributi di un componente e
lavoro dal punto di vista sono outjected dagli attributi del componente in-
dietro nel contesto consentendo al componente
dell’utente di manipolare il valore delle variabili di contesto
semplicemente impostando le proprie variabili di
istanza.
§ dinamicità: la bijection avviene ogni volta che un
componente è invocato.

Ha funzionalità AJAX?
Cos’è una conversation in Seam?
Sì. Seam fornisce un “built-in JavaScript remoting layer”
per invocare i componenti EJB. I client AJAX possono
Una “conversazione” in Seam è una unità di lavoro dal invocare componenti server side facilmente e senza la
punto di vista dell’utente costruita sulle diverse interazio- necessita di un action layer intermedio. Seam 1.1 integra
ni che l’utente ha con il sistema allo scopo di risolvere un soluzioni open source JSF-AJAX based come ICEfaces e
problema specifico come per esempio la prenotazione di un Ajax4JSF.
volo o la registrazione del profilo in una anagrafica. Per-
tanto una “conversazione” è costituita da varie richieste
HTTP e da varie transazioni sul database.

Note Biografiche
E invece il business process in Seam? Michele Sciabarrà ha scritto di Java e lo ha insegnato per dieci
anni. Quando non cerca di imparare le ultime API o disquisisce
della superiorità del modello Open Source, si diletta a program-
mare cellulari Symbian in C++ e amministrare sistemi Linux.
Il contesto di business process è definito nei processi di

10 n.5 - novembre/febbraio 2008


JAVA Journal JBOSS Seam speciale

JBoss Seam: un
framework per il
Web 2.0
JBoss Seam è un “deep integration” framework open source nato con l’obiettivo di integrare
le tecnologie Java EE e semplificare lo sviluppo. È un framework per il Web 2.0 che offre
soluzioni native per AJAX, per il remoting, per la gestione del workflow e per il business process
management.

>> di Fabio Staro (fstaro@javajournal.it)

N
ella Java Enterprise Edition ver- degli EJB. Per far sì che alla pressione di un pulsante
sione 5.0 sono presenti le tecnolo- di submit (presente in un form HTML) venga invoca-
gie Java Server Faces (JSF) ed En- to un metodo di business (presente in un componen-
terprise Java Beans (EJB) versione te EJB) è necessario dichiarare ed implementare un
3.0. JSF è il framework di riferimen- bean JSF; il quale ha un’unica funzione: fungere da
to per realizzare applicazioni web in ponte verso la tecnologia EJB. Quindi, per integrare
Java, quindi il presentation layer; viceversa, la tecnolo- i framework JSF ed EJB è necessario “passare” per
gia EJB è lo standard con il quale implementare la lo- i backing bean che costituiscono un artificial layer che
gica di business di una applicazione, quindi il business nulla ha a che fare con le reali esigenze del business
layer. Le due tecnologie sono eccellenti nei “relativi (cfr. [JPH]).
tier” e sono necessariamente complementari in una Inoltre, per ottimizzare le operazioni di “ricerca” e le
complessa applicazione di livello enterprise. Tuttavia, modalità di invocazione dei componenti EJB, le “tra-
nella specifica JEE 5, non è presente uno standard dizionali” applicazioni Java EE fanno uso di vari desi-
per integrare i due mondi. gn pattern come il service locator, il business delegate ed il
business facade. Si può argomentare (e tutto sommato
in questi anni varie best practice lo hanno evidenziato)
Integrazione tra JSF e EJB che la separazione netta tra il presetation layer ed il bu-
siness layer porta in dote un debole accoppiamento tra
Il modello a componenti presente in JSF non si in- la view ed il business; e questo è un beneficio quando la
tegra in modo naturale con il modello a componenti logica di business è acceduta da diversi front-end.
Nella realtà, tuttavia, ciò accade raramente. Di solito
le applicazioni web fanno un uso esclusivo dei com-
ponenti EJB (in genere ad interfaccia locale) e l’ac-
coppiamento tra la view ed il business è tale che una
JBoss Seam modifica su un layer si riflette sull’altro.

è stato ideato da
JBoss Seam
Gavin King, l’ideatore di
JBoss Seam, ideato da Gavin King, l’inventore di Hi-
Hibernate bernate ([3]), propone un approccio pratico, foriero
di benefici e di semplificazioni nello sviluppo. Non ci
obbliga a non usare i design pattern precedentemen-
te citati, tuttavia il framework, fornendo un modello

n.5 - novembre/febbraio 2008 11


speciale JBOSS Seam JAVA Journal

FIGURA 1 Installazione dell’application server JBoss con il profilo EJB 3.0

a componenti uniforme (dove non vi è una distinzione tra i ture in un framework ORM è il supporto ad una politica di
componenti del presentation ed i componenti della business caricamento del tipo lazy con la quale le entità in relazione
logic), rende superfluo il codice di integrazione (glue code) vengono caricate in memoria solo quando è strettamen-
tra le diverse tecnologie. Il modello a componenti proposto te necessario (cfr. [JJ3]). Tuttavia una politica di carica-
da JBoss Seam è talmente innovativo che presso la Java mento di tipo lazy non è semplice da realizzare in un fra-
Community è in itere un processo di standardizzazione mework tradizionale MVC (Model View Controller), e per
(JSR 299, cfr. [5]). superare tale limitazione sono nati vari design pattern, tra i
Ma JBoss Seam non è “solo” un framework di integrazio- quali il più noto è il pattern Open Session In View ([6]). Per
ne. È anche un framework per il Web 2.0. Per prima cosa i necessari approfondimenti rimandiamo alla letteratura
estende i contesti di sessione e di applicazione, tipici in sul tema; tuttavia è d’obbligo evidenziare che JBoss Seam
una applicazine web, introducendo i contesti di conversa- supporta il pattern Open Session In View come default. Per-
tion e di business process, più utili per la definizione di un tanto, in una applicazione Seam è bandita l’eccezione di
flusso applicativo: tipo LazyInitializationException e le prestazioni del motore
ORM sono decisamente migliorate poiché il persistence con-
§ conversation context descrive in modo naturale un text è di tipo esteso ed agisce come cache naturale dei dati,
caso d’uso che si realizza da parte di un utente at- riducendo il round trip verso il database (cfr. [JJ3], [JPH]).
traverso varie interazioni http; Come si può intuire da quanto finora detto, l’articolo pre-
§ business process context, consente di trattare i pro- suppone una conoscenza del mondo JEE ed in particolare
cessi di business di tipo “long running” dove i del framework JSF e della tecnologia EJB versione 3.0 (ri-
task di business sono realizzati anche da diversi
utenti nel tempo.

Secondariamente, il framework integra in modo naturale


soluzioni per il remoting e AJAX. Prima di tutto fornisce un
built-in JavaScript remoting layer con il quale i client AJAX JBoss Seam
possono invocare i componenti server side (quindi EJB)
direttamente e senza la necessità di un action layer inter-
è anche
medio; inoltre integra soluzioni open source JSF-AJAX ba- un framework per il
sed come Ajax4JSF.
Web 2.0
Infine, JBoss Seam è un framework progettato per i mo-
tori ORM (Object Relational Mapping) e quindi per inte-
grare la specifica JPA (cfr. [JJ3]). Una delle principali fea-

12 n.5 - novembre/febbraio 2008


JAVA Journal JBOSS Seam speciale

FIGURA 2 La semplice applicazione per il salvataggio in rubrica

mandiamo alla bibliografia e ai numeri 1 e 3 di JavaJour- @Entity(name=”utente”)


nal per gli opportuni approfondimenti). @Name(“utente”)
Per inciso, l’esempio riportato è stato verificato con l’ap- @Scope(SESSION)
plication server JBoss versione 4.0.5 (JEMS Installer 1.2.0 @Table(name=”UTENTE”)
[4], installato con l’opzione EJB 3.0, Figura 1) e con il da- public class Utente implements Serializable
tabase MySQL versione 5.0.27 [2]. La versione del fra- {
mework JBoss Seam usata è la 1.2.1 [7]. ...
private String nome;
private String cognome;
private String telefono;
Un primo esempio
private String indirizzo;
L’esempio che desideriamo realizzare è volutamente sem-
plice al fine di introdurre alcune delle “feature” del fra- @Id
mework eliminando le complessità applicative legate ad public String getCognome()
un particolare dominio di interesse. L’applicazione consen- {
te l’inserimento in tabella dei dati anagrafici di un utente return cognome;
e consiste di: }
...
§ una pagina jspx (editUtente.jspx) attraverso cui in- }
serire i dati anagrafici;
§ un Session Stateless EJB (Rubrica.java), compo- Osserviamo nel dettaglio il codice riportato. Le annotazio-
nente che espone il servizio di salvataggio dei ni @Entity, @Table e @Id sono annotazioni della specifi-
dati e che interagisce con la API JPA dell’Entity ca JPA e caratterizzano la classe Utente come entity bean. In
Manager; particolare:
§ un entity bean (Utente.java), che è il data model
dell’esempio (Figura 2).
§ L’annotazione @Entity informa il provider dei
Di seguito riportiamo uno stralcio del codice della classe servizi JPA che la classe è di fatto una entità per
Utente. la quale deve gestire la persistenza;

n.5 - novembre/febbraio 2008 13


speciale JBOSS Seam JAVA Journal

§ L’annotazione @Table specifica la tabella di map-


ping;
§ L’annotazione @Id identifica la chiave primaria
della entità (cfr. [JJ3]).

Le annotazioni @Name e @Scope sono, invece, del fra-


mework Seam. Analizziamole in dettaglio. L’annotazio-
ne @Name, presente nel package org.jboss.seam.annotations,
consente di identificare la classe Utente come componen-
te Seam il cui nome è “utente”. Pertanto la classe Uten-
te è contemporaneamente sia un entity bean (annotazio-
ne @Entity della specifica JPA) sia un componente Seam
(annotazione @Name). Un componente Seam è un POJO
(acronimo di Plain Old Java Object), il cui tipo può essere tra
quelli riportati nell’elenco che segue:

§ EJB 3.0 Session Stateless;


§ EJB 3.0 Session Stateful;
§ EJB 3.0 Entity Bean;
§ JavaBean;
§ EJB 3.0 Message Driven Bean.

Seam
FIGURA 3 I contesti in Seam
può anche
funzionare in assenza di Seam, deve essere univoco in tutta l’applicazione. Un com-
EJB 3.0 ponente Seam, e quindi nel nostro caso il componente di
nome “utente”, può essere direttamente referenziato dai
componenti JSF presenti nelle pagina jsp.
Per esempio, la seguente riga di codice, estratta dalla pagi-
na editUtente.jspx, collega il valore di un campo di tipo testo
al nome dell’utente:

<h:inputText id=”txt_nome” value=”#{utente.nome}”


Osservando l’elenco è possibile notare come Seam sia stato required=”true”/>
progettato e disegnato specificatamente per gli EJB 3.0 e
che tuttavia il framework può anche funzionare in assenza La cosa interessante è che “utente” è un componente
di EJB 3.0, definendo come componenti dei “semplici” Ja- Seam e non un “semplice” backing bean JSF; inoltre, os-
vaBean. Tuttavia l’uso di EJB 3.0 come componenti Seam serviamo che “utente” non è stato dichiarato (come invece
porta in dote tutti quei servizi propri della specifica degli è norma in una applicazione JSF) nel file di configurazione
Enterprise Java Beans (cfr [JJ2a] e [JJ2b]) e di un contai- faces-config.xml (cfr. [JJ1]). Riprendiamo l’analisi del codice
ner EJB, tra i quali i principali sono: della classe Utente.
L’annotazione @Scope, presente nel package org.jboss.seam.
§ Gestione da parte del container delle transazio- annotations, consente di specificare il contesto nel quale vive
ni; ed è definito un componente Seam. Il framework definisce
§ Gestione da parte del container della sicurezza; e gestisce i seguenti contesti:
§ Injection dell’Entity Manager attraverso l’anno-
tazione @PersistenceContext; § Stateless;
§ Definizione dei componenti EJB come WebSer- § Event (o request);
vice (attraverso l’annotazione @WebService, cfr. § Page;
[JJ2b]); § Conversation;
§ Supporto per i componenti asincroni (i message § Session;
driven bean). § Business process;
§ Application.

Torniamo ad analizzare la classe Utente. Il valore specificato I contesti, ad eccezione del contesto Stateless, sono in rela-
con l’annotazione @Name, ossia il nome del componente zione gerarchica tra loro (Figura 3).

14 n.5 - novembre/febbraio 2008


JAVA Journal JBOSS Seam speciale

package it.example.action; anagrafica). Pertanto, una conversazione è


costituita da varie richieste HTTP e da va-
import …; rie transazioni sul database. Il framework
Seam offre due tipi di conversazioni:
@Stateless
@Name(“rubrica”) § Temporary conversation;
public class Rubrica implements RubricaLocal § Long running conversation.
{
Una temporary conversation esiste per la du-
@In
rata di una request, incluse eventuali ope-
private Utente utente;
razione di redirect. Questa “feature” risol-
@PersistenceContext ve un limite presente nell’architettura JSF,
private EntityManager em; dove normalmente una operazione di redi-
rect non conserva le informazioni salvate
@Logger nel FacesContext (ad esempio le istanze della
private static Log log; classe FacesMessages).
Viceversa, una long running conversation esi-
public String salva() ste per la durata di una ben definita serie
{
di request http; i confini della conversazio-
List existing = em.createQuery(
ne sono definiti o mediante file di configu-
“select u.cognome
from utente u razione o mediante annotazioni. È impor-
where u.cognome= tante sottolineare che vi possono essere più
#{utente.cognome}”).getResultList(); conversazioni attive e concorrenti durante
una sessione HTTP; ma ogni conversazio-
if ( existing.size()==0 ) ne, con le sue variabili di contesto, è isola-
{ ta dalle altre.
em.persist(utente); Il contesto di business process è definito nei
FacesMessages.instance().add( processi di business di tipo “long running”
“Registrato utente:
dove lo stato è gestito e reso persistente da
#{utente.cognome}
un motore di BPM (Business Process Ma-
#{utente.nome} nella rubrica”);
nagement) come JBoss jBPM. Una business
log.info(“Registrato utente: process interaction può coinvolgere più utenti
#{utente.cognome} e lo stato è condiviso tra questi in un modo
#{utente.nome} nella rubrica”); ben definito. La definizione di un processo
return null; di business sì complesso è possibile attra-
} verso un process definition language.
else
{ Riprendiamo l’analisi del codice analizzan-
FacesMessages.instance().add(
do la classe Rubrica (cfr. Listato 1). Que-
“Utente #{utente.cognome}
sto componente è un Session Stateless EJB
già presente in rubrica.”);
return null; (annotazione @Stateless). Osservando il
} codice riportato nel Listato 1 possiamo
} osservare che sono presenti le annotazioni
} del framework Seam: @Name, @Logger e
@In. In particolare, il valore dell’annota-
zione @Name è “rubrica”. Come nel caso
del componente “utente” anche il com-
ponente Seam “rubrica” può essere diret-
LISTATO 1 Il codice del Session Stateless EJB: Rubrica.java tamente referenziato dai componenti JSF
presenti in una pagina jsp. Pertanto il me-
todo di business salva() è direttamente referenziato (sen-
Nell’elenco riportato possiamo notare come ai tre contesti za la mediazione di backing bean) come action dal command
tipici di una applicazione web (ossia i contesti di request, button JSF presente nella pagina editUtente.jspx:
session ed application), il framework aggiunga i contesti di
conversation e business process. <h:commandButton value=”Salva”
In particolare, il conversation context è un concetto centrale action=”#{rubrica.salva}”/>
nell’architettura Seam. Una conversazione è una unità di
lavoro dal punto di vista dell’utente, costruita sulle diver- Il metodo memorizza in tabella i valori di un utente. Ma
se interazioni che l’utente ha con il sistema allo scopo di chi “passa” l’utente da memorizzare all’EJB Rubrica? Os-
risolvere un problema specifico (ad esempio la prenotazio- servando il codice della classe Rubrica è intuibile come
ne di un volo o la registrazione di un profilo utente in una l’annotazione @In sia responsabile della valorizzazione

n.5 - novembre/febbraio 2008 15


speciale JBOSS Seam JAVA Journal

tion (in questo caso da parte


del container EJB), è valoriz-
zato l’Entity Manager JPA (cfr.
[JJ3]).

Validazione via Hibernate

Nelle applicazioni web la vali-


dazione dei dati di input deve
essere eseguita non solo nel
presentaion layer ma anche nel
business layer e tipicamente pri-
ma del salvataggio dei dati.
Generalmente un framework
web, ad esempio JSF, ed un
framework ORM, ad esempio
FIGURA 4 La pagina editUtente.jspx con i controlli di validazione JPA, hanno meccanismi dif-
ferenti e tutto sommato ridon-
dell’attributo utente: danti per la validazione dei dati. Seam consente di definire
le regole di validazione sui dati attraverso annotazioni in-
@In serite direttamente sugli entity bean JPA. Questi constrain
private Utente utente; per la validazione sono usati automaticamente nella vali-
dazione dei campi di input di un form HTML quando l’en-
Siamo in presenza di un processo di dependency injection tity bean è usato come backing bean JSF. In questo modo il
(cfr. [JJ2a]). L’infrastruttura di Seam legge il nome del- codice della pagina web (nel nostro caso editUtente.jspx) ri-
la variabile di istanza, “utente” nel nostro caso, ed inizia a sulta privo dei validatori del framework JSF (cfr. Listato 2).
cercare una variabile con lo stesso nome nei vari contesti Le annotazioni che definiscono le regole sui dati sono parte
(iniziando la ricerca dal contesto Event e proseguendo nei del framework Hibernate Validator, perfettamente integrato
contesti via via più ampi). Prima di invocare il metodo di in Seam. Di seguito riportiamo uno stralcio del codice della
business salva(), il framework valorizza l’attributo utente classe Utente con le annotazioni di validazione:
della classe Rubrica con il valore della variabile recuperato
dalla sessione. @Length(min=3, max=50,
message = “La lunghezza deve essere
Altro esempio di dependency injection è l’annotazione @Log- compresa tra {min} e {max} caratteri.”)
ger: public String getIndirizzo()
{
@Logger return indirizzo;
private static Log log; }

Attraverso questa annotazione l’infrastruttura Seam iniet-


ta e valorizza l’attributo “log” prima che sia invocato un L’annotazione @Length, presente nel package
qualsiasi metodo di business. Prima di concludere que- org.hibernate.validator, consente di definire un constrain sul-
sta introduzione all’injection presente in Seam è doveroso la lunghezza del campo. Alcune tra le annotazioni presenti
notare come in Seam esista anche il concetto di bijection nel framework Hibernate Validator sono @NotNull, @Ran-
esemplificato dall’annotazione @Out (simmetrica alla an- ge e @Pattern. Con quest’ultima è possibile usare un’espres-
notazione @In). In sintesi, il valore delle variabili di conte- sione regolare per definire la regola di validazione.
sto è injected dal contesto negli attributi di un componente
attraverso l’annotazione @In, ed è outjected dagli attributi Per integrare Hibernate Validator in una pagina jsp, Seam
del componente indietro nel contesto attraverso l’annota- offre i tag validateAll e decorate. Il tag validateAll consente di
zione @Out, consentendo di fatto al componente di ma- “identificare” i componenti JSF per i quali applicare le re-
nipolare il valore delle variabili di contesto semplicemente gole di validazione, mentre il tag decorator consente di ge-
impostando le proprie variabili di istanza. stire la visualizzazione dei messaggi di errore “wrappan-
Prima di concludere l’analisi del codice della classe Rubri- do” i facet JSF beforeInvalidField e afterInvalidField in presen-
ca osserviamo che è presente l’annotazione @Persistence- za di un errore. Di seguito è riportato uno stralcio del codi-
Context: ce della pagina editUtente.jspx:

@PersistenceContext …
private EntityManager em; <f:facet name=”beforeInvalidField”>
<h:outputText value=”X”
Attraverso questa annotazione, esempio di dependency injec- styleClass=”erroreInput” />

16 n.5 - novembre/febbraio 2008


JAVA Journal JBOSS Seam speciale

FIGURA 5 Il packaging dell’applicazione

</f:facet>
<f:facet name=”afterInvalidField”> § application.xml;
<s:message styleClass=”erroreInput” /> § jboss-app.xml
</f:facet>
<s:validateAll>
… Il codice del file application.xml, specifico di una applicazio-
<tr> ne enterprise Java, è riportato nel Listato 3; viceversa, il file
<td>Nome*</td> jboss-app.xml, come suggerisce il nome, è specifico dell’ap-
<td> plication server JBoss e specifica il class loader della appli-
<s:decorate> cazione (cfr. Listato 4).
<h:inputText value=”#{utente.nome}” Analizziamo i file di configurazione del modulo web, rubri-
required=”true”/> ca_web.war. All’interno della cartella WEB-INF sono pre-
</s:decorate> senti tre file XML di configurazione:
</td>
</tr> § web.xml;
… § faces-config.xml;
</s:validateAll> § components.xml.

Il primo, web.xml, è proprio di una applicazione web Java.
Osservando il codice precedente possiamo notare che, in In questo, relativamente a Seam, è definito un listener re-
presenza di un errore di validazione, prima del campo di sponsabile del bootstrapping del framework e della distru-
input è visualizzato il carattere “X”, dichiarato nel facet JSF zione dei contesti di sessione e di applicazione:
beforeInvalidField; e che dopo il campo di input è visualizza-
to il messaggio di errore vero e proprio, facet JSF afterInva- <listener>
lidField (Figura 4). <listener-class>
org.jboss.seam.servlet.SeamListener
</listener-class>
</listener>
Configurazione e packaging dell’applicazione

L’applicazione di esempio è una applicazione enterprise


costituita da un modulo web e da un modulo EJB (Figu- Il file faces-config.xml è proprio del framework JSF (cfr.
ra 5). I file di configurazione dell’archivio enterprise rubri- [JJ1]). In questo, relativamente a Seam, deve essere defi-
ca_EAR.ear sono presenti all’interno della directory META- nito un phase listener responsabile della interazione di Seam
INF e sono:

n.5 - novembre/febbraio 2008 17


speciale JBOSS Seam JAVA Journal

<?xml version=”1.0”?>

<jsp:root xmlns:jsp=”http://java.sun.com/JSP/Page”
xmlns:h=”http://java.sun.com/jsf/html”
xmlns:f=”http://java.sun.com/jsf/core”
xmlns:s=”http://jboss.com/products/seam/taglib”
xmlns=”http://www.w3.org/1999/xhtml”
version=”2.0”>
<jsp:output doctype-root-element=”html”
doctype-public=”-//W3C//DTD XHTML 1.0 Transitional//EN”
doctype-system=”http://www.w3c.org/TR/xhtml1/DTD/
xhtml1-transitional.dtd”/>
<jsp:directive.page contentType=”text/html”/>
<html>
<head>
<title>Inserisci un nuovo utente</title>
<link rel=”stylesheet” type=”text/css” href=”css/style.css” />
</head>
<body>
<f:view>
<h:form>
<f:facet name=”beforeInvalidField”>
<h:outputText value=”X” styleClass=”erroreInput” />
</f:facet>
<f:facet name=”afterInvalidField”>
<s:message styleClass=”erroreInput” />
</f:facet>
<h:messages globalOnly=”true” styleClass=”messaggio”/>
<table border=”0”>
<s:validateAll>
<tr>
<td>Nome*</td>
<td><s:decorate>
<h:inputText id=”txt_nome” value=”#{utente.nome}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Cognome*</td>
<td><s:decorate>
<h:inputText value=”#{utente.cognome}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Telefono*</td>
<td><s:decorate>
<h:inputText value=”#{utente.telefono}” required=”true”/>
</s:decorate>
</td>
</tr>
<tr>
<td>Indirizzo</td>
<td><s:decorate>
<h:inputText value=”#{utente.indirizzo}”/>
</s:decorate>
</td>
</tr>
</s:validateAll>
</table>
<h:commandButton value=”Salva” action=”#{rubrica.salva}”/>
</h:form>
</f:view>
</body>
</html>
</jsp:root>

LISTATO 2 Il codice della pagina Web editUtente.jspx

18 n.5 - novembre/febbraio 2008


JAVA Journal JBOSS Seam speciale

<?xml version=”1.0” encoding=”UTF-8”?> con il ciclo di vita di una richiesta JSF:


<application
xmlns=”http://java.sun.com/xml/ns/javaee” <lifecycle>
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” <phase-listener>
xsi:schemaLocation=”http://java.sun.com/xml/ns/javaee org.jboss.seam.jsf.SeamPhaseListener
http://java.sun.com/xml/ns/javaee/application_5.xsd” </phase-listener>
version=”5”>
</lifecycle>
<display-name>Rubrica Application</display-name>
<module>
<web>
<web-uri>rubrica_web.war</web-uri> Infine, il file components.xml (cfr. Listato 5) è specifi-
<context-root>/rubrica</context-root> co del framework Seam ed è usato per una configura-
</web> zione avanzata dei componenti, sia di quelli nativi sia
</module> di quelli definiti nell’applicazione. Nella configurazio-
<module>
ne di base abbiamo solo specificato il pattern jndi con il
<ejb>rubrica_ejb.jar</ejb>
</module> quale il framework recupera, in modo trasparente per
<module> lo sviluppatore, le reference degli EJB Session durante
<java>jboss-seam.jar</java> le operazioni di lookup:
</module>
<module> <core:init
<java>el-api.jar</java> jndi-pattern=
</module>
”rubrica_EAR/#{ejbName}local”/>
<module>
<java>el-ri.jar</java>
</module>
</application> Osserviamo che tale valore è specifico dell’application
server, non esistendo uno standard nella specifica de-
gli EJB versione 3.0 (cfr. [JJ2a]). Prima di conclude-
re questa panoramica sul modulo web osserviamo che
LISTATO 3 Il file application.xml nella directory WEB-INF/lib è presente il file jboss-
seam-ui.jar.

Analizziamo il modulo EJB, rubrica_ejb.jar. All’interno


della cartella META-INF sono presenti due file XML di
<jboss-app> configurazione:
<loader-repository>
seam.jboss.org:loader=rubrica_EAR § ejb-jar.xml;
</loader-repository> § persistence.xml.
</jboss-app>

Il primo specifica un interceptor (cfr. [JJ2a]) che regola


LISTATO 4 Il file jboss-app.xml l’interazione di Seam con gli EJB dell’applicazione:

<ejb-jar>

<interceptor-binding>
<ejb-name>*</ejb-name>
<?xml version=”1.0” encoding=”UTF-8”?> <interceptor-class>
<components
org.jboss.seam.ejb.SeamInterceptor
xmlns=”http://jboss.com/products/seam/components”
</interceptor-class>
xmlns:core=”http://jboss.com/products/seam/core”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance” </interceptor-binding>
xsi:schemaLocation=“http://jboss.com/products/seam/core …
http://jboss.com/products/seam/core-1.2.xsd </ejb-jar>
http://jboss.com/products/seam/components
http://jboss.com/products/seam/components-1.2.xsd”>
Il secondo, il file persistence.xml (cfr. [JJ3]), è necessa-
<core:init jndi-pattern=”rubrica_EAR/#{ejbName}/local”/>
<core:ejb installed=”false”/> rio per la configurazione di JPA, definendo in partico-
</components> lare Hibernate come provider:


<persistence>
LISTATO 5 Il file components.xml

n.5 - novembre/febbraio 2008 19


speciale JBOSS Seam JAVA Journal

Riferimenti e Bibliografia
<persistence-unit name=”userDatabase”>
<provider> [1]: http://www.jboss.com/.
org.hibernate.ejb.HibernatePersistence [2]: http://www.mysql.com/
</provider> [3]: http://www.hibernate.org/
<jta-data-source> [4]: JEMS Installer: http://labs.jboss.com/jemsinstaller/
java:/theDataSource [5]: Web Beans JSR 299 (http://www.jcp.org/en/jsr/detail?id=299).
</jta-data-source> [6]: Open Session In View Pattern: http://www.jroller.com/cardsharp/
<properties> entry/open_session_in_view_pattern
<property [7]: Download Jboss Seam: http://www.jboss.com/products/seam
name=»hibernate.hbm2ddl.auto» [JJ1] : “Speciale JSF”. Java Journal N. 1
value=»create-drop»/> [JJ2a] : “Introduzione agli EJB 3.0”. Java Journal N. 3.
</properties> [JJ2b] : “Orizzonti Enterprise” Java Journal N. 3.
</persistence> [JJ3] : “JPA (prima parte)”. Java Journal N. 4.
… [JSF]: De Mann, Kito, “JavaServer Faces In Action”, Manning Publica-
tions Co 2005.
Prima di concludere osserviamo che nell’archivio rubrica_ejb.jar è [MEJ]: Sriganesh R. P., Brose G., Silverman M. “Mastering Enterprise
presente il file seam.properties. La cosa curiosa è che il file è vuoto ed è JavaBeans 3.0”, Wiley Publishing, Inc.
tuttavia fondamentale! Infatti allo startup Seam cerca i suoi componenti [BAD]: Kodali Raghu R., Wetherbee J. e Zadrozny P., “Beginning EJB
(le classi annotate con @Name) in tutti gli archivi che contengono un 3 Application Development”, Apress.
file, anche vuoto, il cui nome è appunto seam.properties. [JPH]: Bauer C. e King G., “Java Persistence with Hibernate”, Manning
Publications Co.
Conclusioni Note Biografiche
In questo articolo abbiamo iniziato ad apprezzare i benefici introdotti Fabio Staro, dottore in Fisica è Responsabile Tecnico per i pro-
getti Java presso la Direzione Ricerca ed Innovazione di Engi-
con JBoss Seam. Abbiamo anche accennato al concetto di conversa- neering Ingegneria Informatica S.p.A.
zione utente (conversation context) e alla relativa gestione.

20 n.5 - novembre/febbraio 2008


“Algoritmi Genetici in .NET”
di Fabio Fabozzi
Anno 2008
100 pagine, formato 17x24 cm
ISBN 9788881500314

solo
15,00
Euro

Perchè scrivere un libro dedicato agli AG?


Anzitutto, per la necessità di sottolineare l’esigenza di un approccio diverso alle scienze delle computazioni
mentali.
Non si può ignorare il fatto che la nostra struttura biologica e l’interazione tra le persone e gli oggetti presenti
nell’universo che ci circonda abbiano delle connotazioni che sfuggono dal calcolo sublime o da promettenti
simulazioni meccanicistiche.
La natura è ciò che è: difficilmente prevedibile. Ma se ci si chiedesse, o se ci si ponesse in grado, di avvicinarsi
con una certa accuratezza alla natura e con una certa approssimazione, allora le applicazioni che si vogliono
imporre come “intelligenti” potrebbero presentare un certo grado di accuratezza o essere “verosimili”, rispetto
alla realtà che ci circonda.
Nonostante possa apparire come una sorta di utopia scientifica, in realtà si tratta di una questione di osser-
vazione tra ciò che è l’osservatore e ciò che è osservato. È la loro interdipendenza che crea una dinamicità
irripetibile.
Gli AG rappresentano un modo di fare scienza presuntuoso e anche corretto, per il numero di problemi che si
possono risolvere attraverso essi; perchè? La risposta è semplice: si tratta di una scienza che tiene in pregio
un concetto molto importante; si tratta cioè di conoscere “la storia” di un sistema che si sta studiando e la sua
evoluzione nel tempo ed in che modo accadrà tale possibile evoluzione.
Spero che l’utilizzo dei linguaggi VB.NET e C#, impiegati nella realizzazione degli esempi di questo libro, ne
faciliti la diffusione.

“Algoritmi Genetici in .NET”


Ordinalo su

www.shopinfomedia.com
JAVA Journal educational

DAO Generator
Realizzare un’applicazione Web resistente alle migrazioni tra DBMS

>> di Riccardo Solimena (rsolimena@javajournal.it)

N
on sempre, quando iniziamo a scri- DAO Generator
vere un progetto, sappiamo se use-
remo per sempre un determinato Quando si progettano applicazioni suddivise in di-
DBMS, oppure se nel corso del tem- versi tier (Presentation/Business/Data Access/Value
po cambierà. Object) una tra le operazioni più gravose consiste
A priori, di conseguenza, converreb- nella configurazione e nella creazione dei Data Ac-
be premunirsi da questi cambiamenti disegnando cess Object (DAO), che spesso sono il vero “core” del-
un’architettura robusta e con dei package di imple- l’applicazione. Ma per scrivere bene i DAO lo sforzo è
mentazione facilmente intercambiabili. notevole, soprattutto quando sia le tabelle sia i cam-
Infatti, a meno che non si stiano utilizzando prodotti pi sono in numero elevato. Infatti, i passi da esegui-
come Hybernate (che si interpone come middlewa- re sono:
re parlando nel dialetto SQL del DBMS che dobbia-
mo utilizzare), abbiamo bisogno per ogni DBMS di
un “matching” appropriato tra SQL e tipi di dati, dal § costruire oggetti Java che rispecchiano la
DBMS a JAVA. Ovviamente, senza le giuste accor- struttura delle tabelle e degli attributi del
tezze in fase di progettazione, il refactoring del Da- DB;
taLayer comporta problemi e costi di manutenzione § scrivere per ogni tabella e per ogni chiave
elevatissimi; inoltre, non rimane traccia della vecchia primaria del DB un Value Object (VO);
versione della nostra implementazione se non in ob- § scrivere un’interfaccia con i metodi (e le ec-
soleti backup. cezioni) relativi ad ogni singola tabella;

La soluzione

Lo scopo è realizzare dei data layer Java paralleli che


attraverso semplici switch ci esonerino da una inutile
e costosa attività di manutenzione.
Vedremo come attraverso semplici strumenti (uno fi-
sico e due concettuali) si possa riuscire in questo in-
Nelle applicazioni
tento.
Parleremo fondamentalmente di pattern e di best
multitier una delle
practice, passando così, come da titolo, dal DAO Ge-
nerator per creare la base del data layer, al Connec- operazioni più gravose
tion Factory per la gestione ottimale delle connes-
sioni, all’Abstract Factory per rendere trasparente il è la configurazione e la
richiamo delle implementazioni delle varie logiche
parallele di data layer, al cache manager per gestire creazione dei DAO
al meglio le risorse in gioco. Vediamo subito DAO Ge-
nerator, un potente strumento per i lavori cosiddetti
“di massa”.

n.5 - novembre/febbraio 2008 23


educational JAVA Journal

FIGURA 1 Schermata principale di DAO Generator

figurazione in caso di incompatibilità tra le impostazioni


§ implementare per ogni interfaccia una classe della JAVA_HOME è alquanto banale: infatti, basterà mo-
DAO relativa. dificare con un qualsiasi editor di testi il file BAT (al mo-
mento di stesura di questo articolo il software è giunto alla
versione 1.2).
Il lavoro è gravoso, ma i benefici sono notevoli, in quanto,
implementando il livello Data Acces, gli altri livelli riman-
gono immutati se un giorno la struttura del DB dovesse Lanciato il programma dal file run.bat, il programma mo-
mai cambiare (spero non vi accada mai, ma purtroppo … stra la schermata riportata in Figura 1. La semplice in-
accade spesso). terfaccia ha un menu essenziale e allo stesso tempo com-
Come dicevo, il lavoro è abbastanza impegnativo, poiché di pleto.
codice da scrivere ve ne è tanto e può accadere di dimenti-
carsi di gestire alcune eccezioni, oppure di utilizzare come Generiamo il layer DAO
parametro di input una connessione cercando di istanziar-
la all’interno del DAO stesso, con ovvie ripercussioni sul Dal menù File sarà sufficiente inserire il nome del nuo-
nostro progetto. vo progetto e la cartella in cui andrà a risiedere il file di
Per fortuna c’è chi, come akcess, ha realizza-
to un software del tutto open-source che non
solo rispetta i maggiori standard di stesura
dei DAO, ma effettua un reverse engineering
da molti DBMS esistenti in commercio, tra
cui MySql, Oracle, SQL Server, HSQLDB, Po-
stgres, ecc.
Stiamo parlando di DAO Generator, questo
mago della lampada di casa akcess, che data
la struttura di un DB fa al posto nostro tutto il
lavoro descritto prima, comprese tutte le query
di base, la gestione delle eccezioni e delle con-
nessioni del caso, per non parlare dell’overri-
ding del metodo toString per ogni VO.
La semplicità del prodotto lascia sbalorditi, so-
prattutto per la libertà di personalizzazione dei
nostri package.
Il prodotto non va installato, e l’eventuale con-
FIGURA 2 Creazione di un nuovo progetto

24 n.5 - novembre/febbraio 2008


JAVA Journal educational

salvataggio (Figura 2). Una volta creato il pro-


getto sarà necessario dire al programma qual è
il DBMS con cui dovrà dialogare e la posizione
della libreria collettore (Figura 3). Il passo suc-
cessivo è effettuare il login nel database; biso-
gnerà quindi specificare la URL, lo user id e la
password associate al DB ed effettuare la con-
nessione (Figura 4).
Se abbiamo fornito correttamente tutte le in-
formazioni richieste, apparirà nella console po-
sizionata in basso nella finestra di DAO Gene-
rator il messaggio di avvenuta connessione (Fi-
gura 5).
Dal menu a tendina (o dalle icone della sotto-
stante toolbar) sarà possibile selezionare l’op-
zione Generate DAO: così facendo si aprirà la fine-
stra di selezione delle tabelle (Figura 6). A que- FIGURA 3 Selezione del DBMS
sto punto, si selezionano le tabelle di cui si vuole
effettuare il “reverse engineering” e si passa al
passo successivo di mappatura tra tabelle e og-
getti (Figura 7).
Fatto ciò, sarà necessario specificare la cartella
in cui si vuole salvare il package, il percorso del
package e i nomi dei singoli sottopackage (Fi-
gura 8), tra cui DAO, VO e addirittura Exception,
Implementation e Factory! Fantastico no?

A partire da 4 tabelle
FIGURA 4 Specifica delle credenziali di accesso al database
con 19 attributi
DAO Generator ha
prodotto 39 file Java
FIGURA 5 Messaggio di avvenuta connessione

A partire da appena quattro tabelle, conte-


nenti in totale solamente 19 attributi, il bravo
DAO Generator ha scritto per noi 39 file Java
(che però dovremo compilare da noi … uno
sforzo accettabile no?) e sette cartelle. Il tut-
to servito su un piatto d’argento: basta vedere
la quantità (e la qualità) di codice scritto nei
file (soprattutto il codice SQL) per capire il la-
voro risparmiato interagendo con cinque sem-
plici finestre. Il sito web del progetto DAO Ge-
nerator è disponibile all’indirizzo https://dao-
generator.dev.java.net/

Ovviamente fornendo uno strato di Imple-


mentation, il codice generato è già sufficien-
te per avere un’applicazione che rispetta il
pattern DAO (Figura 9). Come si nota, gli
FIGURA 6 Selezione delle tabelle

n.5 - novembre/febbraio 2008 25


educational JAVA Journal

Connection Factory

Prima di passare a sfruttare il codice appena ge-


nerato dal tool DAO Generator, teniamo conto
che tutto il livello data layer necessita di una con-
nessione attiva di tipo Connection, perciò imple-
mentiamo un mini-tool per la gestione dinami-
ca della connessione verso i DBMS.
Poiché, e non mi stancherò mai di dirlo, le con-
nessioni vanno passate ai DAO e non vanno ge-
nerate all’interno di ognuno di essi (per ovvi mo-
tivi di scalabilità, sicurezza e manutenibilità),
abbiamo bisogno di una classe che dati alcuni
parametri (tra cui ad esempio il nome del DBMS
a cui connettersi), restituisca un’istanza di Con-
nection da passare a tutti i DAO e non solo.
FIGURA 7 Mapping tra tabelle e oggetti Java Partendo dal presupposto di fornire un tool di
connessione, dobbiamo prevedere N classi di
connessione per gli N DBMS che vogliamo con-
siderare, ognuno dei quali dovrà avere un meto-
do che restituisca una connection di tipo

java.sql.Connection

A questo punto, abbiamo bisogno di una classe


Manager, che amministri la connessione secon-
do necessità. Una siffatta classe potrebbe avere
un metodo del tipo riportato nel Listato 1; ma
questa soluzione, se pur comoda e rapida, non
rispecchia una robusta architettura e la manu-
tenibilità potrebbe essere compromessa col pas-
sare del tempo.
Di conseguenza, sarà meglio affidarsi ad un’in-
terfaccia per ogni tipo di connessione, assicu-
rando oltretutto una corretta gestione delle pos-
sibili eccezioni generate in fase di connessio-
FIGURA 8 Schermata di generazione dei DAO
ne; e ciò per tutte le classi di connessione ai vari
strati costruiti sono: DBMS.
L’interfaccia può essere anche molto semplice come la se-
guente:
§ il layer Abstract Factory, ossia il “core” dell’appli-
cazione, in quanto punto di accesso a tutte le al- public interface ConnectionInterface {
tre classi. public Connection connect() throws
§ il layer DAO Factory, ovvero le interfacce per le ConnectException, ClassNotFoundException,
classi DAO. SQLException;
§ il layer Implementation, che comprende l’imple- }
mentazione vera e propria dei metodi utilizzan-
do le Factory.
§ il layer Exception, fondamentale per la gestione Ovvero assicuriamo che il metodo implementato dalle
personalizzata degli errori. classi di connessione abbia sempre lo stesso nome, garan-
§ il layer Entity, ossia i value object che rispecchia- tendo la cattura delle stesse eccezioni per tutte le classi.
no la struttura del database in chiave Java. A questo punto, appoggiandoci ad una classe di costanti,
§ il layer Primary Key basterà realizzare delle classi di connessione di questo tipo,
come si vede nel Listato 2 per la connessione a MySQL o
Nel layer Primary Key c’è un po’ di difficoltà indotta nella nel Listato 3 per la connessione a Oracle.
gestione degli entity, ma avete idea di che comodità sia ge- Potremmo anche utilizzare un sistema di switch (come gli
stire le PK come oggetti? … No? L’avrete ben presto! If Else visti precedentemente) per smistare le varie connes-
Inoltre ad ogni classe è associato uno strato intero di sioni; ma c’è un’altra scelta: utilizzare la Reflection per
COUNT, utilissimo per le comunissime operazioni di con-
teggio dei dati presenti nelle singole tabelle.

26 n.5 - novembre/febbraio 2008


JAVA Journal educational

FIGURA 9 Diagramma delle classi generate da DAO Generator

n.5 - novembre/febbraio 2008 27


educational JAVA Journal

Ponendo che ProjectConstant.DBMS_PRE-


FIX sia
public Connection getConnection(String DBMSName)
throws ConnectException, ClassNotFoundException,
org.solimena.javacourse.connection
SQLException{
Connection connection = null;
if(“MySQL”.equals(DBMSName)){ che ProjectConstant.DBMS_SUFFIX sia “ Con-
connection = new MySQLConnection().connect(); nection” e che DBMSName sia “MySQL”, l’in-
} tera stringa genererà:
else if(“Oracle”.equals(DBMSName)){
connection = new OracleConnection().connect(); org.solimena.javacourse.connection.MySQLConn
} ection
return connection;
}
e di conseguenza la Reflection non farà altro
LISTATO 1 Il metodo GetConnection che trasformare

ConnectionInterface factory =
public class MySQLConnection implements (ConnectionInterface)c.cast(c.newInstan
ConnectionInterface ce());
{

public Connection connect() throws in


ConnectException, ClassNotFoundException,
SQLException ConnectionInterface factory =
{ new MySQLConnection();
Connection conn = null;

String username = oppure in


ProjectConstant.DBMS_MYSQL_USERNAME;
String password = ConnectionInterface factory =
ProjectConstant.DBMS_MYSQL_PASSWORD;
new OracleConnection();

Class.forName(
ProjectConstant.DBMS_MYSQL_DRIVER);
e così via per gli altri tipi di DBMS.
String url = ProjectConstant.DBMS_MYSQL_URL; Se ci sono stati dei problemi il metodo prov-
vederà a inviare l’eccezione, altrimenti pas-
conn = DriverManager.getConnection( serà semplicemente la connessione al meto-
url,username, password); do chiamante.
return conn;
} Partendo da questo presupposto, per poter
}
asserire di aver fornito un buon servizio di
connessione trasparente anche a livello di
LISTATO 2 La classe MySQLConnection
Business, servirebbe un metodo che in auto-
istanziare l’apposita classe di connessione. È una scelta matico restituisca la connessione di default
più dispendiosa, ma che non necessita di manutenzione. scelta dall’amministratore o dallo sviluppatore del siste-
Infatti, in questo modo il codice può diventare: ma, senza dover ogni volta conoscere e inserire le informa-
zioni necessarie. Un modo semplice ed elegante è ricorrere
public Connection getConnection(String DBMSName) ancora una volta a un file di costanti e prelevare la connes-
throws ConnectException,ClassNotFoundException, sione di default scelta dall’utente e sfruttarla all’interno
SQLException,InstantiationException, della logica di un metodo:
IllegalAccessException
{ public Connection getDefaultConnection() throws
Class c = Class.forName( ConnectException,
ProjectConstant.DBMS_PREFIX + ClassNotFoundException,
DBMSName + SQLException,
ProjectConstant.DBMS_SUFFIX); InstantiationException,
ConnectionInterface factory = IllegalAccessException
(ConnectionInterface)c.cast(c.newInstance()); {
Connection connection = factory.connect(); return getConnection(
return connection; ProjectConstant.DBMS_CONNECTION);
} }

28 n.5 - novembre/febbraio 2008


JAVA Journal educational

public class OracleConnection implements


ConnectionInterface dove ProjectConstant.DBMS_CONNECTION
{ è il tipo del DBMS che vogliamo usare per
default (MySQL, Oracle, ecc.).
public Connection connect() throws
ConnectException, ClassNotFoundException,
A questo punto per ottenere una connessio-
SQLException
{ ne, indipendentemente dal tipo di DBMS
Connection conn = null; adottato, sarà sufficiente una sola riga di
codice, peraltro autoesplicativa:
String username =
ProjectConstant.DBMS_ORACLE_USERNAME; Connection conn =
String password = new ConnectionFactory().
ProjectConstant.DBMS_ORACLE_PASSWORD; getDefaultConnection();

Class.forName( Pur essendo un po’ articolata internamente,


ProjectConstant.DBMS_ORACLE_DRIVER);
questa architettura offre una forte versatili-
String url = ProjectConstant.DBMS_ORACLE_URL; tà, affidabilità e leggibilità per l’utilizzatore;
infatti, utilizzando una semplice classe main
conn = DriverManager.getConnection( è possibile intuire gli innumerevoli benefici
url,username, password); di questo approccio (Listato 4).
return conn; Come si è già detto, se la connessione è an-
} data a buon fine siamo stati in grado di
istanziarla con una sola riga di codice! Inol-
} tre, disponiamo di un’efficiente sistema di
gestione degli errori per poter individuare
immediatamente il problema e risolverlo
LISTATO 3 La classe OracleConnection senza perderci in eccezioni generiche.
Un ultimo appunto, ma di importanza forse
public class Launch superiore, è ciò che ho racchiuso nella clau-
{ sola finally, in quanto nel 99% dei casi (an-
public static void main(String[] args) che in progetti di grosse dimensioni) non è
{ difficile che le connessioni vengano aperte e
Connection conn = null; mai chiuse. Con l’utilizzo di finally in questo
try modo, ci assicuriamo che in qualsiasi caso,
{
eccezione o no, la connessione verrà comun-
conn = new
ConnectionFactory().getDefaultConnection(); que chiusa, altrimenti la connessione stessa
System.out.println(“Connection estabilished”); rimane “appesa” incrementando l’utilizzo
di memoria nel server e una temporanea pa-
//inserire qui il proprio codice ralisi del DBMS e quindi dell’applicazione!
Bisogna chiudere sempre e comunque le con-
} catch (ConnectException e) { nessioni una volta aperte, e il metodo final-
e.printStackTrace(); ly, spesso trascurato, dà l’opportunità di non
} catch (ClassNotFoundException e) { sbagliare, perciò sfruttiamola.
e.printStackTrace(); Le costanti utilizzate nella classe ProjectCon-
} catch (SQLException e) {
stant sono riportate nel Listato 5.
e.printStackTrace();
} catch (InstantiationException e) { Ovviamente è consigliato largamente l’uti-
e.printStackTrace(); lizzo di file statici di proprietà in modo tale
} catch (IllegalAccessException e) { da non dover mettere mano al codice nel
e.printStackTrace(); caso di modifica delle impostazioni di base
} quali nome del DB e credenziali di accesso.
finally { In Figura 10 è riportato il diagramma delle
if(conn != null){ classi realizzate.
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace(); Abstract Factory
}
} Una volta fornito un package affidabile di
} connessioni torniamo indietro a ciò che
DAO Generator ha creato per noi.
} Osserviamo la classe DAOFactoryCreater. Pur-
} troppo, il metodo DAOFactoryCreater creato
da DAOGen è ottimo per creare una nuova
LISTATO 4 La classe Lunch serie di DAO, ma saranno DAO tutti dello

n.5 - novembre/febbraio 2008 29


educational JAVA Journal

public DAOFactory getFactory(){


return new DAOFactoryImpl();
}
}

Per ottenere i risultati desiderati bisogna mo-


dificare questo generatore di Factory come è
riportato nel Listato 6. Come si vede, sfrut-
tando lo stesso pattern adottato per la con-
nessione è molto semplice gestire le imple-
mentazioni dei singoli Factory. Ma è stato in-
dispensabile modificare la tipologia di classe
in Abstract.
DAO Generator ha creato dei DAOFactoryImpl
(Figura 11), ossia delle implementazioni del-
l’interfaccia DAOFactory, ma, come si intuisce,
è necessaria un’implementazione per ogni
DBMS (basterà quindi ricreare, selezionando
il dialetto opportuno in DAO Generator, un
nuovo insieme di classi ). Adesso che abbia-
mo creato questo strato di Abstract Factory
(in poche parole una Factory di Factory) le
implementazioni di DAOFactory che prima
FIGURA 10 Overview Connection Factory erano nella forma:

stesso DB. public class DAOFactoryImpl implements


Di conseguenza, per realizzare un’applicazione che effet- Serializable, DAOFactory
tui un rapido switch da un DBMS ad un altro, è necessario
modificarlo opportunamente per il supporto multi DB.
Il codice della classe creata da DAO Generator è il seguen- saranno ora cambiate in:
te:
public class DAOFactoryImplMySQL
package org.solimena.javacourse.factory; extends DAOFactoryCreater
public class DAOFactoryCreater
{

FIGURA 11 Overview Abstract Factory DAO

30 n.5 - novembre/febbraio 2008


JAVA Journal educational

da ricopiare nel nostro progetto saranno quelle sotto-


stanti il livello DAOFactoryCreater così come mostra la
struttura del progetto nella Figura 12.

CacheManager

La tecnica di Reflection utilizzata per il package di


connessione, se pur comoda, può rivelarsi molto di-
spendiosa. Infatti, il costo in termini di tempo per
istanziare una classe con questa tecnica è circa il
doppio rispetto all’istanziamento diretto. Inoltre, per
quanto riguarda la gestione dei DBMS, anche la sud-
divisione in un numero elevato di livelli, può appe-
santire il sistema. Sarebbe quindi opportuno adottare
un sistema cache manager per memorizzare le infor-
mazioni una volta che le classi hanno caricato tut-
ti i dati.
Vi sono diverse tecniche per gestire la cache, e spesso
molti programmatori non si accorgono che bastereb-
be veramente poco per gestire al meglio le operazio-
ni più comuni, e soprattutto gli oggetti in memoria,
senza perdersi nell’utilizzo di oggetti di sessione (che
successivamente sarà difficile gestire).
Per l’esempio in questione è stato sufficiente realizza-
re una semplicissima classe che funge da cache ma-
nager per risolvere i problemi appena evidenziati di
FIGURA 12 Package Explorer prestazione e gestione degli oggetti.
Poiché gestisce oggetti contenuti nella HttpServletRe-
quest, il nostro CacheManager estenderà, a seconda del-
la tecnologia che decidiamo di adottare (Servlet, JSF,
Struts, ecc.), l’apposita classe (HttpServlet, Action, Di-
spatchAction) in modo da gestire l’apposito contenitore
di Session (Listato 7).

Il concetto è di inserire i dati di interesse, una volta


caricati, all’interno di un HashMap e a sua volta me-
morizzare l’intera HashMap all’interno di un oggetto
Session in modo tale che le informazioni siano disponi-
FIGURA 13 Tabella Elenco Libri
bili ad ogni classe che le richieda e cha abbia la possi-
bilità di passare la Request.
La semplice funzione getSetCache prende in input solo
la richiesta ed effettua un controllo sulla sessione. Se
la cache HashMap non è presente in Session, verranno
dapprima effettuati i dispendiosi calcoli e successiva-
mente inserite le informazioni all’interno della cache
HashMap, la quale verrà subito inserita nella Session.
Se invece la cache è già presente in Session, il Cache-
Manager semplicemente la restituirà.
FIGURA 14 Tabella Dettaglio Il recupero degli oggetti è abbastanza semplice, infatti
all’interno delle nostre classi di Presentation (Servlet,
e così via per tutti gli altri DBMS di cui abbiamo necessi- ManagedBean di JSF, Action di Struts) una volta este-
tà. sa alla classe CacheManager, saranno sufficienti le tre
seguenti righe di codice per recuperare i due oggetti
Dal momento che l’interfaccia di DAOFactory è stata adot- caricati dinamicamente in sessione:
tata in DAOFactoryCreater (che a sua volta è stato modifi-
cato aggiungendo altri metodi) è ovvia e indispensabile la HashMap cache = getSetCache(request);
modifica di implements della vecchia classe in extends nella Connection connection =
classe modificata. (Connection)cache.get(“CONNECTI
Così come accennato prima, per ogni implementazione ON”);
dobbiamo ricreare un export con DAO Generator e le classi

n.5 - novembre/febbraio 2008 31


educational JAVA Journal

DAOFactory daoFactory =
(DAOFactory)cache.get public static final String DBMS_CONNECTION =
(“DAO_FACTORY”); getPropValue(“dbms.connection”);

//MYSQL
public static final String
DBMS_CONNECTION = “MySQL”;
Interazione tra i componenti public static final String
DBMS_MYSQL_USERNAME = “root”;
A questo punto possiamo radu- public static final String
DBMS_MYSQL_PASSWORD = “password”;
public static final String
DBMS_MYSQL_DRIVER =
nare tutti i concetti esposti fino-
“com.mysql.jdbc.Driver”;
ra e vedere come sarà semplice public static final String DBMS_MYSQL_URL =
realizzare delle classi di Presen- “jdbc:mysql://localhost:3306/javacourse”;
tation ben strutturate.
Nella semplice classe di Action //ORACLE
Struts riportata nel Listato 8 ci // analogo ...
sono tutti i concetti evidenziati public static final String DBMS_ORACLE_USERNAME = “…”;
finora. public static final String DBMS_ORACLE_PASSWORD = “…”;
A partire dal recupero dei dati public static final String DBMS_ORACLE_DRIVER = “…”;
nel CacheManager, vediamo public static final String DBMS_ORACLE_URL = “…”;
public static final String DBMS_PREFIX = “…”;
come il daoFactory ci permetta,
public static final String DBMS_SUFFIX = “…”;
con dei semplici comandi, di ot-
tenere delle funzionalità di alto
livello; infatti, daoFactory.createBo
okDAO() crea il BookDAO relati- LISTATO 5 Costanti utilizzate nella classe ProjectConstant
vo al DBMS selezionato prece-
dentemente dall’utente (attra- public abstract class DAOFactoryCreater implements DAOFactory
verso l’utilizzo del file di costan- {
ti) in modo del tutto trasparente
per l’utente. Come si può notare, private static DAOFactoryCreaterNew
non appare nessun riferimento getDAOFactory(String dbType)
al DBMS. {
if(dbType.equals(ProjectConstant.DBMS_CONNECTION_MYSQL)){
Il metodo invocato di BookDAO,
return new DAOFactoryImplMySQL();
findAll(connection), necessita so- }
lamente della connessione, assi- else if(dbType.equals(
curando, così come detto prece- ProjectConstant.DBMS_CONNECTION_ORACLE)){
dentemente, una corretta gestio- return new DAOFactoryImplOracle();
ne della connessione, in quanto }
l’istanza, la gestione delle ecce- else{
zioni e la chiusura della connes- return new DAOFactoryImplMySQL();
sione vanno gestiti ad alto livello }
e non nei singoli metodi. }
Con una sola riga di codice ab-
public static DAOFactoryCreater getFactory(){
biamo ottenuto l’elenco dei Libri return getDAOFactory(ProjectConstant.DBMS_CONNECTION);
presenti in archivio. }
DAOGen gestisce gli oggetti }
multipli come Array di oggetti;
dato che per il lato presentation
gli array sono a volte ingestibi- LISTATO 6 La classe DAOFactory
li con alcuni framework, è stato
adottato un metodo di utilità che converta gli Array di og- Avendo implementato le factory in modo da rimandare
getti in ArrayList di oggetti le eccezioni al livello superiore, la gestione delle eccezio-
ni viene effettuata solamente in tutte le classi di presen-
JavaUtils.getArraylistFromArray(books); tation; assicurando così una gestione centralizzata note-
volmente semplificata. Infatti, in questo modo è possibile
personalizzare il messaggio di errore in base al tipo di ec-
in modo da passare infine il risultato nella request con il cezione scatenata e rimandare l’errore stesso al client dal-
comando: l’opportuna pagina di errore.
Quando si progettano applicativi basati sull’utilizzo di dati
request.setAttribute(“results”, results); provenienti da database, uno tra i concetti più importanti
è la chiusura della connessione dopo il suo utilizzo, come
abbiamo già detto.

A questo punto non resta che evidenziare i dati caricati

32 n.5 - novembre/febbraio 2008


JAVA Journal educational

public class CacheManager extends DispatchAction {

private HashMap cache = new HashMap();


private HttpSession session;
private DAOFactory daoFactory;
private Connection connection;
private String result = “”;

public HashMap updateCache(String name, Object value){

if(!cache.containsValue(name)){

cache.put(name, value);
session.setAttribute(“SESSION”, cache);

return cache;
}

public HashMap getSetCache(HttpServletRequest request) throws


ConnectException,
ClassNotFoundException,
SQLException,InstantiationException,
IllegalAccessException
{

session = request.getSession();

if(session.getAttribute(“SESSION”) == null ||
session.getAttribute(“SESSION”).equals(“”))
{

//insert Connection
connection = new Connection Factory().getDefaultConnection();
cache.put(“CONNECTION”, connection);

//insert DAOFactory
daoFactory = DAOFactoryCreaterNew.getFactory();
cache.put(“DAO_FACTORY”, daoFactory);

session.setAttribute(“SESSION”, cache);
}

return cache;
}
}

LISTATO 7 La classe CacheManager

n.5 - novembre/febbraio 2008 33


educational JAVA Journal

public class BooksAction extends CacheManager {


private Connection connection;
private DAOFactory daoFactory;
private String result;

public ActionForward findAll(ActionMapping mapping, ActionForm form,


HttpServletRequest request, HttpServletResponse response)
{

try {

HashMap cache = getSetCache(request);


connection = (Connection)cache.get(“CONNECTION”);
daoFactory = (DAOFactory)cache.get(“DAO_FACTORY”);
Book[] books = daoFactory.createBookDAO().findAll(connection);
ArrayList results = JavaUtils.getArraylistFromArray(books);
request.setAttribute(“results”, results);

} catch (ConnectException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (ClassNotFoundException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (SQLException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (InstantiationException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
} catch (IllegalAccessException e) {
request.setAttribute(“error”, e);
e.printStackTrace();
}

finally {

try {

if(connection != null) connection.close();


result = “success”;

} catch (final SQLException e) {

result = “failure”;
request.setAttribute(“error”, e);
e.printStackTrace();

finally{
return mapping.findForward(result);
}
}
}
}

LISTATO 8 La classe BooksAction

34 n.5 - novembre/febbraio 2008


JAVA Journal educational

<%@ taglib uri=”/tags/struts-bean” prefix=”bean”%>


<%@ taglib uri=”/tags/struts-logic” prefix=”logic”%>

<html>
<body>
<logic:present name=”results”>
<logic:notEmpty name=”results”>
<table border=”1”>
<tr>
<td align=”center”>ID</td>
<td align=”center”>NAME</td>
<td align=”center”>PRICE (�)</td>
</tr>
<logic:iterate id=”book” name=”matrix”>
<tr>
<td>
<a href=”books.do?action=findById&id=<bean:write name=”book” property=”id” />”>
<bean:write name=”book” property=”id” /></a>
</td>
<td><bean:write name=”book” property=”name” /></td>
<td><bean:write name=”book” property=”price” /></td>
</tr>
</logic:iterate>
</table>
</logic:notEmpty>
<logic:empty name=”results”>
La ricerca non ha prodotto risultati
</logic:empty>
</logic:present>
<logic:notPresent name=”results”>
Nessun oggetto presente.
</logic:notPresent>
</body>
</html>

LISTATO 9 La pagina di visualizzazione dell’elenco degli Item



try {
if(request.getParameter(“id”) != null && !request.getParameter(“id”).equals(“”))
{
int id = Integer.parseInt(request.getParameter(“id”));
HashMap cache = getSetCache(request);
connection = (Connection)cache.get(“CONNECTION”);
daoFactory = (DAOFactory)cache.get(“DAO_FACTORY”);
Book[] books = daoFactory.createBookDAO().findById(id, connection);
ArrayList results = JavaUtils.getArraylistFromArray(books);
request.setAttribute(“results”, results);
}
else{
result = “failure”;
request.setAttribute(“error”, “No ID set!”);
}
} catch …

LISTATO 10 La pagina di visualizzazione dell’elenco degli articoli

n.5 - novembre/febbraio 2008 35


educational JAVA Journal

<%@ taglib uri=”/tags/struts-bean” prefix=”bean”%>


<%@ taglib uri=”/tags/struts-logic” prefix=”logic”%>
<html>
<body>
<logic:present name=”results”>
<logic:notEmpty name=”results”>
<table border=”1”>
<tr>
<td align=”center”>ID</td>
<td align=”center”>NAME</td>
<td align=”center”>DESCRIPTION</td>
<td align=”center”>PRICE</td>
<td align=”center”>QUANTITY</td>
</tr>
<tr>
<td><bean:write name=”book” property=”id” /></td>
<td><bean:write name=”book” property=”name” /></td>
<td><bean:write name=”book” property=”description” /></td>
<td><bean:write name=”book” property=”price” /></td>
<td><bean:write name=”book” property=”quantity” /></td>
</tr>
</table>
</logic:notEmpty>
<logic:empty name=”results”>
La ricerca non ha prodotto risultati
</logic:empty>
</logic:present>
<logic:notPresent name=”results”>
Nessun oggetto presente.
</logic:notPresent>
</body>
</html>

LISTATO 11 Markup della pagina di dettaglio articolo

dalle nostre action. Per la Action in questione, adottando DAOGen, nonostante generi Array di oggetti e non Collec-
le Tag Libraries di Struts, la pagina di visualizzazione per tions (operando così in vecchio stile), si può considerare a
l’elenco degli Items (Listato 9) produrrà un aspetto simile tutti gli effetti uno strumento indispensabile di generazio-
a quanto è mostrato nella Figura 13. ne DAO (per chi ragiona secondo questo pattern) anche
perché ci può aiutare facilmente, durante le fasi di proget-
E anche il corpo del metodo Action “findById” sarà analo- to, nelle modifiche strutturali al DB, senza impattare sulle
go (Listato 10), così come la pagina di dettaglio (Listato funzionalità di alto livello, grazie all’utilizzo delle opportu-
11 e Figura 14). ne Factory di creazione dei DAO.
Gli argomenti trattati in questo articolo sono tanti e di si-
Conclusioni curo hanno bisogno di essere assimilati con la pratica: il
punto fondamentale è notare come Java, al solito, fornisca
Nonostante la complessità di strutturazione delle factory gli strumenti per realizzare sistemi complessi in termini di
necessarie per ottenere dei metodi di alto livello, l’archi- funzionalità, ma di semplice utilizzo per lo sviluppatore fi-
tettura così creata fornisce in fase di sviluppo innumere- nale. Il tutto facendo colloquiare più sistemi di piccole di-
voli benefici: buona visibilità del codice, manutenibilità, mensioni ma con funzionalità e scopi ben definiti.
estendibilità e una completa gestione delle eccezioni; ga- Le nozioni fornite, se pur basilari nella loro implementa-
rantendo così una distinta robustezza dell’applicazione. zione, sono una buona base per realizzare applicazioni web
Attraverso questi concetti, se sfruttati bene, non è diffi- su cui potranno intervenire più sviluppatori, ma avendo ri-
cile ottenere dei package riusabili da adottare nei nostri spettato gli standard. Buon lavoro a tutti.
progetti: dal package delle connessioni, al DAOFactory, a
quello di CacheManager o alla JavaUtil che trasforma gli Riferimenti
Array in ArrayList.
In questo modo al programmatore finale sarà fornito un DAO Generator: https://dao-generator.dev.java.net/
framework a tutti gli effetti, attraverso il quale, con po-
Note Biografiche
che righe, potrà gestire rapidamente e con estrema puli-
zia l’intero progetto, evitando di incappare negli errori più Riccardo Solimena si occupa di sviluppo Java. Gestisce il sito
www.riccardosolimena.com.
comuni.

36 n.5 - novembre/febbraio 2008


focus JAVA Journal

JPA: Java
Persistence API
seconda parte
La specifica JPA fornisce uno standard per la persistenza dei dati in Java, semplificando
radicalmente la precedente tecnologia degli EJB di tipo Entity Bean. Tuttavia JPA non è
una reingegnerizzazione della precedente tecnologia ma è di fatto una nuova architettura

>> di Fabio Staro (fstaro@javajournal.it)

N
el precedente articolo su JPA (acro-
nimo di Java Persistence Api) [1] ab- Tra le classi Prodotto e Autore è presente una relazione
biamo introdotto le caratteristiche molti a molti bidirezionale. E tra le classi Autore ed In-
base della specifica ed abbiamo ap- dirizzo è presente una relazione uno a uno unidirezio-
profondito la gestione delle relazioni nale. La specifica JPA, per supportare in un database
tra le entità. Nell’articolo risaltava in relazionale il concetto di ereditarietà, offre varie stra-
modo prepotente la radicale semplificazione presente tegie di mapping. Queste sono specificate nella enu-
con JPA rispetto alla precedente specifica per la per- merazione javax.persistence.InheritanceType:
sistenza dei dati in Java: gli Entity Bean versione 2.x.
In questo articolo, conclusivo sull’argomento, appro- • SINGLE_TABLE;
fondiamo ulteriormente la specifica soffermandoci • JOINED;
sulle strategie di mapping per la gestione della ere- • TABLE_PER_CLASS;
ditarietà, un design pattern frequente nel paradigma di
sviluppo object-oriented e non presente nel mondo In questo articolo analizzeremo le prime due strate-
relazionale dei database. Gli esempi riportati realiz- gie per il mapping delle entità tralasciando la strate-
zano un processo di sviluppo top-down: ossia, par- gia TABLE_PER_CLASS in quanto il suo supporto da
tendo dal modello delle classi deriveremo il disegno parte dei provider JPA non è obbligatorio nella attua-
delle tabelle. le versione della specifica.
Gli esempi sono stati verificati con l’application ser-
ver JBoss versione 5.0 [2], con il database MySQL
versione 5.0.27 [3] e con il provider JPA Hibernate La strategia SINGLE_TABLE
[4].
Iniziamo con l’approfondire la strategia di mapping
SINGLE_TABLE. Questa è la strategia di default, dove
Strategie per l’ereditarietà una sola tabella è usata per rappresentare l’intera ge-
rarchia delle classi. Una colonna della tabella, assu-
Gli esempi che desideriamo realizzare sono voluta- mendo valori differenti in base al tipo Java rappre-
mente semplificati, al fine di approfondire l’API e sentato dal record, è usata come discriminante per
l’architettura JPA eliminando le complessità applica- distinguere tra le sottoclassi della gerarchia.
tive legate ad un particolare dominio di interesse. Os- Di seguito riportiamo uno stralcio del codice della
servando il diagramma delle classi riportato in Figu- classe Prodotto:
ra 1 possiamo notare la semplice gerarchia presente
tra le classi: Prodotto, Libro, Video, DVD e VHS. In par-
ticolare, la classe astratta Prodotto è la root class della @Entity(name=”Prodotto_Single”)
gerarchia e le classi Libro e Video la estendono diretta- @Table(name=”PRODOTTO_SINGLE”)
mente. La classe Video è a sua volta astratta ed è este- @Inheritance(strategy=InheritanceType.SINGLE
sa dalle classi concrete DVD e VHS. _TABLE)

38 n.5 - novembre/febbraio 2008


JAVA Journal focus

FIGURA 1 Il diagramma delle classi

@DiscriminatorColumn(name=”DISC”, @DiscriminatorValue(“LIBRO”)
discriminatorType=DiscriminatorType.STRING) public class Libro extends Prodotto
public abstract class Prodotto {
{ ...
... private int numeroPagine;
@Id private boolean edizioneEconomica;
@GeneratedValue(strategy=GenerationType.AUTO) ...
private int id; }
private String titolo;
private Date annoProduzione;
@ManyToMany(cascade=CascadeType.ALL, Ecco uno stralcio del codice della classe Video,
fetch=FetchType.LAZY,
targetEntity=Autore.class) @Entity(name=”Video_Single”)
private Set<Autore> autori = null; public abstract class Video extends Prodotto
... {
} ...
private boolean colore;
...
Osservando il codice della classe Prodotto è possibile no- }
tare l’uso delle annotazioni @Inheritance e @Discrimina-
torColumn. Attraverso l’annotazione @Inheritance è possi- e della classe VHS,
bile specificare la strategia di mapping, nell’esempio SIN-
GLE_TABLE. L’annotazione @DiscriminatorColumn consen- @Entity(name=”VHS_Single”)
te di specificare il nome, nell’esempio “DISC”, e il tipo del- @DiscriminatorValue(“VHS”)
la colonna che funge da discriminante nel distinguere le public class VHS extends Video
sottoclassi della catena gerarchica. Di seguito riportiamo i {
frammenti di codice significativi per le altre classi della ge- ...
rarchia. Iniziamo con uno stralcio del codice sorgente del- private String tipoNastro = null;
la classe Libro: ...
}
@Entity(name=”Libro_Single”)

n.5 - novembre/febbraio 2008 39


focus JAVA Journal

<persistence>
<persistence-unit name=”GestioneBiblioteca”>
<jta-data-source>java:/theDataSource</jta-data-source>
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>it.articolo.jpa2.Prodotto</class>
<class>it.articolo.jpa2.Libro</class>
<class>it.articolo.jpa2.Video</class>
<class>it.articolo.jpa2.VHS</class>
<class>it.articolo.jpa2.DVD</class>
<class>it.articolo.jpa2.Autore</class>
<class>it.articolo.jpa2.Indirizzo</class>
<exclude-unlisted-classes/>
<properties>
<property name=”hibernate.show_sql” value=”true”/>
<property name=”hibernate.format_sql” value=”true”/>
<property name=”hibernate.hbm2ddl.auto” value=”create”/>
</properties>
</persistence-unit>
</persistence>

LISTATO 1 Il file persistence.xml

Osservando la Figura 2 possiamo notare come la strategia


e, per concludere, della classe DVD: SINGLE_TABLE abbia effettivamente portato alla genera-
zione di una singola tabella, nell’esempio la tabella PRO-
@Entity(name=”DVD_Single”) DOTTO_SINGLE, le cui colonne sono tutti gli attributi del-
@DiscriminatorValue(“DVD”) le classi costituenti la gerarchia, più la colonna discrimi-
public class DVD extends Video { nante dichiarata attraverso l’annotazione @Discrimina-
... torColumn, nell’esempio la colonna “DISC”. Osserviamo
private boolean contenutiSpeciali; nel dettaglio la struttura della tabella PRODOTTO_SIN-
... GLE. Di seguito riportiamo il comando DDL (Data Defina-
} tion Language) della tabella:

Osservando il codice sopra riportato è possibile notare CREATE TABLE PRODOTTO_SINGLE (


come, al variare delle classi, varia il valore della colonna DISC varchar(31) NOT NULL,
“discriminante” (nell’esempio la colonna “DISC”). Il va- id int(11) NOT NULL auto_increment,
titolo varchar(255),
lore che assume in base al tipo della classe è specificato at-
annoProduzione datetime,
traverso l’annotazione @DiscriminatorValue. In particolare, numeroPagine int(11),
la colonna “DISC” assume il valore “LIBRO” in presenza di edizioneEconomica bit(1),
un record che rappresenta un oggetto della classe Libro e, colore bit(1),
viceversa, assume il valore “VHS” in presenza di un video tipoNastro varchar(255),
del tipo VHS ed il valore “DVD” in presenza di un record contenutiSpeciali bit(1),
che rappresenta un oggetto DVD. PRIMARY KEY (id)
)
Dopo aver definito il modello ad oggetti e dopo aver dichia-
rato la strategia di mapping per l’ereditarietà, deriviamo
la struttura delle tabelle del databa-
se (processo di sviluppo top-down). Il
provider JPA che usiamo è Hibernate
il quale grazie alla proprietà:

hibernate.hbm2ddl.auto

impostata al valore “create” consen-


te di derivare le tabelle del database
partendo dalle classi opportunamen-
te annotate. Il Listato 1 riporta il sor-
gente del file persistence.xml. Il risultato
del deploy delle classi entity in JBoss è
la creazione delle tabelle per il databa-
se MySql, riportate in Figura 2.

FIGURA 2 Il diagramma ER (strategia di mapping SINGLE_TABLE)

40 n.5 - novembre/febbraio 2008


JAVA Journal focus

FIGURA 3 Il diagramma ER (strategia di mapping JOINED)

A parte la colonna “DISC” e la colonna ID che è la chiave Considerazioni preliminari sulle strategie di mapping
primaria, tutte le altre colonne della tabella possono assumere il
valore NULL. Questo è necessario, in quanto un record del- Quale strategia di mapping applicare ad una gerarchia di
la tabella può rappresentare una qualsiasi classe presente classi? La risposta a questa domanda non è semplice, in
nella gerarchia. Se, per esempio, avessimo mappato l’attri- quanto varia in funzione del risultato che si desidera otte-
buto “contenutiSpeciali” della classe DVD su una colonna nere: per esempio, prestazioni adeguate o maggiore fles-
dichiarata come NOT NULL sarebbe stato impossibile per- sibilità durante le fasi di design e/o deployment. Di seguito
sistere un oggetto delle classi Libro e VHS… cercheremo di delineare alcune linee guida, ben consci che
tali indicazioni sono preliminari e che necessitano di una
sperimentazione sul campo, specifica al proprio contesto.
La strategia JOINED

Analizziamo ora la strategia di mapping di tipo JOINED. Applicazione della strategia SINGLE_TABLE
A livello di codice Java le classi Prodotto, Libro, Video, VHS
e DVD non variano, a parte il valore assegnato alla anno- La strategia di mapping SINGLE_TABLE è consigliata in
tazione @Inheritance. Di seguito uno stralcio del sorgente presenza di una gerarchia stabile e sostanzialmente sem-
delle classe Prodotto e Libro: plice e poco “profonda”. Infatti aggiungere una nuova
classe alla gerarchia o aggiungere nuovi attributi a qualche
@Entity(name=”Prodotto_Joined”) classe preesistente nella gerarchia porta alla creazione di
@Table(name=”PRODOTTO_JOINED”) nuove colonne nella tabella di mapping. Pertanto una ge-
@Inheritance(strategy=InheritanceType.JOINED) rarchia molto estesa può condurre alla generazione di una
public abstract class Prodotto tabella con un numero di colonne elevato con la conseguenza
{...} di un impatto negativo sul “layout” della tabella e del data-
base in generale. Sempre in relazione al “layout” della ta-
@Entity(name=”LIBRO_JOINED”) bella di mapping è opportuno ricordare che le colonne del-
public class Libro extends Prodotto la tabella mappate sugli attributi delle classi della gerar-
{...} chia devono poter assumere il valore NULL. Inoltre, se per
qualche motivo vi è la necessità di mappare uno o più attri-
buti in colonne di tipo LOB può essere necessario mappare
La struttura delle tabelle che deriva dal modello delle clas- l’entity class non più su una sola tabella ma su più tabelle
si è riportata in Figura 3. Per ogni entità della gerarchia è attraverso l’annotazione @SecondaryTable. Relativamen-
generata una tabella le cui colonne sono solo gli attributi te alle prestazioni, poiché generalmente si è in presenza di
esplicitamente dichiarati nella classe. La root class della ge- una singola tabella, le operazioni di ricerca sui diversi tipi
rarchia è mappata su una root table (in Figura 3 la tabella della gerarchia o su uno specifico tipo risultano efficienti,
PRODOTTO_JOINED) nella quale è definita la chiave pri- non essendo richieste operazioni di JOIN tra tabelle.
maria poi usata in tutte le tabelle della gerarchia. Ogni ta-
bella nella gerarchia definisce una chiave primaria uguale
alla chiave primaria della root table e definisce una foreign
key (chiave esterna) verso la chiave primaria della root ta-
ble.

n.5 - novembre/febbraio 2008 41


focus JAVA Journal

Applicazione della strategia JOINED in JPA. Infatti, il linguaggio è object-oriented, usando nella
sua sintassi le entity class e le regole di navigazione definite
La strategia di mapping di tipo JOINED offre una buona tra le entità, ed è indipendente dal database. Al contrario,
flessibilità durante le fasi di design e di deployment. Infat- il linguaggio SQL, pur esistendo uno standard, è di fatto
ti, l’aggiunta o la rimozione di uno o più attributi ad una coniugato in diversi “dialetti” caratteristici di ogni data-
classe presente nella gerarchia coinvolge nella modifica base che non ne garantiscono la portabilità (vendor lock-in).
solo la tabella che specificatamente rappresenta la classe; Per ottenere una istanza dell’oggetto Query è possibile in-
mentre l’introduzione di una nuova classe nella gerarchia vocare sull’oggetto EntityManger o il metodo createQuery()
porta semplicemente alla creazione di una nuova tabella nel- o il metodo createNativeQuery(). Il primo metodo usa il lin-
lo schema. Relativamente alle prestazioni, una operazione guaggio EJB QL per la definizione dello statement mentre il
di ricerca tra le entità della gerarchia necessiterà di una o secondo metodo usa il linguaggio SQL. Per esempio, con
più operazioni di JOIN anche in funzione della “profon- riferimento alla Figura 2, per ottenere tutti i prodotti è
dità” della gerarchia. Pertanto la presenza di un numero possibile scrivere:
elevato di sottoclassi può avere un impatto negativo sulle
prestazioni. public List<Prodotto> getProdotti()
{
Query query = entityManager.createQuery(“SELECT
Una API per le query con JPA
o FROM Prodotto_Single o”);
La specifica JPA definisce un linguaggio per eseguire le return query.getResultList();
query sulle entità ed il loro stato persistente. Il linguag- }
gio consente allo sviluppatore di specificare la semantica
di una query in modo portabile ed indipendente dallo spe-
cifico database presente nella propria infrastruttura tecno- L’espressione che rappresenta lo statement di una query
logica. Con JPA si è in presenza di una radicale estensione può essere ricavata a runtime, ossia durante l’esecuzione
del linguaggio EJB QL definito nella precedente specifica del programma, come di fatto accade nell’esempio prece-
per gli EJB di tipo Entity Bean versione 2.1 [5]. dente; o può essere dichiarata in un file di configurazione
Nel precedente articolo su JPA [1] abbiamo osservato come della applicazione. Nel primo caso si è in presenza di una
attraverso l’oggetto EntityManager è possibile fare semplici query dinamica, nel secondo di una query statica o di una na-
operazioni di ricerca attraverso il metodo find(). La firma med query. Le query statiche sono dichiarate attraverso la
del metodo è: annotazione @NamedQuery. Per esempio, la query prece-
dente può divenire una named query dichiarandola come
public <T> T find(Class<T> entityClass, Object annotazione del sorgente della classe Prodotto:
primaryKey);
@Entity(name=”Prodotto_Single”)
Il metodo accetta come parametro di input il tipo della en- ...
tity class di cui tornarne una istanza ed un oggetto che rap- @NamedQuery(name = “Prodotto.findAll”,
presenta la chiave primaria e restituisce l’istanza della en- query = “SELECT o
tity class di data chiave primaria. Il metodo è pratico e allo FROM Prodotto_Single o”)
stesso tempo semplice. Tuttavia nei progetti è necessario, public abstract class Prodotto implements
la maggior parte delle volte, eseguire query complesse la Serializable
cui esecuzione restituisce, eseguendo operazioni di JOIN e {
condizioni di WHERE articolate, una o più istanze di enti- ...
ty class. In questi casi è necessario usare un oggetto di tipo }
Query, definito nel package javax.persistence e la sintassi
estesa del linguaggio EJB QL. I passi essenziali per creare
un oggetto Query ed eseguire una query sono schematizza- Per usare una named query il metodo precedente diviene:
ti di seguito:
public List<Prodotto> getProdotti()
• Recuperare dall’Entity Manager una istanza della {
classe javax.persistence.Query; Query query = entityManager.createNamedQuery(
• Impostare i parametri necessari all’esecuzione “Prodotto.findAll”);
della query; return query.getResultList();
• Eseguire effettivamente la query. }

Come si è detto in precedenza, le query possono essere


scritte attraverso il linguaggio EJB QL. Tuttavia è anche Ovviamente è possibile dichiarare più di una named query
possibile usare direttamente il linguaggio SQL ed in tal come annotazione di una entity class. In tal caso è neces-
caso si è in presenza di query scritte in linguaggio nativo sario usare l’annotazione @NamedQueries. Prima di ter-
(indicate, infatti, con il termine native query nella specifi- minare è opportuno accennare ai named parameters attra-
ca). Il linguaggio EJB QL, sintatticamente molto simile al verso i quali è possibile specificare le condizioni di WHE-
linguaggio SQL, è la via preferenziale per scrivere le query RE. Per esempio se vogliamo ricercare i prodotti che han-
no un titolo particolare possiamo definire la named query

42 n.5 - novembre/febbraio 2008


JAVA Journal focus

come segue:
@TransactionAttribute(
@NamedQuery(name = “Prodotto.findByTitolo”, TransactionAttributeType.REQUIRES_NEW)
query = “SELECT o public void bulkUpdate(String entityName)
FROM Prodotto_Single o {
WHERE o.titolo = :TITOLO”) String dOperation = “UPDATE “+entityName+” t
SET t.annoProduzione = :ANNO_PRODUZIONE”;
Query q = entityManager.createQuery(dOperation);
ed un metodo che la usa: q.setParameter(“ANNO_PRODUZIONE”, null);
q.executeUpdate();
public List<Prodotto> getProdottiByTitolo(String }
titolo)
{ @TransactionAttribute(
Query query = entityManager.createNamedQuery( TransactionAttributeType.REQUIRES_NEW)
“Prodotto.findByTitolo”); public void bulkDelete(String entityName)
query.setParameter(“TITOLO”, titolo); {
return query.getResultList(); Query q = entityManager.createQuery(
} “DELETE FROM “+entityName);
q.executeUpdate();
}

EJB-QL: nuove caratteristiche

In precedenza abbiamo osservato come il linguaggio per In particolare, con riferimento alla Figura 2, il metodo
eseguire le query definito nella specifica JPA sia una esten- bulkUpdate() imposta il valore della colonna “anno di pro-
sione del linguaggio EJB QL. In particolare, introduce varie duzione” presente nella tabella PRODOTTO_SINGLE al va-
migliorie che di seguito accenniamo: lore null; mentre il metodo bulkDelete() elimina tutti i re-
cord rappresentati da una entity class. Osserviamo che se
• Aggiornamenti e cancellazioni “massive”; si invocato i metodi bulkUpdate() e bulkDelete() passando
• Operazioni di JOIN; come parametro di input il valore “Libro_Single”, ossia il
• Parole chiave GROUP BY e HAVING; nome della entity class Libro, sono aggiornati ed eliminati
• Projection; i record relativi ad un libro; viceversa, se si invocano i due
• Subquery. metodi passando come parametro di input il valore “Pro-
dotto_Single”, ossia il nome della entity class Prodotto (la
Operazioni massive root class della gerarchia), sono aggiornati ed eliminati tutti
i record relativi ad un libro, ad un video di tipo DVD e ad
Per aggiornamenti e cancellazioni “massive” indichiamo un video di tipo VHS.
una singola operazione il cui risultato è l’eliminazione o
aggiornamento di un numero, anche elevato, di entità (in
inglese i termini per indicare queste caratteristiche sono Operazioni di JOIN
bulk update e bulk delete). Quando si esegue una operazione
di cancellazione o di aggiornamento “massivo” valgono le Analizziamo ora il supporto introdotto in JPA per la gestio-
seguenti regole: ne delle operazioni di JOIN. Con JPA possiamo avere i se-
guenti tipi di JOIN:
• L’operazione “massiva” si applica all’entità
“sorgente” della bulk operation e a tutte le • JOIN;
sottoclassi di questa; • LEFT JOIN;
• L’operazione non si propaga alle entità • FETCH JOIN.
relazionate con l’entità “sorgente” della
bulk operation; Per esempio, sempre con riferimento alla Figura 2, se vo-
• Il persistence context non è sincronizzato con lessimo trovare tutti i prodotti che hanno associato almeno
il risultato della operazione. un autore potremmo scrivere la JOIN:

L’ultima tra le regole sopra elencate merita una riflessione. @NamedQuery(name=”prodottiByAutoreJOIN”,


Poiché il persistence context non si sincronizza con il risulta- query=”SELECT o FROM Prodotto_Single o
to di una operazione “massiva” è necessario che tali opera- JOIN o.autori”)
zioni avvengano o all’inizio di una transazione o che siano
eseguite in una transazione separata.
Lo stralcio di codice che segue (due metodi presenti in un Viceversa, per ottenere i prodotti ai quali è associato o
EJB di tipo session stateless) mostra un semplice esempio meno un autore scriveremo la LEFT JOIN:
di bulk update e di bulk delete:
@NamedQuery(name=”prodottiByAutoreLEFT_JOIN”,
query=”SELECT o FROM Prodotto_Single o
LEFT JOIN o.autori”)

n.5 - novembre/febbraio 2008 43


focus JAVA Journal

Le FETCH JOIN consentono di caricare le entità correlate Subquery


specificate in una query, indipendentemente dalla politica
di “loading” specificata nella definizione della relazione. Concludiamo questa panoramica sulle nuove caratteristi-
Ricordiamo che in JPA, nella definizione di una relazione, che introdotte nel linguaggio parlando delle subquery. At-
la politica di caricamento può assumere i valori: EAGER e traverso una subquery è possibile eseguire delle query come
LAZY (Per ulteriori informazioni si veda [1]). La modalità parte della condizione di WHERE. L’uso delle subquery deve
di caricamento EAGER è generalmente meno efficiente, in essere ben valutato in quanto può portare ad un degrado
quanto porta a caricare in memoria l’intera mappa delle re- delle prestazioni. Ad esempio, se volessimo recuperare tut-
lazioni; viceversa, la modalità di caricamento LAZY indica ti i prodotti che sono stati realizzati da almeno due autori
che le entità correlate sono caricate solo quando è necessa- è possibile scrivere:
rio (purché vi sia un persistence context attivo). Ad esempio
(sempre con riferimento alla Figura 2), se tra le entità Pro- @NamedQuery(name=”findWithSubQuery”,
dotto e Autore la relazione molti a molti fosse caratterizzata query=”SELECT o
da una modalità di caricamento LAZY e volessimo esegui- FROM Prodotto_Single o
re una query il cui risultato siano i prodotti con valorizzato WHERE (SELECT count(e)
l’elenco di autori ad essi relazionati potremmo scrivere: FROM o.autori e) > 0”)

@NamedQuery(name=”prodottiByAutoreFETCH_JOIN”,
query=”SELECT o FROM Prodotto_Single o
Conclusioni
JOIN FETCH o.autori”)
Con questo articolo concludiamo la panoramica sulla spe-
cifica JPA. Non è stato possibile trattare tutte le caratte-
Parole chiave GROUP BY e HAVING ristiche della persistence API, tuttavia sono evidenti due
peculiarità: da un lato la semplicità di JPA come prodotto
Nella precedente specifica di EJB QL era assente il suppor- ORM (Object Relational Mapping) e dall’altro l’estrema fles-
to per le parole chiave GROUP BY e HAVING di SQL. Nella sibilità dell’API con il mapping delle relazioni e della ere-
attuale specifica JPA tale supporto è stato introdotto: per- ditarietà. Sarà il tempo a dirci se JPA diverrà la modali-
tanto è possibile scrivere query che specificano raggruppa- tà standard e più diffusa, tra sviluppatori e architetti del
menti e condizioni tramite queste keyword. Per esempio software, per persistere gli oggetti in Java. Tuttavia, per
per ottenere i conteggi del numero di video, sia VHS che quanto si è detto e per la diffusione di Hibernate e TopLink
DVD, che sono a colori ed in bianco e nero possiamo scri- (genitori naturali di JPA), le premesse sono estremamen-
vere: te positive.

@NamedQuery(name=”contaVideo”,
Riferimenti
query=”SELECT o.colore,
COUNT(o) FROM Video_Single o [1] : JPA (prima parte). Java Journal N. 4, anno I.
GROUP BY o.colore”) [2]: http://www.jboss.com/.
[3]: http://www.mysql.com/
[4]: http://www.hibernate.org/
Proiezioni [5] : Enterprise JavaBeans, v 2.1. http://java.sun.com/
products/ejb
Con il termine Projection la specifica indica la possibilità
che nel risultato di una query siano presenti solo alcuni at- Bibliografia:
tributi di una entità o di un insieme di entità. Si tratta di
una ottimizzazione nel caso ad un client non interessi la- [MEJ]: Mastering Enterprise JavaBeans 3.0, edito dalla Wiley
vorare con la totalità degli attributi di una entità, ma solo Publishing, Inc. Autori: Rima Patel Sriganesh, Gerald Bro-
con un sottoinsieme. Per esempio, se avessimo necessità di se, Micah Silverman.
un elenco con solo i titoli e l’anno di produzione dei pro- [BAD]: Beginning EJB 3 Application Development, edito dalla
dotti possiamo scrivere: Apress. Autori: Raghu R. Kodali and Jonathan Wetherbee
with Peter Zadrozny
@NamedQuery(name=”findWithProjection”,
query=”SELECT o.titolo,
o.annoProduzione FROM Prodotto_Single o”)

Il risultato della query è un vettore in cui ogni elemento Note Biografiche


è un array di Object. Nell’esempio riportato, ogni array di Fabio Staro dottore in Fisica è Responsabile Tecnico per i
Object ospitato nel vettore contiene due elementi: il titolo di progetti Java presso la Direzione Ricerca ed Innovazione di
tipo String e l’anno di produzione di tipo Date. Engineering Ingegneria Informatica S.p.A.

44 n.5 - novembre/febbraio 2008


COMMUNITY
FREESPEECH Login Topic

COMMUNITY WATCH
Il JUG Torino
Ü di Stefano Sanna
(stefano.sanna@javajournal.it)

Dopo aver conosciuto il Java User Group Sardegna ONLUS,


proseguiamo il nostro viaggio nella penisola alla scoperta dei
JUG italiani. Dal sud a nord: facciamo conoscenza con il JUG
Torino e con Bruno Bossola, Java Champion nonché uno dei
fondatori del gruppo piemontese.

Java Journal: Prima di tutto, ci dici in due parole chi è Bruno Bos-
sola?

Bruno Bossola: Sono uno dei tanti programmatori in circola-


zione che ha iniziato con un VIC20, percorrendo tutta la lunga
strada CBM fino a chiudere con un fantastico Amiga 500 con
20MB di hard disk SCSI! Il mondo del lavoro mi ha portato
a lavorare in C per 8 anni, prima nell’ambito dell’automazio-
ne industriale e poi nel CAD, per poi proseguire con Java per
i restanti 11 anni (wow, quanto tempo!). La mia dedizione alla
piattaforma Java, unita anche a tutti gli sforzi che ho fatto per
diffonderla, mi è anche valsa il riconoscimento di Java Cham- BB: Il JUG si occupa principalmente di diffondere la co-
pion [1] noscenza di Java sul territorio locale organizzando meeting
mensili e altri eventi, come il JavaDay e l’ancora più recente
JavaDay@school [4], quando ci siamo recati ad evangelizzare
JJ: Com’è iniziata l’avventura del JUG Torino? (si fa per dire!) direttamente l’ITIS Avogadro di Torino :) Scri-
viamo saltuariamente anche del software, qualcuno di noi parte-
BB: L’idea originale è di Luigi Viggiano [2], che per primo in- cipa a progetti opensource, ma quello che ci piace di più è con-
viò la richiesta di un JUG sull’allora sito di mamma Sun. Quan- dividere la conoscenza che ciascuno di noi possiede! Nei mee-
do tornai da un paio d’anni di vita a Milano io e Luigi, grazie ting troverete sempre interventi interessanti, da relatori com-
anche all’aiuto di altre persone, fondammo in un bar, di fronte a petenti, e su argomenti che possono veramente fare da traino
una sontuosa esposizione alcolica :) , il JUG Torino. Tutta la sto- alla vostra formazione personale. Il JUG offre anche degli scon-
ria la trovate comunque sul sito del JUG [3] ti agli iscritti per acquisire la certificazione Sun e per partecipa-
re a corsi di formazione. Inoltre organizza ogni tanto “trasferte”
JJ: Quali sono le attività principali del JUG? per seguire le conferenze internazionali più importanti, come
JavaPolis [5] o Jazoon [6].
Note Biografiche
JJ: Torino rappresenta uno dei poli scientifici ed industriali più impor-
tanti del Paese. Il JUG, per così dire, nasce in una valle fertile ...
Stefano Sanna si occupa di sviluppo di applicazioni multi-
mediali per piattaforma Savaje presso Beeweeb Technolo-
BB: Sì, anche se trovandoci in un’area industriale ci ritrovia-
gies (http://www.beeweeb.com). Ha lavorato per sette anni
mo comunque di fronte a una mentalità analoga, con processi di
nel gruppo Network Distributed Applications del CRS4, oc-
tipo predittivo e strumenti “mainstream”. Qui le industrie usa-
cupandosi di mobile computing e applicazioni network-orien-
no ancora Struts 1 e i DAO, e non è sempre uno spasso. Il van-
ted per cellulari e PDA. Collabora attivamente con JIA, JUG
taggio è che lo spazio per crescere è molto, e i membri del JUG
Sardegna e Java Mobile Developers Forum. Il suo sito web
sono spesso dei “motori” di questa spinta!
personale è http://www.gerdavax.it

46 n.5 - novembre/febbraio 2008


COMMUNITY
FREESPEECH Login Topic

tro campi e bottoni: non ci potete dare un’infrastruttura di base


molto buona (pensate a JDBC ad esempio) mentre poi qualcun
altro si occupa, eventualmente, di creare un framework decen-
te? (pensate a Hibernate ora). Questo comunque per citarne un
paio; se volete approfondiamo: sul lato EE ci sono ben altri mo-
stri, o anche roba che semplicemente non serve, tanto che anche
la Sun se ne è accorta e per la prossima Java EE 6 comincerà con
il cosiddetto “pruning” di alcune librerie (ciao ciao EJB2 enti-
ty beans!!!). Per quanto riguarda il linguaggio ci sono due passi
ancora fondamentali da fare secondo me. Innanzitutto allegge-
rire il controllo sui tipi, che nacque per aiutare il programma-
tore a fare meno errori ma che ora è diventato semplicemente
un modo per imboccare il compilatore: noi abbiano bisogno che
il nostro codice sia espressivo, che dichiari le sue intenzioni,
mentre siamo costretti a irrigidirci in costrutti sintattici molto
complessi che sono di solo aiuto al compilatore, non a noi. Ri-
tengo poi necessario introdurre le closure, meglio con la propo-
sta BGGA di Gafter & Co, che permetterebbero di realizzare au-
tonomamente semplici estensioni al linguaggio e di introdurre
un approccio innovativo allo sviluppo, consentendo ad esempio
con molta semplicità l’uso di iteratori interni.
JJ: In Italia ci sono tanti JUG, apparentemente segno di divisione. In
realtà i JUG italiani collaborano tanto tra di loro, il JavaDay ne è pro- JJ: Un consiglio al neofita che vuole imparare il linguaggio...
va tangibile. Perché?
BB: Beh, libri che parlano di Java ce ne sono parecchi, ma per
BB: Il territorio italiano purtroppo non si presta ad avere un quanto riguarda i neofiti devo dire che non ho ancora trovato
singolo JUG, la sua stessa struttura porta ad una forte segmen- un testo in italiano decoroso ... Onestamente non saprei consi-
tazione. Ecco perché ci sono tanti JUG, che però collaborano gliare! Forse “Thinking in Java”, di Eckel oppure “Core Java”
attivamente fra di loro: la motivazione alla base della separa- di Horstmann, che si trovano anche tradotti in italiano. Il mio
zione è tutt’altro che campanilistica. In effetti però allo stato consiglio è di imparare prima di tutto l’inglese e di acquista-
attuale la frammentazione è un po’ troppa, e quello che insie- re qualche libro in lingua originale, che parli di Object Orien-
me con il JUG Milano si sta cercando di fare, ad esempio qui ted, come “Object-Oriented Software Construction” di Meyer.
al nord, è di trovare una squadra per formare almeno un’enti- Quindi leggere un buon testo su Java, seguendo contempora-
tà che aggreghi noi due (e chi si vuole unire!) anche perché il neamente il Java Tutorial [7] sul sito della Sun. Se avete la possi-
coordinamento delle attività del JUG pesa parecchio. Comun- bilità poi di seguire un corso fatelo, se poi il docente è bravo an-
que ben vengano anche JUG microscopici: quando c’è la voglia cora meglio. Non dimenticatevi poi di iscrivervi ad un JUG lo-
sei al 90% dell’opera :) , e la volontà di fare cose tutti insieme cale: quello sarà per voi il vero punto di riferimento nel tempo!
non manca mai!
JJ: JUG Torino nel 2008: cosa bolle in pentola?
JJ: Java ha portato con sé tante tecnologie che hanno rivoluzionato il
modo di programmare (Applet, MIDlet, Servlet ...). Quale sarà, a tuo BB: Per il 2008 prevediamo sicuramente di replicare il JavaDay,
avviso, la prossima rivoluzione? visto il successo dell’iniziativa (più di 130 persone sono interve-
nute nel 2007!). E credo cercheremo di portare avanti il proget-
BB: La prossima rivoluzione per quanto riguarda la piattafor- to JavaDay@school coinvolgendo altre scuole. Insieme con gli
ma Java si svolgerà nel mondo mobile: nuovi e potenti devi- altri JUG, inoltre, stiamo poi cercando di organizzare una nuo-
ce, con processori di potenza paragonabile a quella degli attua- va iniziativa nazionale, sulla quale non posso purtroppo anco-
li desktop, renderanno possibile operare con API simili a quelli ra dire nulla ma che vi garantisco sarà qualcosa di sensazionale!
di Java SE, rendendo di fatto obsoleta l’attuale distinzione fra Rimanete sintonizzati sui nostri blog :) [8]
queste piattaforma e Java ME; alla fine queste si unificheran-
no, differenziandosi magari solo per un profilo. In generale nel-
l’arena dei linguaggi prevedo un’ascesa di Javascript, che nei
prossimi anni diventerà pienamente object oriented e rivaleg-
gerà a pieno titolo la supremazia attuale di Java.

JJ: Quali, invece, le limitazioni che Java dovrebbe superare? Ringraziamo Bruno Bossola per il tempo che ci ha dedicato e
per l’impegno suo e di tutto il JUG Torino nel promuovere Java
BB: Java dovrebbe innanzitutto lavorare su alcune librerie di nel nostro Paese.
base che attualmente incorpora nel core, cercando di eliminar-
le o riscriverle. Innanzitutto il Collections framework: una cosa
veramente triste; viola pressoché tutti i principi OO che cono-
sco (pensate ad esempio alla sostituibilità e alle famigerate Un- [1] http://java-champions.dev.java.net/
supportedOperationException); soffre di una progettazione ve- [2] http://it.newinstance.it/
ramente povera (pensate ai tristissimi iteratori esterni: ma i [3] http://www.jugtorino.it/vqwiki/jsp/Wiki?StoriaDelJug
blocchi di SmallTalk proprio li abbiamo dimenticati?); e man- [4] http://www.jugtorino.it/vqwiki/jsp/Wiki?JavaDayAtSchool
ca anche secondo me di una metafora uniforme (è così difficile [5] http://www.javapolis.com
pensare alle liste come delle mappe in cui la chiave è l’indice?). [6] http://www.jazoon.com
Passiamo ora a Swing: a me sembra un campionato di overdesi- [7] http://java.sun.com/docs/books/tutorial/
gn! Insomma, alla fine dobbiamo aprire delle finestre con den- [8] http://www.jugtorino.it/vqwiki/jsp/Wiki?Blog

n.5 - novembre/febbraio 2008 47


CORSI
DI FORMAZIONE
ON-SITE

education@infomedia.it
OFFERTE ABBONAMENTI
2008
ABBONAMENTO ANNUALE
WEB Cartaceo

COMPUTER PROGRAMMING 50,00€ 75,00€

DEV 50,00€ 75,00€

VISUAL BASIC & .NET JOURNAL 40,00€ 52.50€

LOGIN 40,00€ 52.50€

JAVA JOURNAL 40,00€ 52.50€

2 a scelta 80,00€

3 a scelta 120,00€

4 a scelta 170,00€

5 a scelta 220,00€

INDIRIZZO DI SPEDIZIONE INDIRIZZO DI FATTURAZIONE


(solo per riviste web)
Nome/Società __________________________________________________________ Nome e Cognome _______________________________________________________

Codice Fiscale (obbligatorio) ________________________________________________ Ditta __________________________________________________________________

Indirizzo _______________________________________________________________ Indirizzo _______________________________________________________________

CAP _____________ Città ___________________________________ Prov. ______ CAP ____________ Città _________________________________ Prov. _________

Telefono ____________________________ Fax ______________________________ P.IVA _________________________________________________________________

E-Mail ________________________________@_______________________________ E-Mail per invio fattura _________________________ @ ________________________

Codice Cliente __________________________________________________________

• I prezzi degli abbonamenti Web sono conprensivi dell’ IVA al 20% MODALITA’ DI PAGAMENTO
• I prezzi degli abbonamenti per l’estero sono maggiorati di spese di spedizione. � Allego fotocopia del Bonifico Bancario effettuato sul C/C 000000014804
CAB 25200 ABI 01030 Cin “A” - Monte dei Paschi di Siena - Agenzia di Perignano
• Gli abbonamenti decorrono dal primo numero raggiungibile. IBAN IT84A0103025200000000014804
Per attivazioni retroattive contattaci al numero 0587/736460 o invia una e-mail
all’indirizzo: abbonamenti@gruppoinfomedia.it � Allego fotocopia della ricevuta del versamento sul C/C Postale N.14291561 intestato
a: “Gruppo Editoriale Infomedia S.r.l. - Ponsacco” IBAN IT84X0760114000000014291561

PRIVACY � Allego assegno bancario intestato a: “Gruppo Editoriale Infomedia S.r.l.”


NON TRASFERIBILE
Con la presente si autorizza al trattamento dei dati personali ai sensi delle
vigenti norme sulla privacy � Contrassegno (+ € 11.00 contributo spese postali)
� Autorizzo l’addebito dell’importo di € _____________________ sulla mia CARTASI’/VISA
FIRMA________________________________________________ N. _________________________________________________________________

Scad. ______ / ______ (mm/aa) Codice di sicurezza “CV2” ______________


SI , mi voglio iscrivere gratuitamente alla newsletter Infomedia
che mi tiene aggiornato sui prossimi argomenti delle mie riviste di Nome del Titolare ____________________________________________________
programmazione e mi informa delle offerte, le nuove uscite e le prossime
pubblicazioni. Questo è il mio indirizzo di posta elettronica: Data di nascita ____________________________________________________
______________________________@____________________________ Firma del Titolare ____________________________________________________
Posso annullare la mia iscrizione in qualsiasi momento alla pagina: � Collegati al sito www.shopinfomedia.it dove potrai effettuare il pagamento con
www.infomedia.it/newsletter.htm carta di credito in modalità sicura (banca SELLA)

Garanzia di riservatezza - Gruppo Editoriale Infomedia garantisce la massima riservatezza dei dati da lei forniti e la possibilità di richiederne gratuitamente la rettifica
o la cancellazione scrivendo a: Responsabile Dati - Gruppo Editoriale Infomedia Srl - Via Valdera P. 116 - 56038 Ponsacco (PI). Le informazioni custodite nel nostro
archivio elettronico verranno trattate in conformità alla legge 196/03 sulla tutela dati personali.
L’IVA sul prezzo dell’abbonamento cartaceo è assolta dall’Editore e non sussiste l’obbligo di emissione della fattura, ai sensi del D.M. 9 aprile 1993, art.1, comma 5;
pertanto, ai fini contabili, farà fede la sola ricevuta di pagamento; perciò la fattura verrà emessa solo se esplicitamente richiesta al momento dell’ordine.
Lei può dedurre il costo dell’abbonamento dal reddito d’impresa e dai redditi derivanti dall’esercizio di arti e professioni (artt. 54 e 56 del TUIR)

GRUPPO EDITORIALE INFOMEDIA S.R.L.


Via Valdera P. 116 - 56038 Ponsacco (PI) - Tel. 0587 736460 - Fax 0587 732232
www.infomedia.it - abbonamenti@gruppoinfomedia.it
“Si fa presto a dire sito web”
di Paolo Frattini
Anno 2007
54 pagine a colori, formato A4
ISBN 9788881500222

solo
12,90
Euro

Fai il make-up al tuo sito web


con l’ultimo libro di Paolo Frattini

l e , t r u c c hi e c o nsigli
Scopri rego
c o m u n i c ar e v i a I nternet
per

“Si fa presto a dire sito web”


Ordinalo su

www.shopinfomedia.com