j2007 03 jj4

58

Upload: turing-club

Post on 07-Jun-2015

600 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: j2007 03 jj4
Page 2: j2007 03 jj4

���� ��� ������� ���������� �������������� ����� ����������� ���������� ���� ��� ������ ����������� ���� ��������� ���������� ������ ���� �������� �����������������������������������������������������������������������������������������������������������������������������������������

���������������������������������������������������������������������

���������������������������������������������������������������������������������������������������

�����������

���������������

����������� ��������������������� �������

������������������������������������������������������� �������

�� ������� ������ ������������ ���� ��������� ����� ����������� ��� ������ �����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

�����������������������

������������������������������������������������������������

�������������������������������������������������������������

����������������������������������������������������������������

��������������������������������������������������������������

������������������������������������������������������������

��������������������������������������������������������������

����������������������

��������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

����������������������������������������������������������������������������

������������������������������������������������������������������������������

�����������������������������������������������������������������������������

�������������������������������������������������������������������������������

������������������������������������������������������������������������������

���������������������������������������������������������������������������������������������������������������������������������

�������� ������� ������� ������������ ���������� ���� ���� ����� ���������������������������

���� ����������� ���� �� ��������������� ����� �� ���������� ������������������ ������������������������������� �� ����� �����������������������

����������� ��� ��������� ��� ���������� ��� ������������ ���� �����

����������������������������������������������������

���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

����������������������������

Page 3: j2007 03 jj4

EDITORIALEwww.infomedia.it

n.4 - settembre/ottobre 2007 3

JAVA Journal

BIMESTRALE - ANNO 1 - N.4

D I R E T T O R E R E S P O N S A B I L E MA R I A L E T I Z I A MA R I

(M M A R I@I N F O M E D I A . I T )

D I R E T T O R E E S E C U T I V O

MI C H E L E SC I A B A R R À

(M I C H E L E .S C I A B A R R A@J A V A J O U R N A L . I T )

E D I T O R I A L B O A R D

UG O LA N D I N I , ST E F A N O SA N N A, FA B I O ST A R O, TO N Y MO B I L Y

R E D A Z I O N E

M I R E L L A D I G I R O L A M O

C O L L A B O R A T O R IA N D R E A C O L L E O N I

J A C O P O G I U D I C IM A R C O PA N C O T T I

FE D E R I C O PA P A R O N IS T E F A N O S A N N AR O B E R T O S I D O T I

FA B I O S T A R OAN D R E A ZO L E O

GR U P P O ED I T O R I A L E IN F O M E D I A S R L

V I A VA L D E R A P.11656038 PO N S A C C O (PI ) I T A L I A

TE L 0587736460 FA X 0587732232E -M A I L I N F O@I N F O M E D I A . I T

S I T O WE B W W W. I N F O M E D I A . I T

D I R E Z I O N E NA T A L E FI N O (N F I N O@I N F O M E D I A . I T )

C O N T A T T I

TE C H N I C A L B O O K(B O O K@I N F O M E D I A . I T )

M A R K E T I N G & A D V E R T I S I N GSE G R E T E R I A : 0587736460

(M A R KE T I N G@I N F O M E D I A . I T )

A M M I N I S T R A Z I O N E(A M M I N I S T R A Z I O N E@I N F O M E D I A . I T )

S E G R E T E R I A ( I N F O@I N F O M E D I A . I T )

G R A F I C A(G R A F I C A@G R U P P O I N F O M E D I A . I T )

U F F I C I O A B B O N A M E N T ITE L 0587736460 FA X 0587732232

A B B O N A M E N T I@I N F O M E D I A . I T

W W W. I N F O M E D I A . I T

J A V A E T U T T I I M A R C H I D E R I V A T I S O N O M A R C H I O M A R C H I R E G I S T R A T I D I SU N M I C R O S Y S T E M S , I N C . N E G L I USA E I N A L T R I PA E S I . I L GR U P P O E D I T O R I A L E I N F O M E D I A È I N D I P E N -D E N T E D A SU N M I C R O S Y S T E M S , I N C .

J A V A J O U R N A L È U N A R I V I S T A D E L GR U P P O ED I T O R I A L E I N F O M E D I A S R LD I R E Z I O N E E A M M I N I S T R A Z I O N E :V IA VALDERA P.116 - PONSACCO (PI )RE 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 D I P I S A N .19 /06 D E L 5 /9 /2006

JavaFx: si ricomincia?

Avete mai “giocato” con una applet? Se siete programmatori Java della prima ora, la risposta non può che essere: ovviamente!

Ma non molti sono così… “anziani”. Considerando che la vita media di un programmatore è di circa cinque anni (poi si diventa team leader, project manager e così via, cioè... sempre meno codice e sempre più attività commerciale e di management), la maggior parte dei programmatori Java in attività ha cominciato con J2EE, quindi dopo il 2000; e così molti non hanno avuto occasione di “toccare con mano” le famose applet.

Oserei dire: per fortuna! Perché, a parte le prime implementazioni in cui tutto filava liscio, a partire dalla famosa guerra dei browser Microsoft-Netscape, sviluppare delle applet era un vero incubo in termini di compatibilità. E così lo spazio vitale delle applicazioni Web lato client è stato lentamente conquistato da Flash, che ha da sempre avuto il pregio di essere molto leggero e molto orientato ai grafici. Mentre Java ha conquistato il suo spazio vitale nel mondo server. Almeno finché lo spazio dei grossi server Internet di Sun non è stato rosicchiato da Linux. Ma questa è un’altra storia.

Il mondo cambia, ma spesso tende a un ritorno alle origini. E infatti oggi si parla tanto di rich client e di applicazioni GUI che si installano dalla rete. E verrebbe da dire: Ma no? Che novità! Infatti avverto un fortissimo senso di déjà vu.

Ad ogni modo, abbiamo in campo da un lato Flash, che cerca di estendersi ovunque con Flex e Apollo, e propone un Javascript super potenziato (da sembrare quasi Java); dall’altro Microsoft che con il Silverlight e .NET propone una soluzione, a tutti gli effetti concorrente di Flash, che a dire di Microsoft è interoperabile tra le varie piattaforme (sarà... vedremo).

E nel mezzo Java che fa? Francamente, non mi è chiarissimo. Quello che è certo è che è stato creato JavaFx, che è sempre Java (come tecnologia, JVM, ecc.), ma utilizza un linguaggio Java semplificato, tanto da sembrare JavaScript, e con molte caratteristiche che lo rendono allettante per i grafici (dalle demo si nota che ha una sintassi che rende molto semplice creare applicazioni grafiche sofisticate, stile Flash appunto).

La sensazione è che si stia ricominciando con la battaglia delle applet, con una versione di Java che vuole competere con Flash. A rinforzare questa sensazione l’annuncio che il prossimo Java runtime sarà modulare, e comprenderà solo “quello che serve”.

Ad oggi, scaricare JavaRuntime per Windows, per esempio, è un download da 20 MB, mentre quello di Flash è un download di 2 MB. L’obiettivo del nuovo runtime Java è di “pesare poco”, pochi megabyte (quanti, di preciso, è da vedere).

In sintesi, mi sembra che l’obiettivo sia proprio rendere Java comparabile con Flash, e riproporre, 10 anni dopo, l’idea originale che ha portato al successo di Java: le applet!

Michele SciabarràDirettore Esecutivo

Java Journal

Page 4: j2007 03 jj4

Speciale Object/Relational MappingIntroduzione a Hibernatedi Marco Pancotti 8iBatis: il più nostalgico degli ORMdi Roberto Sidoti 14JPA: JAVA Persistence API - Prima partedi Fabio Staro 20

EducationalXP e dintorni di Andrea Zoleo 32

Focus Database con SuperWaba per PDA e Smartphonedi Jacopo Giudici 40Grafici nelle applicazioni JAVAdi Federico Paparoni 48

RubricheOrizzonti EnterpriseTutto ciò che è tendenza nel mondo JEE

di Fabio Staro 29

Community WatchIntervista al JAVA User Group Sardegna Onlus

di Stefano Sanna 55

SOMMARIO Settembre/Ottobre 2007

numero 4 JAVA Journal

n.4 settembre/ottobre 2007

Page 5: j2007 03 jj4
Page 6: j2007 03 jj4

IN VETRINA

>> 6JAVA JOURNAL > n.4 settembre/ottobre 2007

Java Persistence with Hibernate - 2nd Edition di C. BauerManning980 pp - euro 52,95 ISBN 9781932394887

EJB 3 in Actiondi D. Panda, R. Rahman e D. LaneO’ Reilly712 pp - euro 44.95ISBN 9781933988344

Professional Microsoft Smartphone Programmingdi B. Yang, P. Zheng e L. M. NiJonh Wiley 494 pp - euro 50,70ISBN 9780471762935

JavaScript & DHTML Cookbook, Second Edition di D. GoodmanO’ Reilly604 pp - euro 45,00ISBN 9780596514082

Practical JBoss® Seam Projects di J. FarleyApress229 pp - euro 46,40ISBN 9781590598634

The Web’s Awake: An Introduction to the Field of Web Science and the Concept of Web Lifedi P. D. TetlowJohn Wiley239 pp - euro 44,50ISBN 9780470137949

Now You Know Treo 680 Smartphone di P. AmesAddison Wesley160 pp - euro 25,50ISBN 9780321453488

Smartphone Operating System Concepts with Symbian OS: A Tutorial Guidedi M. J. Jipping John Wiley354 pp - euro 57,40ISBN 9780470034491

iPhone : The Missing Manualdi D. Pogue O’ Reilly304 pp - euro 22,30ISBN 9780596513740

Page 7: j2007 03 jj4

IN VETRINA JAVA JOURNAL 4

Scrivi a [email protected] specificando nell’oggetto della e-mail: IN VETRINA Java Journal n. 4

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

JAVA JOURNAL 4

iBATIS in Action, Edition 1di C. Beginet al.Manning384 pp - euro 41,00ISBN 9781932394825

Professional Java JDK 6 Editiondi W. C. Richardson et al.John Wiley741 pp - euro 41,50ISBN 9780471777106

Walls: Spring in Actiondi C. Walls e R. BreidenbachManning650 pp - euro 45,00ISBN 9781933988139

Page 8: j2007 03 jj4

JAVA Journal

8 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 9

Object/Relational Mapping speciale

Scrivere un breve testo su Hibernate è tutt’altro che facile, in quanto il prodotto è estremamente ricco di funzionalità e di caratteristiche, ognuna delle quali meriterebbe un approfondimento a sé.

>> di Marco Pancotti ([email protected])

Questo articolo è una introduzione “a volo di rondine” su ciò che Hi-bernate può offrire a chi sviluppa applicazioni Java in cui la persi-stenza degli oggetti è un elemen-to determinante. Seguiranno, nei

prossimi numeri di Java Journal, una serie di articoli in cui, passo dopo passo, si vedrà, in dettaglio, come installare Hibernate, come utilizzarlo per mappare dei Domain Model complessi e come ottimizzarne le prestazioni.

Il problema del mapping Object/Relational

Il problema della mappatura oggetto/relazione è un tema vasto ed interessante, ma trascende lo scopo di questo primo articolo, che vuole invece concentrar-si sulla soluzione che Hibernate propone. Per questo motivo in questo contesto ci limitiamo ad osserva-re che:

• Hibernate è un vero e proprio O/R Mapper, non un wrapper (com’è ad esempio Rails), o un Data Mapper (come è Ibatis). Le differenze sono sottili ma importanti. Un wrapper, ad esempio, richiede che la progettazione avvenga in termini di model-lo relazionale e che il Domain Model sia derivato dal data model, mentre un ORM permette un di-segno ad oggetti indipendente da cui si è in grado successivamente di derivare, in modo automati-co, il modello relazionale ideale. Un Data Mapper, invece, richiede che l’accesso al database venga specificato in termini di codice SQL, mentre un

ORM produce SQL sulla base di metadati associa-ti alla classe da rendere persistente.

• Hibernate richiede un certo sforzo di apprendi-mento, in quanto affronta un tema complesso in modo professionale. Le ottimizzazioni possibili sia in lettura sia in scrittura, l’uso di Annotation proprietarie che possono affiancare quelle proprie dello standard JPA, la disponibilità di cinque di-verse possibilità di accesso ai dati, l’uso di tecni-che di caching e la presenza di opzioni specifiche per il supporto alle applicazioni Web fanno di Hi-bernate un prodotto sofisticato, che richiede, per poter essere sfruttato appieno, un certo studio.

• Hibernate ha una flessibilità tale da poter essere utilizzato sia in un contesto in cui si può disegna-re il modello dati partendo dal modello ad ogget-ti, sia in un contesto in cui si deve fare i conti con un modello dati preesistente. Lo scenario ideale per l’impiego di Hibernate è comunque quello in cui un articolato Domain Model, ricco di classi e di associazioni tra classi, deve essere reso persi-stente in totale indipendenza rispetto al database utilizzato, al contesto tecnologico (sistema opera-tivo, network, ecc.) e all’interfaccia di accesso ai dati (Web classico, RIA, Swing o nuovi ambienti come Flex, Silverlight o JavaFX). Per semplici ap-plicazioni, dove non vi è necessità di supportare diversi database e dove si deve gestire una man-ciata di classi persistenti, è probabile che Hiber-nate rappresenti un mezzo suicidio e che una so-luzione basata su JDBC possa risultare più ade-guata.

Introduzione a Hibernate

Page 9: j2007 03 jj4

JAVA Journal

8 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 9

Object/Relational Mapping speciale

La soluzione Hibernate al problema del mapping O/R

Hibernate è un tool open source per il mapping object/relational il cui intendimento è garantire agli utilizzatori benefici in termini di produttività, manutenibilità, presta-zioni e indipendenza dal produttore del RDBMS. Hibernate è nato dallo sforzo di Gavin King, ben presto supportato da Christian Bauer e da altri sviluppatori. Nel 2005 JBoss ha acquisito i diritti su Hibernate ed ha ingag-giato i principali membri del gruppo di lavoro. Oggi Hiber-nate, in seguito all’acquisizione da parte di JBoss, fa par-te dell’offerta di RedHat, anche se il gruppo di sviluppo ha mantenuto una totale indipendenza in termini di licen-cing, disponibilità e supporto.Hibernate si posiziona al top dell’offerta nell’ambito degli strumenti per la gestione della Java Persistence. Il gruppo di sviluppo Hibernate ha partecipato alla definizione dello standard EJB 3.0 influenzandone in modo evidente le scel-te, pur mantenendo soluzioni di mapping e di tuning pro-prietarie che permettono un superamento dei limiti impo-sti dalla stretta aderenza agli standard JPA.Hibernate è nato come tool Java, ma ne è stata sviluppa-ta una versione per l’ambiente .NET, denominata NHiber-nate. La release 1.2 di NHibernate, disponibile dai primi di Maggio del 2007, comprende caratteristiche che attestano NHibernate molto vicino ad Hibernate per Java.

Configurare un’applicazione basata su Hibernate

La configurazione di un’applicazione in cui si vuole utiliz-zare Hibernate è piuttosto semplice. Il classpath dell’appli-cazione deve includere una serie di file jar, tra cui i prin-cipali inclusi nei package Hibernate Core e Hibernate Annota-tions scaricabili dal sito Hibernate, che sono:

• hibernate3.jar• hibernate-annotations.jar• ejb3-persistence.jar• hibernate-commons-annotations.jar

Oltre ai jar principali, è necessario che il classpath com-prenda anche una serie di dipendenze, che sono:

• antlr.jar• asm.jar • asm-attrs.jar • c3p0.jar• cglib.jar • commons-collections.jar • commons-logging.jar• dom4j.jar • jta.jar

Tutti i jar citati sono reperibili nella directory lib di Hiber-nate Core.

Se si utilizza l’IDE Eclipse è conveniente scaricare ed in-stallare anche il plugin compreso in Hibernate Tools. Una volta impostato il classpath è necessario che in corrispon-denza della root della propria applicazione sia definito un

file di configurazione dal nome hibernate.cfg.xml. La confi-gurazione riportata qui di seguito è la più semplice possi-bile:

<hibernate-configuration> <session-factory> <property name=”hibernate.connection.driver_ class”>com.mysql.jdbc.Driver</property> <property name=”hibernate.connection.url”> jdbc:mysql://localhost/jjhtut</property> <property name=”hibernate.connection.username”> myname</property> <property name=”hibernate.connection.password”> mypass</property> <property name=”dialect”>org.hibernate.dialect. MySQLDialect</property> <!-- Mapped classes --> <mapping class=”org.jjh.Person”/> <mapping class=”org.jjh.Organization”/> … </session-factory></hibernate-configuration>

In altre parole, la precedente configurazione dichiara che:

• per la connessione è utilizzato il driver JDBC MySql• il database a cui si è connessi è sotto localhost e si chia-

ma jjhtut• le credenziali di accesso sono myname con password

mypass• il dialetto da utilizzare nella creazione delle istruzioni

SQL è quello di MySql• le classi Java mappate sul database sono org.jjh.Person e

org.jjh.Organization

Il file di configurazione può essere arricchito di diversi altri parametri. Interessanti, tra gli altri, sono quelli che permettono di creare o aggiornare automaticamente il da-tabase sulla base del mapping; quelli che permettono di visualizzare in console il codice SQL generato automati-camente da Hibernate quando esegue i comandi; e quelli destinati alla configurazione di pool di connessioni JDBC e

Hibernate è un tool

open source per il

mapping

object/relational

Page 10: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200710

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 11

Object/Relational Mapping speciale

della cache. Terminato il setup di base, si può cominciare a definire il mapping.

Uso delle Annotation per la mappatura del modello a classi su un DB relazionale

Hibernate, nei suoi primi anni di vita, ha utilizzato un me-todo di mapping basato su file di configurazione XML. Questo metodo, peraltro tuttora pienamente supportato, è stato affiancato, a partire dalla disponibilità di Java 5, dal mapping basato su Annotations. Le Annotation utilizza-te da Hibernate sono quelle definite all’interno dello stan-dard JSR 220 (Java Persistence API, o JPA) arricchite da una serie di Annotation proprietarie, che sono spesso uti-li, se non indispensabili, per ottenere il massimo dal pro-prio database.Chi volesse rimanere aderente allo standard JPA dovreb-be limitarsi ad usare le Annotation standard; ma il no-stro consiglio, se si vuole sfruttare appieno Hibernate, è di studiare con attenzione anche le estensioni, anche per-ché è probabile che presto entrino a far parte dello stan-dard stesso.Poiché in questo “speciale ORM” vi è un articolo specifi-camente dedicato allo standard JPA, non ripeteremo qui la spiegazione del significato di Annotation come @Enti-ty, @Id, @Column e via dicendo, perfettamente corrispon-denti a quanto previsto dallo standard.Nel codice che segue, in ogni caso, si può vedere un sempli-cissimo mapping Hibernate definito tramite Annotation.

@Entitypublic class Flight implements Serializable { Long id; String destination;

@Id public Long getId() { return id; } public void setId(Long id) { this.id = id; }

@Column(length=50) Public getDestination(){Return destination;} Public void setDestination(destination) { this.destination=destination;)}

Ricordiamo invece che un ORM come Hibernate genera automaticamente le istruzioni SQL necessarie per eseguire le letture e le scritture delle classi rese persistenti. Nel co-dice Java, di conseguenza, ci si limiterà ad eseguire sem-plici istruzioni come

get(Class, id)

o

save(object)

mentre la loro trasformazione nelle istruzioni SELECT o UPDATE è delegata ad Hibernate. Per evitare che lo svi-luppatore perda completamente il controllo del codice

SQL che viene generato, molte delle Annotation proprie-tarie sono dedicate ad un tuning che ha, come conseguen-za, la generazione di un SQL più conforme ai desideri del-lo sviluppatore. Questa attività di tuning può riguardare, tra l’altro:

• il contenuto del codice SQL generato e l’opportunità di eseguire o meno le istruzioni di UPDATE in determina-te circostanze;

• il tipo di lock ottimistico da implementare nella gestio-ne degli aggiornamenti;

• l’impiego di speciali istruzioni WHERE nelle letture;• il comportamento “a cascata” nel caso di cancellazione

di una entità “padre” rispetto alle entità associate;• la gestione di indici legati ad una o più proprietà;• l’adozione di codice utente per la persistenza di una en-

tità diverso da quello normalmente adottato da Hiber-nate (ad esempio per utilizzare stored procedure, LDAP o altri approcci);

• l’utilizzo di uno dei generatori di chiavi primarie messi a disposizione da Hibernate nel caso il database utiliz-zato non ne fornisca uno adeguato;

• l’adozione di formule per calcolare valori come se fos-sero campi virtuali;

• l’utilizzo di UserType, cioè di tipi definiti dall’utente che richiedono particolari accorgimenti nel gestire la loro persistenza.

Sono disponibili molte altre Annotation specifiche di Hi-bernate, troppe per essere citate integralmente in questo articolo. La loro presenza permette allo sviluppatore un controllo molto elevato del tool Hibernate, quando ciò è ri-chiesto, evitando la frustrazione tipica di chi si è affidato ad uno strumento nella speranza di guadagnare in sempli-cità e rapidità di sviluppo per poi scoprire di dover subire limitazioni inaccettabili in termini di funzionalità e pre-stazioni.

La gestione delle transazioni

Utilizzando Hibernate, la problematica della gestione delle transazioni può essere affrontata in due modi:

• includere il controllo della transazione all’interno del proprio codice, esplicitando così dove inizia e dove fini-sce una transazione, per quali eccezioni eseguire le ca-tch e per quali rimandare allo strato software superio-re;

• delegare il controllo della transazione ad un container, magari basato su Spring o su EJB3. In questo caso, il proprio codice si limita ad eseguire l’istruzione di ac-cesso al database, mentre il container controlla la tran-sazione e ne gestisce le eccezioni.

In apparenza, il secondo metodo appare più sofisticato: ma non dimentichiamo che esiste una scuola di pensiero per cui il cuore della logica di un’applicazione gestionale sta proprio nel controllo delle transazioni. Per chi è di questa opinione il primo metodo è l’unico da seguire.Hibernate, come tutti gli ORM aderenti allo standard JPA,

Page 11: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200710

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 11

Object/Relational Mapping speciale

permette di implementare un locking ottimistico basato sul versioning o sul timestamp. Nel primo caso Hibernate, ad ogni UPDATE, incrementa automaticamente una pro-prietà numerica identificata dall’Annotation @Version. Nel secondo caso la proprietà è invece di tipo Timestamp e l’ag-giornamento consiste nella memorizzazione dell’istante in cui è avvenuto l’UPDATE.

L’ottimizzazione delle prestazioni

Hibernate è dotato di una ricca serie di opzioni destinate a garantire elevate prestazioni alle applicazioni che lo utiliz-zano per la gestione della persistenza.

La strategia di fetch e la possibilità di tuning della stessa

Una prima serie di opzioni è dedicata alla possibilità di de-finire in dettaglio quando e come un’entità, e le entità ad essa associate, sono lette dal database. Si tratta di un pun-to critico nell’utilizzo di un ORM, in quanto il codice uten-te si limita, tramite un’istruzione

get(Class, id)

o

load(Class, id)

a dichiarare cosa vuole leggere; mentre la traduzione di questa lettura in termini SQL è delegata all’ORM stesso. La criticità emerge in modo prepotente quando la classe target è piena di associazioni ad altre classi, siano esse re-lazioni molti a uno (ManyToOne) sia uno a molti (OneTo-Many). Un cattivo disegno del mapping, in questi casi, può far decadere in modo irrimediabile le prestazioni, facendo rimpiangere una classica soluzione JDBC.Con Hibernate non si corre questo pericolo, in quanto l’uso adeguato delle sue parametrizzazioni, tutte esplicitabili tramite Annotation, permette un forte controllo del codi-ce SQL generato.Nei casi più critici è sempre possibile richiedere che una particolare lettura sia effettuata utilizzando un codice SQL scritto “a mano” o tramite l’utilizzo di una stored proce-dure.

Il caching

Uno dei motivi per cui si possono preferire le soluzio-ni ORM rispetto al semplice uso di JDBC è che le prime permettono di implementare una strategia di caching dei dati, trasparente all’applicazione ma in grado di minimiz-zare l’accesso al database manager. Il caching può essere realizzato a tre livelli:

• Transazionale: riguarda i dati propri della transazione o del gruppo di transazioni (conversation) in corso; l’ac-cesso a questa cache non può essere concorrente;

• Processo: riguarda i dati condivisibili da più transazioni, anche in modo concorrente, ma all’interno di una sin-gola macchina;

• Cluster: riguarda i dati condivisibili tra più transazioni potenzialmente situate su diverse macchine connesse tra loro in rete.

Il caching sfugge alle standardizzazioni JPA o EJB, per cui ogni fornitore di interfacce di persistenza propone la pro-pria soluzione. Hibernate implementa una sofisticata ar-chitettura di caching a due livelli. Il primo livello di ca-ching è predefinito e si occupa del caching transazionale. Il secondo livello di cache è configurabile come cache di pro-cesso o di cluster. Questa cache è “pluggable” (è possibile decidere se e come attivarla), può fare riferimento ad una o più classi persistenti, ed è configurabile in funzione del fatto che ci si aspetti un’attività transazionale più o meno frequente sulla classe messa in cache e del fatto che si vo-glia garantire un livello più o meno alto di “isolamento” agli oggetti presenti in cache. La cache di secondo livello può essere implementata, a scelta dell’utente, usando uno dei vari prodotti supportati da Hibernate (dal più sempli-ce EHCache fino al sofisticato JBoss Cache passando da OSCache e SwarmCache). La configurazione della cache può essere pilotata da apposite Annotation proprietarie di Hibernate, unite, quando necessario, alla configurazione del prodotto utilizzato.Una corretta configurazione della cache, insieme ad una strategia di dimensionamento e di alimentazione preven-tiva della stessa all’avvio dell’applicazione, può condurre a significativi incrementi di performance e di scalabilità di un’applicazione Hibernate, soprattutto in ambito Web.

La flessibilità nella scelta della strategia di accesso ai dati

Hibernate propone un ampio ventaglio di possibilità di ac-cesso ai dati persistenti.

Hibernate si posiziona al top dell’offerta nell’ambito degli strumenti per la

gestione della Java Persistence

Page 12: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200712

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 13

Object/Relational Mapping speciale

HQL e JPA QL

Il primo metodo si chiama HQL (Hibernate Query Langua-ge) che è un’estensione del linguaggio standard JPA deno-minato QL. Una tipica istruzione HQL è del tipo:

from Person as p where p.name=’Marco’

Come si può osservare, vi è una forte somiglianza con SQL, anche se ci si riferisce a classi e proprietà e non a tabelle e campi. Un uso professionale di HQL permette di ottenere tutto ciò che, normalmente, si chiede a SQL, con il vantag-gio di ricevere in output liste di oggetti immediatamente utilizzabili nel proprio codice Java, e non dei semplici Re-sultSet.

Query by Criteria

Capita spesso, che in un applicativo si debba costruire una query “al volo”, sulla base dello stato corrente, in quanto si desidera poter decidere a runtime che cosa ricercare, e sulla base di quali criteri di selezione. Per fare questo si po-trebbe delegare al codice Java la creazione della stringa di ricerca concatenando le stringhe “from”, “where”, “and” e via dicendo, per ottenere un comando adatto alla ricerca che si vuole effettuare. Questo metodo è però scomodo e poco adatto alla programmazione ad oggetti.Per ovviare a questo limite, Hibernate mette a disposizio-ne un’interfaccia Java che permette di definire una query creando degli oggetti di tipo Criteria all’interno dei quali è possibile, sempre in modo dinamico, specificare i dettagli dell’interrogazione da creare.Benché l’uso di questa tecnica sia più raro rispetto all’uso di HQL, la presenza delle Query by Criteria può risultare molto comoda in determinate circostanze.

Query by Example

Le Query by Exemple sono molto simili alle Quey by Crite-ria, ma il dettaglio dell’interrogazione è specificato utiliz-zando delle classi che contengono degli “esempi” dei dati da utilizzare come filtri di ricerca.L’esecuzione della ricerca ritorna, come risultato, gli ogget-ti della stessa classe “compatibili” con l’esempio fornito. È evidente che questa possibilità può essere preziosa nel-le classiche ricerche “libere” dove l’utente deve compilare uno schermo da usare come “template” per un’interroga-zione complessa.

SQL nativo

Vi sono casi, per quanto rari, in cui tutte le possibilità offer-te da Hibernate per il tuning delle query si rivelano insuffi-cienti rispetto all’obiettivo che si vuole ottenere. In questo caso il tool permette di creare una query utilizzando istru-zioni SQL native, anche proprie del dialetto SQL imple-mentato dal DBMS di riferimento.Ovviamente, quando decide di usare SQL nativo, l’utente

si deve far carico del problema della correttezza del codice generato, così come degli eventuali problemi di portabilità su altri database.

Hibernate nelle applicazioni Web

Un’applicazione Web moderna, soprattutto in un conte-sto Java, è normalmente disegnata a più livelli. Il layer più basso, quello della persistenza, è il regno di Hibernate. Il layer Persistenza basato su Hibernate è normalmente com-posto da:

• Un Domain Model adeguatamente annotato• Un DAO base, riutilizzato in più punti dell’applicativo

per i più semplici comandi di lettura e aggiornamento dei dati

• Da DAO specifici, che implementano istruzioni di ricer-ca e gestione per le classi più complesse, che richiedo-no strategie particolari di query o di aggiornamento dei dati.

I DAO (che altro non sono che degli insiemi di metodi per l’accesso al database), siano essi standard o specifici, sono poi utilizzati dallo strato superiore del software, normal-mente denominato “layer Servizi”. Il layer Servizi imple-menta gli “use case” di gestione del database attivati dalla GUI o dalle applicazioni di tipo batch. Uno “use case” di inserimento di un ordine cliente, ad esempio, può essere gestito da una classe di tipo “service” denominata Order-Fulfillment che, a sua volta, utilizza un OrderDAO, un Custo-merDAO, un PaymentDAO, ecc.L’uso di questa architettura permette di concepire, svilup-pare ed implementare dei Domain Model persistenti for-temente indipendenti dal software sottostante (database manager, sistema operativo, rete, ecc.) e da quello sovra-stante (GUI, layer Servizi, ecc.), che siano di facile docu-mentazione e manutenzione.

Il test di applicazioni basate su Hibernate

Il test dello strato di persistenza basato su Hibernate è molto più semplice rispetto a quello che normalmente si progetta per applicazioni non basate su un ORM. L’uso delle Annotation, infatti, rende inutile la verifica della consistenza tra classe Java e tabella usata per la persisten-za. Allo stesso tempo la correttezza del codice SQL utilizza-to per l’accesso al database è garantito da Hibernate stes-so e non richiede ulteriori attenzioni. Il test si concentra quindi, nella maggioranza dei casi, sulla verifica delle pre-stazioni e della scalabilità dell’applicazione, alla ricerca di eventuali problemi risolvibili tramite l’ottimizzazione delle Annotation o la semplificazione del modello.

L’uso di Hibernate con database già configurati (legacy)

Hibernate sviluppa tutta la sua potenza quando si può par-tire da un Domain Model concepito solo in funzione del-

Page 13: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200712

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 13

Object/Relational Mapping speciale

la sua rappresentatività del problema affrontato, senza preoccupazioni legate al data model. Nella realtà, purtroppo, si deve spesso fare i conti con mo-delli dati preesistenti, da utilizzare all’interno della propria applicazione, senza una reale possibilità di cambiamento. Hibernate è in grado di essere utile anche in questa circo-stanza, in quanto il suo sistema di Annotation può descri-vere anche le situazioni più complesse, garantendo il map-ping richiesto tra un database legacy e il proprio modello ad oggetti.

I componenti complementari a Hibernate

Quando si parla di Hibernate, normalmente, si fa riferi-mento al prodotto Hibernate Core insieme a Hibernate Anno-tations. Ma l’offerta è ancora più ricca, e si completa con i seguenti prodotti:

• Hibernate EntityManager. Implementa l’interfaccia di programmazione e le regole del ciclo di vita definite dalle specifiche EJB3. Utilizzando l’EntityManager si può quindi adottare uno standard di programmazione EJB3 anche all’interno di un semplice application con-tainer come Tomcat.

• Hibernate Tools. Si tratta di una serie di tools utilizzabili all’interno di un plugin Eclipse o come co-mandi Ant che facilitano la creazione della configura-zione Hibernate (hibernate.cfg.xml), la visualizzazione dello schema persistente, la creazione e l’aggiornamen-to dello schema del database sulla base delle specifiche di mapping ed altro ancora.

• Hibernate Validator. Fornisce un insieme standard di Annotation utilizzabili per la validazione dei dati, come ad esempio @NotNull, @Email, @CreditCard-Number, @Max, @Range, ecc. L’utilizzo di queste An-notation permette di definire a livello di Domain Mo-del delle regole di validazione che possono poi essere utilizzate in diversi punti dell’applicazione.

• Hibernate Search. Permette di sfruttare la tecnologia Lucene di indicizzazione e di “full text search” all’in-terno del Domain Model persistente. Tramite una serie di Annotation vengono creati e mantenuti gli indici ne-cessari per poter poi eseguire ricerche di tipo free-text in modo ottimizzato all’interno delle proprietà di tipo testo. Poiché viene utilizzato Lucene, l’indicizzazio-ne avviene indifferentemente dal fatto che il databa-se manager fornisca una specifica tecnologia a questo scopo.

• Hibernate Shards. Permette di rendere persistente un Domain Model su più database, anche posizionati su diversi nodi della rete, in modo trasparente all’ap-plicazione.

• JBoss Seam. Seam è un framework che si pone come ponte tra Hibernate e JSF, allo scopo di favorire la scrit-tura di sofisticate applicazioni Web in cui sia possibi-

le progettare l’interfaccia utente in termini di Conver-sation (sequenza di richieste logicamente collegate tra loro). Seam si colloca in un contesto EJB3 arricchen-dolo di funzionalità destinate alla semplificazione della scrittura di GUI Web.

Conclusioni

Al termine di questa prima carrellata, possiamo afferma-re che:

• Hibernate è un prodotto molto ambizioso, in continua crescita in termini di funzionalità e flessibilità che si colloca al vertice delle possibili scelte di un ORM in ambito Java.

• Usando Hibernate e le sue Annotation, sia standard sia proprietarie, possiamo descrivere con semplicità il mapping delle proprie classi senza perdere in termini di potenza e rappresentatività delle situazioni più com-plesse.

• In caso di necessità, Hibernate permette di ripiegare su

un codice SQL scritto “a mano” dal progettista dell’ap-plicazione, anche se, grazie alla sofisticazione delle An-notation proprietarie, si tratta di una caratteristica che ha scarse probabilità di dover essere utilizzata.

• L’utilizzo di Hibernate non solo non comporta perdi-te di prestazioni ma, in un contesto di Domain Model complesso dove è sfruttabile il caching di secondo livel-lo, si possono avere significativi vantaggi rispetto alle soluzioni basati sul semplice JDBC.

• Hibernate apre la strada in modo semplice all’utilizzo di tecnologie avanzate come quelle di full-text search o di clustering multi-database.

Bibliografia e riferimenti

[1] Christian Bauer e Gavin King, “Java Persistence with Hi-bernate”, Manning Publications Co. (2007). È un testo pubblicato da qualche mese al confronto del quale ogni altro libro in circolazione è, al momento, obsoleto op-pure incompleto.

[2] www.hibernate.org - Il sito di Hibernate.

Note Biografiche

Marco Pancotti ha iniziato la sua carriera nel 1982, in una delle maggiori società internazionali di Business Consulting. Dopo aver diretto una società di software ha cominciato, a partire dai primi anni 90, ad operare come consulente direzionale in ambi-to IT. È autore di una metodologia per la certificazione di qua-lità del software basata sull’applicazione della norma ISO 9126 e di un metodo di valutazione della qualità di siti Web orienta-ti all’eBusiness. È membro del Comitato Tecnico OASIS per la definizione dello standard UBL e realizza applicazioni basate sugli standard ebXML/UBL.

Page 14: j2007 03 jj4

JAVA Journal

14 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 15

Object/Relational Mapping speciale

L’utilizzo degli ORM (Object Relational Mapping tool) consente di raggiungere il livello di astrazione desiderato e facilita ulteriormente la gestione dei dati durante il processo di sviluppo.

>> di Roberto Sidoti ([email protected])

Da molti anni ormai, ci si è accorti che le operazioni per interagire con un database sono spesso ripetitive e che quindi il livello di astrazione di JDBC non è quello ottimale. Gli sviluppato-ri Java traggono spesso profitto dal-

l’impiego di framework open source nella loro attivi-tà di sviluppo e design. Molte volte questi framework hanno condizionato anche l’evoluzione del linguag-gio stesso: basti pensare all’influenza che ha avuto Hibernate nella definizione delle Java Persistence API (JPA). Hibernate è sicuramente l’ORM che ha conquistato la leadership in quanto a diffusione ed utilizzo nei progetti Java; però c’è da sottolineare che non è l’unico che ha riscosso successo. Tra i proget-ti open source, che si occupano di rendere la vita più agevole agli sviluppatori quando hanno a che fare con un database relazionale, iBatis è uno di quelli più utilizzati e vanta una curva di apprendimento prati-camente piatta. In questo articolo ne presenteremo le caratteristiche principali e incominceremo a vederlo all’opera basandoci su un esempio pratico.

Perchè scegliere iBatis?

iBatis (Figura 1) è un framework non così evoluto e distante da quello che è l’approccio JDBC. Infatti, al contrario di altri framework, come ad esempio Hi-

bernate, è sempre l’SQL a ricoprire il ruolo principa-le nella gestione dei dati; però molti passaggi impo-sti dalle API JDBC sono stati semplificati ed affidati a file XML di configurazione. Possiamo già immagi-nare che questo approccio soddisfi sia i DBA (che nei progetti di dimensioni medio-grandi possono tenere sotto controllo l’SQL utilizzato) sia gli architetti fun-zionali (che possono contare su API ben disegnate e pensate per ridurre le possibilità di errore degli svi-luppatori). Infatti, chi ha avuto a che fare con JDBC sa benissimo che le operazioni da effettuare sono spesso ripetitive; la gestione dei dati in molti casi si riduce a poche righe di codice, mentre le restanti ope-razioni sono dovute a:

• Gestire le connessioni e le transazioni;

• Estrarre da oggetti Java i parametri per le query SQL;

• Creare i PreparedStatement;

• Convertire i risultati ottenuti dai ResultSet negli oggetti Java appropriati.

Ecco che iBatis ha pensato di minimizzare tali opera-zioni attraverso la definizione di una serie di pattern concentrati in un framework denominato DataMap-per (oppure SqlMapClient). Questo framework, infatti,

iBatis: il più nostalgico degli ORM

Page 15: j2007 03 jj4

JAVA Journal

14 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 15

Object/Relational Mapping speciale

prevede diverse tipologie di gestione delle connessioni al DB nonché il supporto delle più diffuse API per la gestione delle transazioni. I pattern proposti si occupano in modo molto elegante sia del mapping tra i VO (JavaBean) dell’applicazione ed i pa-rametri da utilizzare nei PreparedStatement, sia del processo inverso, ossia del mapping tra i ResultSet e gli oggetti Java. La base dell’utilizzo del DataMapper è costituita dall’impie-go di uno o più file XML che contengono le query SQL che si vogliono eseguire, ed i mapping appena discussi.

Full immersion

Definiamo un’applicazione d’esempio che ci aiuterà a ca-pire le caratteristiche principali di questo tool. Data la na-tura didattica dell’esempio, le soluzioni proposte si presta-no senza dubbio a migliorie ed integrazioni. Supponiamo di dover gestire la collocazione dei farmaci all’interno di uno o più scaffali. Avremo, quindi, essenzialmente a che fare con le entità farmaco e con le relative posizioni occu-pate all’interno degli scaffali. Una posizione ha le seguen-ti proprietà:

public class PosizioneVO { private String id=null; private String nomeScaffale=null; private int piano=0; private int colonna=0;

… // getter e setter}

In particolare l’id sarà la chiave primaria della tabella, mentre il campo nomeScaffale rappresenta il nome/etichetta dello scaffale; infine piano e colonna servono a definire la posizione del farmaco nello scaffale. Invece, possiamo de-finire una modellazione del farmaco rappresentata dalla seguente classe Java:

public class FarmacoVO { private String id=null; private String nome=null; private String descrizione=null; private int quantita=0; private PosizioneVO posizione=null; … // getter e setter}

Come prima, l’id sarà la chiave primaria della corrispon-dente tabella del DB; il nome rappresenta il nome del far-maco, il campo quantità memorizza le unità presenti. Il campo posizione serve a memorizzare la posizione in cui è possibile reperire il farmaco. Ora che sappiamo quali dati dobbiamo gestire nell’applicazione, incominciamo a vede-re come funziona iBatis. Per prima cosa serve un file XML che definisca la gestione della connessione, delle transa-zioni e di tutti gli aspetti di configurazione per un utilizzo efficiente del DB:

FIGURA 1 Il sito ibatis.apache.org

Page 16: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200716

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 17

Object/Relational Mapping speciale

<sqlMapConfig> <settings useStatementNamespaces=”true” />

<transactionManager type=”JDBC”> <dataSource type=”SIMPLE”> <property name=”JDBC.Driver” value=”org. hsqldb.jdbcDriver”/> <property name=”JDBC.ConnectionURL” value=”jdbc:hsqldb:file:/roby/private/software/dev/java/iBatisCafe/data/ iBatisCafe”/> <property name=”JDBC.Username” value=”sa”/> <property name=”JDBC.Password” value=””/> <property name=”JDBC.DefaultAutoCommit” value=”true” /> </dataSource> </transactionManager>

<sqlMap resource=”posizione.xml”/> <sqlMap resource=”farmaco.xml”/>

</sqlMapConfig> All’interno del tag sqlMapConfig sono definite tre sezioni: settings, transactionManager e sqlMap. La prima prevede la di-chiarazione di un insieme di attributi opzionali che servo-no ad ottimizzare l’oggetto sqlMap che si istanzierà da codi-ce Java. La semantica dell’attributo useStatementNamespaces sarà chiarita successivamente. Il tag transactionManager ser-ve per la configurazione del gestore delle transazioni. L’at-tributo type specifica quale tipo gestore si vuole utilizzare; lo si può valorizzare o con il nome di una classe (utile per eventuali personalizzazioni del framework) o con tre alias: JDBC, JTA o EXTERNAL. Il primo specifica che le transa-zioni sono gestite direttamente con le primitive messe a disposizione da JDBC. Il secondo permette di agganciarsi alle Java Transaction API di Sun, l’ultimo valore può essere utilizzato quando si vuole affidare la gestione delle transa-zioni ad un layer esterno a iBatis.Il tag dataSource, e tutti i tag da esso contenuti, servono a definire la gestione delle connessioni al DB e quindi il tipo di connection pool da utilizzare. Il framework mette a dispo-sizione tre valori da poter assegnare all’attributo type:

• SIMPLE specifica che sarà utilizzata una soluzione pro-prietaria ed è la soluzione ideale quando iBatis non è abbinato a nessun container J2EE;

• DBCP consente di sfruttare l’omonima libreria open source di Apache;

• JNDI permette di agganciarsi tramite JNDI alla gestio-ne delle connessioni messe a disposizione da un con-tainer esterno.

È importante notare che la proprietà JDBC.DefaultAutoCommit valorizzata a true evita la gestione da codice delle transazio-ni; pertanto tutte le operazioni di scrittura sul DB saranno oggetto di commit automatico da parte del framework.

La sezione sqlMap definisce un elenco di file XML in cui sono contenute le query SQL ed i mapping ad esse asso-ciati. Nel nostro caso sono stati specificati due file, ognu-no abbinato alla gestione di uno dei JavaBean precedente-mente definiti.

File di mapping

I file di mapping vengono caricati dal framework in base all’ordine definito nel file di configurazione, che abbiamo chiamato SqlmapConfig.xml. Essenzialmente, contengono le query SQL utilizzate per scrivere e leggere i dati; ogni query è etichettata con una stringa il cui valore può essere uti-lizzato all’interno del codice Java per invocare l’enunciato SQL in questione. Il loro utilizzo non è tutto qui: infatti, si occupano sia di mappare gli oggetti Java sui parametri dei PreparedStatement utilizzati, sia di trasformare i ResultSet in oggetti che modellano il dominio dell’applicazione.

<sqlMap namespace=”posizione”>

<select id=”read” parameterClass=”java.lang. String” resultClass=”cafe.farma.data.vo. PosizioneVO”> select * from posizione where id=#value# order by nomescaffale </select>

<insert id=”create” parameterClass=”cafe. farma.data.vo.PosizioneVO”>

insert into posizione(id,nomescaffale, piano,colonna)values(#id#,#nomeScaffale#,#piano#,

#colonna#) </insert>

<update id=”update” parameterClass=”cafe. farma.data.vo.PosizioneVO”> update posizione set nomescaffale=#nomeScaffale#, piano=#piano#, colonna=#colonna# where id=#id# </update>

<delete id=”delete” parameterClass=”java.lang. String”> delete from posizione where id=#id# </delete>

<select id=”list” parameterClass=”cafe.farma. data.vo.PosizioneVO” resultClass=”cafe.farma.data.vo. PosizioneVO”> select * from posizione where nomescaffale like #nomeScaffale# and piano=#piano# and colonna=#colonna# </select>

</sqlMap>

Page 17: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200716

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 17

Object/Relational Mapping speciale

La semantica dei vari tag XML è molto intuitiva: il tag sql-Map prevede un attributo namespace; esso, insieme ai va-lori degli attributi id dei tag contenuti, compone la stringa con cui è possibile referenziare da codice i diversi enun-ciati SQL. Il tag select prepara il framework all’esecuzio-ne dell’omonimo comando SQL; in particolare parameter-Class definisce il tipo dell’oggetto passato come parametro alla query. Lo stesso valore è mappato dalla stringa #va-lue# nella query contenuta nel tag. #value# è un partico-lare mapping utilizzato per tutti gli oggetti istanze di classi contenute nel package java.lang. Invece, osservando il tag update possiamo notare che gli oggetti, il cui valore dell’at-tributo parameterClass non è una classe di java.lang, abbia-no una forma di mapping diversa. Infatti, nella query di update è possibile far riferimento a tutti i campi dell’ogget-to secondo la sintassi #<campo-Getter>#, dove <campo-Getter> indica il campo dell’oggetto deducibile con il corri-spondente getter. Nei tag select si rende necessario l’utiliz-zo dell’attributo resultClass; esso definisce il mapping tra il ResultSet risultato della Select e gli oggetti che si desidera avere come output.

Mapping avanzato

Il file farmaco.xml presenta qualche difficoltà in più, in quanto l’oggetto FarmacoVO contiene un oggetto istanza di PosizioneVO. Per semplicità, prenderemo in esame solo le operazioni di create e read.

<insert id=”create” parameterMap=”farmacoINS”> insert into farmaco(id,nome,descrizione, quantita,posizione_id) values (?,?,?,?,?)</insert>

Il parametro passato come input all’enunciato insert non è più una classe Java definita da un attributo parameter-Class, ma, come possiamo notare, è definito dall’attribu-to parameterMap. Quest’ultimo deve essere definito prima del suo utilizzo.

<parameterMap id=”farmacoINS” class=”cafe.farma. data.vo.FarmacoVO”> <parameter property=”id” /> <parameter property=”nome” /> <parameter property=”descrizione” /> <parameter property=”quantita” /> <parameter property=”posizione.id” /></parameterMap>

L’attributo id definisce la stringa con cui il parameterMap è referenziabile all’interno del file farmaco.xml. I tag pa-rameter definiscono il mapping e l’ordine con cui vengo-no riprodotte le proprietà dell’oggetto in questione nel-l’enunciato SQL che lo utilizza; in particolare, queste proprietà andranno a sostituirsi ai “?”. Vediamo adesso come iBatis si comporta per l’operazione inversa, ossia come mappa oggetti composti a partire da un ResultSet avuto come risultato di una Select.

<resultMap id=”farmacoRM” class=”cafe.farma.data. vo.FarmacoVO”> <result property=”id” column=”farmaco_id”/> <result property=”nome” column=”farmaco_nome”/> <result property=”descrizione” column=”farmaco_ descrizione”/> <result property=”quantita” column=”farmaco_ quantita”/> <result property=”posizione.id” column=”posizione_id”/> <result property=”posizione.nomeScaffale” column=”posizione_nomescaffale”/> <result property=”posizione.colonna” column=”posizione_colonna”/> <result property=”posizione.piano” column=”posizione_piano”/></resultMap>

<select id=”read” parameterClass=”java.lang. String” resultMap=”farmacoRM”> select farmaco.id as farmaco_id, farmaco.nome as farmaco_nome, farmaco.descrizione as farmaco_ descrizione, farmaco.quantita as farmaco_quantita, posizione.id as posizione_id, posizione.nomescaffale as posizione_ nomescaffale, posizione.colonna as posizione_colonna, posizione.piano as posizione_piano, from farmaco,posizione where farmaco.id=#value# and farmaco.posizione_id=posizione.id order by nome

FIGURA 2 Il progetto visto da Eclipse

Page 18: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200718

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 19

Object/Relational Mapping speciale

</select>

Il tag select specifica la query SQL da utilizzare per la lettura di un farmaco, utilizzando come parametro di input l’id. La novità è rappresentata dal resultMap che definisce la moda-lità con cui mappare il risultato della ricerca. Infatti il tag resultMap introduce, per mezzo dei tag result, una lista di coppie di attributi (property, column) che servono a trasfor-mare le colonne risultato della ricerca nelle proprietà del-l’oggetto istanziato (Figura 2).

Ancora DAO

Supponiamo di voler manipolare i dati per mezzo di classi che definiscono dei DAO (Data Access Object) ad essi as-sociati. Prima, però, è obbligatoria una precisazione: iBatis contiene già delle API per la definizione dei DAO; nell’ulti-ma versione se ne sconsiglia l’uso e si consiglia di utilizzare quelle fornite dal Framework Spring che prevede delle API per iBatis molto curate ed efficienti. Quindi, l’implementa-zione proposta di seguito serve solo a dare un taglio pratico e didattico alla presentazione delle API di iBatis. Incominciamo a definire una super classe per i nostri DAO:

public abstract class BaseIBatisDAO { private static SqlMapClient sqlMap=null; protected SqlMapClient sqlMap(){ return sqlMap; }

public BaseIBatisDAO() throws Exception{ if(sqlMap==null){ Reader reader; reader = Resources.getResourceAsReader (“SqlMapConfig.xml”); sqlMap = SqlMapClientBuilder. buildSqlMapClient(reader); } }}

Questa superclasse serve ad istanziare un oggetto Sql-MapClient e a metterlo a disposizione delle sue sottoclassi. Questo oggetto viene costruito a partire da un java.io.Reader ottenuto utilizzando il file SqlMapConfig.xml analizzato in precedenza. Prendiamo in esame uno dei due DAO di cui dovrebbe es-sere fornita la nostra applicazione; dal punto di vista didat-tico ne basta uno, perché l’implementazione dei due DAO è pressoché identica.

public class PosizioneDAO extends BaseIBatisDAO{ public PosizioneDAO() throws Exception { super(); } public void create(PosizioneVO vo) throws SQLException{ this.sqlMap().insert(“posizione.create”, vo); }

public PosizioneVO read(String id) throws SQLException{ PosizioneVO vo =null; vo =(PosizioneVO)this.sqlMap(). queryForObject(“posizione.read”,id); return vo; } public void update(PosizioneVO vo) throws SQLException{ this.sqlMap().update(“posizione.update”, vo); } public void delete(PosizioneVO vo) throws SQLException{ this.sqlMap().delete(“posizione.delete”, vo.getId()); } public ArrayList<PosizioneVO> list(PosizioneVO vo) throws SQLException{ ArrayList<PosizioneVO> list=null; list=(ArrayList<PosizioneVO>) this.sqlMap() .queryForList(“posizione.list” , vo); return list; }}

In questo frammento di codice possiamo notare la facilità di utilizzo delle API di iBatis. È sufficiente utilizzare uno dei metodi messi a disposizione dalla classe SqlMapClient, comporre la stringa che individua la query nel file di map-ping ed il gioco è fatto. Questa classe è ricca di metodi utilizzabili per eseguire i vari tipi di query SQL. Nell’esem-pio, possiamo trovare i metodi insert, update, delete, queryFo-rObject e queryForList. Tralasciando i primi tre, che specifi-cano l’utilizzo degli omonimi enunciati SQL, gli ultimi due introducono l’utilizzo di una Select SQL. Il primo dei due specifica che il risultato della Select deve essere un solo og-getto; mentre il metodo queryForList specifica che il risulta-to della query definita nel file XML può ritornare una lista di oggetti.

iBatis e le transazioni

Finora non abbiamo visto all’opera le API di iBatis che si occupano di gestire le transazioni; infatti, nel caso della classe PosizioneDAO non compare mai l’invocazione di pri-mitive di commit e rollback. Tutto ciò è dovuto al fatto che in fase di configurazione nel file SqlMapConfig.xml abbiamo specificato l’auto commit delle operazioni su DB:

<property name=”JDBC.DefaultAutoCommit” value=”true” />

Supponiamo adesso di voler gestire a mano le transazioni: questa situazione è molto ricorrente nei casi reali in cui si vuole racchiudere sotto un’unica transazione non più sin-gole operazioni su DB, ma sequenze articolate e complesse di transazioni. La prima cosa da fare è di impostare a fal-se la proprietà JDBC.DefaultAutoCommit. Fatto ciò, vediamo come potrebbe presentarsi un metodo che prevede l’inse-

Page 19: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200718

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 19

Object/Relational Mapping speciale

rimento di due oggetti di tipo PosizioneVO garantendone la transazionalità.

public void create(PosizioneVO vo1,PosizioneVO vo2) throws SQLException { try { this.sqlMap().startTransaction(); this.sqlMap().insert(“posizione.create”,vo1); this.sqlMap().insert(“posizione.create”,vo2); this.sqlMap().commitTransaction(); }finally{ this.sqlMap().endTransaction(); }}

Anche in questo iBatis si distingue per la sua semplicità; con startTransaction si demarca l’inizio di una transazione, poi con commitTransaction si effettua il commit delle opera-zioni effettuate sul DB. Comunque, alla fine va chiusa la transazione con endTransaction; nel caso qualcosa non ab-bia funzionato le operazioni di rollback sono effettuate au-tomaticamente dal framework.

Conclusioni

In questo articolo abbiamo visto i principi di utilizzo di iBa-tis e abbiamo abbozzato un esempio pratico per render-ci conto della potenza e della facilità di utilizzo di questo framework. Ovviamente non tutte le funzionalità di iBatis non sono state snocciolate in questo articolo. Alcuni aspet-ti come il caching, il “lazyloading” e la possibilità di ese-guire query dinamiche non sono stati presi in considera-zione, ma tuttavia concorrono a fare di questo framework uno strumento semplice e potente per l’interazione con basi di dati relazionali.

Note Biografiche

Roberto Sidoti è Ingegnere Informatico, in passato si è occupato di servizi VoIP; attualmente lavora come Functional Designer per Herzum Software, una multinazionale di consulenza spe-cializzata nello sviluppo di componenti SOA per applicazioni Enterprise.

Page 20: j2007 03 jj4

JAVA Journal

20 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 21

Object/Relational Mapping speciale

Sun Microsystems ha eseguito una radicale rivisitazione della tecnologia di persistenza dei dati e la nuova specifica, JPA, è una chiara semplificazione che si immette nel solco tracciato dalle soluzioni per la persistenza più diffuse, tra cui Hibernate, TopLink della Oracle e JDO.

>> di Fabio Staro ([email protected])

Gli Entity Bean 2.x sono stati la tecno-logia “ufficiale” in ambito Java EE per la persistenza dei dati. Tuttavia la complessità presente nello svilup-po e nel deployment ha fatto prefe-rire a questi alternative più sempli-

ci, flessibili e performanti. Nel precedente numero di Java Journal abbiamo introdotto la specifica degli EJB versione 3.0, e in particolare ci siamo soffermati sugli EJB di tipo session stateless. Abbiamo evidenziato come per i nuovi EJB la Sun abbia eseguito una rein-gegnerizzazione della tecnologia, apportando sì nuo-ve caratteristiche, ma soprattutto introducendo una notevole semplificazione. In questo articolo ci soffermeremo sui nuovi entity bean, evidenziando la radicale differenza architettu-rale presente tra gli entity 3.0 e le precedenti versioni 2.x e 1.x. Se fino alla versione 2.1 gli entity bean sono a tutti gli effetti degli EJB legati necessariamente ad un container EJB, i nuovi entity, descritti nella spe-

cifica JPA per la persistenza e l’object relational map-ping, sono classi Java alle quali può essere associato un contesto di persistenza sia in un ambiente managed, ossia gestito da un Application Server, sia in un am-biente non managed, ossia Java standard, senza al-cun Application Server. Dalla specifica JPA leggiamo esplicitamente:

“This document is the specification of the Java API for the management of persistence and object/relational mapping with Java EE and Java SE”.

Questa differenza architetturale caratterizza i nuo-vi entità, oltre ad una notevole semplificazione nella programmazione e nel deployment e a nuove carat-teristiche. In questo primo articolo su JPA definiamo una entity class, il concetto del contesto di persistenza e la gestione delle relazioni. Nel prossimo articolo appro-fondiremo la gestione dell’ereditarietà ed il supporto alle query statiche e dinamiche. Prima di iniziare, os-serviamo che JPA è una specifica, e pertanto posso-no esistere diversi provider che la implementano. Tra questi i più noti sono Hibernate e TopLink.

Una semplice biblioteca

L’applicazione software che desideriamo realizzare è volutamente semplice, al fine di approfondire l’API e l’architettura JPA, eliminando qualsiasi complessità applicativa legata ad un particolare dominio di inte-resse. La Figura 1 riporta il diagramma Entità-Rela-zioni (ER) di un semplice repository per i libri di una biblioteca.

JPA: Java Persistence APIprima parte

JPA è una specifica, e pertanto possono

esistere diversi provider che la implementano

Page 21: j2007 03 jj4

JAVA Journal

20 n.4 - settembre/ottobre 2007

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 21

Object/Relational Mapping speciale

Osservando la figura, possiamo notare che le entità princi-pali nel diagramma sono quattro:

• la tabella CASA_EDITRICE, • la tabella INDIRIZZO, • la tabella LIBRO, • la tabella AUTORE.

Le relazioni che intercorrono tra le entità sono le seguen-ti:

• una casa editrice ha un solo indirizzo (relazione 1 a 1) e può, a sua volta, pubblicare molti libri (relazione 1 a molti);

• un libro a sua volta appartiene ad una e una sola casa editrice (relazione molti a uno), e può essere stato scritto da vari autori

; • un autore, a sua volta, può scrivere diversi libri (rela-

zione molti a molti).

Attraverso un processo di realizzazione del tipo bottom-up, ossia partendo dal disegno del database e derivando da questo il modello delle classi, è possibile modellare le enti-tà di dominio ottenendo il diagramma delle classi riporta-to in Figura 2. Le classi mostrate nella Figura 2 non sono, ovviamente, le uniche classi dell’applicazione, ma rappre-sentano le classi del modello dati e sono in definitiva le en-tità che devono essere rese persistenti nel database. Le operazioni di business dell’applicazione sono modellate attraverso degli EJB 3.0 di tipo session stateless. L’esempio ri-portato è stato verificato con l’application server JBoss ver-

sione 5.0 [1], con il database MySQL versione 5.0.27 [2] e con il provider JPA Hibernate [3].

Definizione di un entity

Un entity, nella accezione della specifica JPA, è un POJO (acronimo di Plain Old Java Object), ossia è una semplice classe Java (che non deve implementare interfacce parti-colari o estendere classi di un particolare framework) i cui attributi mappano le colonne di una tabella e, in partico-lare, una istanza della classe rappresenta un ben preciso record di una tabella (questo perché una classe entity deve dichiarare una primary key). Il mapping tra la classe entity e una tabella è semplificato attraverso l’uso delle annotazioni. Lo stralcio di codice che segue mostra la classe CasaEditrice opportunamente annotata:

@Entity(name=”CasaEditriceEntity”)@Table(name=”CASA_EDITRICE”)public class CasaEditrice implements Serializable { … @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name=”id_ce”) private int identificativo; private String ragioneSociale; private String telefono; private String fax; private String email; …}

FIGURA 1 Diagramma Entità Relazioni

Page 22: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200722

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 23

Object/Relational Mapping speciale

Osserviamo in dettaglio il codice riportato. Attraverso l’an-notazione @Entity, presente nel package javax.persistence informiamo il provider dei servizi JPA che la classe CasaE-ditrice è una classe entity. L’attributo facoltativo name con-sente di specificare un nome attraverso il quale è possibile referenziare la classe entity nelle query. Se l’attributo name non è specificato assume il valore di default, che è il nome non qualificato della classe. Attraverso l’annotazione @Table possiamo informare il provider dei servizi JPA su quale tabella presente nel data-base relazionale è mappata dalla entity class (notiamo che è possibile specificare oltre all’attributo name, anche gli attri-buti schema e catalog per meglio “identificare” la tabella). L’annotazione @Column consente di mappare un attribu-to della classe su una colonna della tabella. Nel codice pre-cedente l’attributo identificativo della classe CasaEditrice è mappato sulla colonna id_ce della tabella CASA_EDITRI-CE. È importante sottolineare che se non avessimo specifi-cato la annotazione @Column, come è stato fatto ad esem-pio per gli attributi ragioneSociale, telefono, fax ed email, si ha la mappatura automatica dell’attributo di classe su una co-lonna omonima della tabella (un esempio di configuration by exception). In effetti, per indicare al provider dei servizi JPA che un attributo di una entity class non deve essere reso persistente questo deve essere annotato con l’annotazione @Transient.Precedentemente abbiamo evidenziato come una istanza di una entity class rappresenti un preciso record di una ta-

bella. Pertanto una entity class deve avere una primary key. Nel codice della classe CasaEditrice l’attributo identificativo è la chiave primaria dichiarata ed è identificata attraverso l’annotazione @Id. In casi complessi, la chiave primaria di una entity class può essere un intero oggetto. JPA attraverso l’annotazione @IdClass consente di dichiarare una classe come chiave primaria. L’ultima annotazione nel codice precedente è l’annotazio-ne @GeneratedValue. Attraverso questa annotazione è pos-sibile definire la regola di generazione per una chiave pri-maria. Per esempio, avendo scritto:

strategy=GenerationType.AUTO

il provider JPA assume che la regola di generazione del va-lore della chiave primaria dipenda dal database utilizzato. Ad esempio, con il database MySQL una strategia di ge-nerazione impostata al valore AUTO indica che la colonna sulla tabella è del tipo AUTO_INCREMENT. Altri possibili valori presenti nella enumerazione GenerationType sono:

• SEQUENCE, • IDENTITY, • TABLE.

I valori SEQUENCE e IDENTITY indicano l’uso di una se-quence nel database o di una colonna identità come stra-tegia di generazione della chiave primaria, mentre il valo-

FIGURA 2 Il diagramma delle classi

Page 23: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200722

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 23

Object/Relational Mapping speciale

re TABLE indica che il provider JPA deve assegnare valori univoci usando una tabella del database.

Il Persistence Context

La logica di business della applicazione di esempio è mo-dellata attraverso EJB 3.0 di tipo session stateless. Per esem-pio, l’EJB GestoreCasaEditriceBean ha una serie di metodi per la gestione di una casa editrice. Di seguito riportiamo uno stralcio del codice:

@Stateless (name=”CasaEditrice”)@TransactionManagement(TransactionManagementType. CONTAINER)public class GestoreCasaEditriceBean implements GestoreCasaEditrice { … @PersistenceContext(type=PersistenceContext- Type.TRANSACTION,unitName=”GestioneBiblioteca”) private EntityManager manager = null; public boolean inserisci(CasaEditrice ce) { try { manager.persist(ce); } catch(Exception e) { return false; } return true; } public CasaEditrice getCasaEditrice(int identificativo) { return manager.find(CasaEditrice.class, identificativo); } …}

Osservando il codice sopra riportato osserviamo che le ope-razioni di persist() (di fatto una operazione di insert sul da-tabase) e di find() (operazione di ricerca) sono invocate su un oggetto EntityManager iniettato nel bean GestoreCasaE-ditriceBean dal container EJB. L’annotazione @Persistence-Context consente di dichiarare il contesto di persistenza (si veda anche più avanti dove parliamo del deployment del-l’applicazione). Il contesto di persistenza è la connessione tra le istanze delle entity class che risiedono in memoria e il database sottostante, ed è gestito attraverso una nuova API, l’interfaccia EntityManager sempre presente nel packa-ge javax.persistence. Attraverso il metodo persist() aggiungiamo una istanza di una entity class al persistence context e da quel momento in poi tutte le modifiche che avvengono sullo stato della entity class sono schedulate per la sincronizzazione sul database,

sincronizzazione che avviene al commit della transazione. In effetti è possibile affermare che l’istanza della entity class è nello stato managed (più avanti dettaglieremo maggior-mente il ciclo di vita di una entity class). L’istanza rimane nello stato managed fino a quando non termina il persisten-ce context o fino a quando l’istanza non è esplicitamente ri-mossa.Il persistence context associato ad un EntityManager può es-sere di due tipi (dichiarati nella enumerazione Persitence-ContextType):

• TRANSACTION;• EXTENDED;

Un persistence context di tipo TRANSACTION termina quan-do si conclude la transazione all’interno della quale sono eseguite le operazioni. Da quel momento in poi tutte le istanze delle entity class non sono più nello stato managed, e pertanto non vi è sincronizzazione tra le modifiche che avvengono sulla istanza in memoria ed il database. Un per-sistence context di tipo EXTENDED termina quando viene ri-mossa dal container l’istanza dell’EJB di tipo stateful all’in-terno della quale è dichiarato. Le istanze delle entity class, in tale contesto, rimangono nello stato managed durante le in-vocazioni successive dei metodi di uno stateful session EJB.

Ciclo di vita di un entity

Il diagramma degli stati riportato in Figura 3 sintetizza il ciclo di vita di un entity. L’Entity Manager distingue quattro diversi stati durante la vita di un entity:

• New;• Managed;• Detached;• Removed.

Quando viene creata, una istanza della classe entity si tro-va nello stato new, ossia l’istanza è presente in memoria ma non è associata ad un contesto di persistenza. Pertanto, le variazioni dei valori degli attributi dell’istanza non sono sincronizzate con il database. Un entity nello stato new, dopo l’invocazione sull’Entity Manager di una operazione di persist(), transita nello stato managed e diviene associata ad un contesto di persistenza, avendo una ben precisa identi-tà di persistenza determinata dalla corrispondente chiave primaria. In questo stato, le variazioni dei valori degli attri-buti dell’istanza sono sincronizzate con il database quando la transazione è sottoposta al commit o quando il processo di sincronizzazione viene richiesto direttamente attraver-so il comando flush(). Un’istanza nello stato managed tran-sita nello stato detached quando termina il contesto di persi-stenza. Nello stato detached l’istanza ha ancora una identità di persistenza ma, non essendo più associata con un contesto di persistenza, non sincronizza variazioni dei suoi attributi con il database. Infine, una istanza della entity class, a fron-te di una operazione di remove(), transita dallo stato ma-naged allo stato removed. In questo stato l’istanza è ancora associata ad un contesto di persistenza, ma viene schedulata un’operazione di cancellazione sul database per il record

Page 24: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200724

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 25

Object/Relational Mapping speciale

da questa rappresentato.

Di seguito riportiamo i metodi principali presenti nell’in-terfaccia dell’Entity Manager, direttamente inerenti al ci-clo di vita di un entity:

public interface EntityManager { … // Fa transitare un’istanza nello stato managed e persistente public void persist(Object entity);

// Esegue il merge dello stato di un entity in un contesto di persistenza.

public <T> T merge(T entity);

// Rimuove un’istanza dal database public void remove(Object entity); // Controlla se un dato entity è presente nel

contesto di persistenza corrente public boolean contains(Object entity); …}

La gestione delle relazioni

Il supporto per la gestione delle relazioni è presente fin dalla specifica 2.0 degli EJB di tipo Entity. Con gli EJB 3.0 la gestione delle relazioni è stata notevolmente semplifica-ta attraverso l’uso delle annotazioni. I tipi di relazione che è possibile modellare tra le entity class sono:

• Uno a uno: la relazione indica che vi è esattamente un

solo record in relazione con un altro record. Nel model-lo dei dati dell’esempio è la relazione che esiste tra una casa editrice e il suo indirizzo;

• Uno a molti: la relazione indica che un particolare re-cord è in relazione con molti altri record. Nel modello dei dati dell’esempio è la relazione che intercorre tra una casa editrice e i libri da questa pubblicati. Infatti, una casa editrice pubblica molti libri;

• Molti a uno: la relazione indica che molti record sono in relazione con un solo particolare record. Nel model-lo dei dati dell’esempio è la relazione tra i libri e la casa editrice che li pubblica;

• Molti a molti: la relazione indica che molti record sono in relazione con molti altri record. Nel modello dei dati dell’esempio è la relazione che esiste tra un libro e i suoi autori. Infatti, un libro può essere scritto da più autori, e un autore, viceversa, può scrivere vari libri.

Inoltre, le relazioni possono essere unidirezionali o bidirezio-nali. Nel caso unidirezionale solo l’entità proprietaria della re-lazione è a conoscenza della relazione, mentre in una rela-zione bidirezionale entrambe le entità ne sono a conoscenza. Ad esempio, nel diagramma delle classi riportato in Figu-ra 2 la relazione che esiste tra una casa editrice e il suo in-dirizzo è stata modellata come unidirezionale, e pertanto, data una casa editrice è possibile ricavare il suo indirizzo e non il viceversa; mentre la relazione tra una casa editrice e i libri da questa pubblicati è modellata come bidirezionale in quanto, data una casa editrice, è possibile ricavare i libri da questa pubblicati, e dato un libro, è possibile conoscere la casa editrice che lo ha pubblicato.Iniziamo con l’analizzare uno stralcio del codice sorgente della classe CasaEditrice dove è presente la relazione uno a

FIGURA 3 Ciclo di vita di un entity

Page 25: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200724

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 25

Object/Relational Mapping speciale

uno unidirezionale con la classe Indirizzo:

@Entity(name=”CasaEditriceEntity”)@Table(name=”CASA_EDITRICE”)public class CasaEditrice implements Serializable { … @OneToOne(cascade=CascadeType.ALL,fetch=FetchType.EAGER,targetEntity=Indirizzo.class) @JoinColumn(name=”indirizzo”, referencedColumnName=”id_ indirizzo”) private Indirizzo indirizzo = null;

public Indirizzo getIndirizzo() { return indirizzo; }

public void setIndirizzo(Indirizzo indirizzo) { this.indirizzo = indirizzo; } …}

La relazione uno a uno che esiste tra una casa editrice e il suo indirizzo è dichiarata attraverso l’annotazione @One-ToOne. Prima di esaminare nel dettaglio gli elementi casca-de, fetch e targetEntity valorizzati nella dichiarazione del-la annotazione, analizziamo l’annotazione @JoinColumn. Questa annotazione, consente di definire la colonna che funge da foreign key (ossia da chiave esterna). In particola-re, attraverso l’elemento name dell’annotazione è possi-bile specificare il nome della colonna che è la foreign key, mentre con l’elemento referencedColumnName si specifica il nome della colonna (presente nella tabella correlata) refe-renziata dalla foreign key. L’elemento cascade presente nel-l’annotazione @OneToOne può assumere i valori definiti nella enumerazione javax.persistence.CascadeType e sono:

• ALL;• PERSIST;• MERGE;• REMOVE;• REFRESH;

Specificare

cascade={CascadeType.ALL}

è equivalente ad aver specificato

cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE, CascadeType.REFRESH}

L’elemento cascade indica il tipo di operazione che deve es-sere “propagata” sulla entità correlata. Ad esempio, se l’en-tità correlata (che nel nostro esempio è la classe Indirizzo) assume il valore PERSIST, questa viene resa persistente sul database nel momento in cui si invoca il metodo per-sist() dell’Entity Manager per l’entità owner della relazione (nel nostro caso la classe CasaEditrice). Se non si specifica

l’elemento cascade per default non vi è alcuna propagazione delle operazioni di persistenza tra le entità correlate. L’ele-mento fetch nella annotazione @OneToOne può assumere i valori presenti nella enumerazione javax.persistence.FetchType che sono:

• EAGER;• LAZY;

In una relazione uno a uno, il valore di default dell’ele-mento fetch è EAGER, mentre sarà LAZY nelle relazioni uno a molti e molti a molti. Il valore EAGER per l’elemen-to fetch indica che le entità correlate vengono caricate as-sieme (una sorta di caricamento anticipato); viceversa, il valore LAZY indica che le entità correlate vengono caricate solo quando è necessario (una forma di caricamento diffe-rito). La scelta della modalità di caricamento delle entità ha un impatto rilevante sulle prestazioni dell’applicazione. La modalità di caricamento EAGER è generalmente meno efficiente, in quanto comporta il caricamento in memoria dell’intera mappa delle relazioni. Ad esempio, osserviamo il diagramma delle classi e il diagramma Entità/Relazioni del nostro esempio: se per tutte le entità correlate la politi-ca di caricamento fosse impostata al valore EAGER, allora una semplice query di ricerca di una casa editrice compor-terebbe il caricamento anche dell’indirizzo e, soprattutto, di tutti i libri da questa pubblicati; e per ogni libro si avreb-be il caricamento degli autori. Si intuisce facilmente che impostare tutte le relazioni al valore EAGER porta facil-mente ad un degrado delle prestazioni! Se si sta operando su un insieme di entità all’interno di un persistence context attivo, come politica di caricamento è normalmente più ef-ficiente il valore LAZY. Inoltre, è possibile, attraverso l’uso delle fetch join (argomento che approfondiremo nel prossi-mo articolo), personalizzare la modalità di caricamento delle entità con un maggiore livello di granularità (di fatto, caso per caso, attraverso query specifiche). Nello precedente stralcio di codice l’annotazione @OneToOne è anche carat-terizzata dall’elemento facoltativo targetEntity. Attraverso questo elemento è possibile specificare la classe dell’entità correlata, che nel codice riportato è la classe Indirizzo. Il più delle volte questo elemento può essere omesso, poiché la classe dell’entità correlata viene ricavata dal provider JPA

Una entity class deve

avere una primary key

Page 26: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200726

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 27

Object/Relational Mapping speciale

dall’analisi del tipo dell’attributo di relazione (nel prece-dente stralcio di codice, l’elemento targetEntity può essere in effetti omesso). Tuttavia, l’elemento targetEntity è neces-sario se, ad esempio, come tipo dell’attributo di relazione non si specifica la classe dell’entità correlata ma, ad esem-pio, l’interfaccia da questa implementata.La classe CasaEditrice ha una relazione bidirezionale uno a molti con la classe Libro. Di seguito riportiamo uno stralcio del codice sorgente della classe Libro:

@Entity(name=”LibroEntity”)@Table(name=”LIBRO”)public class Libro implements Serializable{ … @ManyToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinColumn(name=”casaEditrice”, referencedColumnName=”id_ce”) private CasaEditrice casaEditrice = null;

public CasaEditrice getCasaEditrice() { return casaEditrice; } public void setCasaEditrice(CasaEditrice casaEditrice) { this.casaEditrice = casaEditrice; } …}

e della classe CasaEditrice:

@Entity(name=”CasaEditriceEntity”)@Table(name=”CASA_EDITRICE”)public class CasaEditrice implements Serializable { … @OneToMany(mappedBy=”casaEditrice”, cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Collection<Libro> libri = null;

public Collection<Libro> getLibri() { return libri; } public void addLibro(Libro libro) { if (this.getLibri() == null) this.libri = new ArrayList<Libro>(); libro.setCasaEditrice(this); this.getLibri().add(libro); } …}

Osserviamo il codice della classe Libro. La relazione mol-ti a uno con la classe CasaEditrice è esplicitata attraverso l’uso dell’annotazione @ManyToOne. Poiché la relazio-ne tra le due entità è bidirezionale, osservando il codice della classe CasaEditrice notiamo, come si può intuire, la presenza dell’annotazione @OneToMany. In questa classe, oltre agli elementi cascade e fetch, è dichiarato l’elemento

mappedBy. Attraverso questo elemento indichiamo la pro-prietà owner della relazione, che nell’esempio è l’attributo casaEditrice presente nella classe della entità correlata, la classe Libro. Nella dichiarazione della annotazione @One-ToMany è omesso l’elemento targetType, in quanto, grazie all’uso dei generics, è possibile dichiarare esplicitamente il tipo dell’insieme di oggetti correlati ad una casa editrice (Collection<Libro>). Per concludere la panoramica sui tipi di relazioni, analiz-ziamo la relazione bidirezionale molti a molti tra le entità Libro e Autore. Di seguito è riportato uno stralcio del codice della classe Libro:

@Entity(name=”LibroEntity”)@Table(name=”LIBRO”)public class Libro implements Serializable{ … @ManyToMany(mappedBy=”libri”, cascade=CascadeType.ALL, fetch=FetchType.EAGER) private Set<Autore> autori = null;

public Set<Autore> getAutori() { return autori; }

public void addAutore(Autore autore) { if (null==autori) autori=new HashSet<Autore>(); if (!autori.contains(autore)) { autori.add(autore); autore.addLibro(this); } } …}

e della classe Autore:

@Entity(name=”AutoreEntity”)@Table(name=”AUTORE”)public class Autore implements Serializable{ … @ManyToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER) @JoinTable(name=”LIBRO_AUTORE”, joinColumns={@JoinColumn(name=”autore_ id”,referencedColumnName=”id_autore”)}, inverseJoinColumns={@JoinColumn (name=”libro_ id”, referencedColumnName=”id”)} private Set<Libro> libri = null; public void addLibro(Libro libro) { if (null == libri) libri=new HashSet<Libro>(); if (!libri.contains(libro)) {

Page 27: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200726

speciale Object/Relational Mapping JAVA Journal

n.4 - settembre/ottobre 2007 27

Object/Relational Mapping speciale

Note Biografiche

Jacopo Giudici si occupa di applicazioni per il Web, di RFID e di domotica su piattaforme J2ME, J2EE e .NET. Progetta e tiene corsi di formazione aziendali sulla sicurezza delle reti informa-tiche e sulla programmazione Java per ambienti distribuiti.Ha lavorato per Microsoft, BottegaVerde, CONAD, Confartigiana-to e ha pubblicato una collana di 6 libri con DeAgostini Scuola sui Sistemi Elettronici-Informatici per il triennio degli istituti tecnici superiori.

Il supporto per la

gestione delle relazioni

è presente fin dalla

specifica 2.0 degli EJB

di tipo Entity

libri.add(libro); libro.addAutore(this); } } public Collection<Libro> getLibri() { return libri; } …}

La relazione molti a molti è esplicitata attraverso l’uso del-l’annotazione @ManyToMany. Osserviamo che nella classe Autore attraverso la annotazione @JoinTable è possibile spe-cificare la tabella associativa che di fatto realizza la relazio-ne nello schema Entità/Relazioni di Figura 1.

Il deployment dell’applicazione

Le entity class sono raccolte in persistence unit. Una persisten-ce unit è una unità logica di entity class, con i metadati per il mapping e le configurazioni specifiche per il database ed il provider JPA. Una persistence unit è definita in un file de-scrittore chiamato persistence.xml che deve essere presente nella cartella META-INF di un archivio jar o di un archivio war o ear. Di seguito riportiamo il file persistence.xml del-l’esempio della gestione della biblioteca:

<persistence><persistence-unit name=”GestioneBiblioteca”> <jta-data-source>java:/theDataSource</jta- data-source> <provider>org.hibernate.ejb.HibernatePersistence</provider></persistence-unit></persistence>

Analizziamo i tag XML di una persistence unit:

• <description>: un testo opzionale• <provider>: nome qualificato della classe del provider,

nel nostro caso Hibernate, che implementa la specifica JPA;

• <transaction-type>: attributo del tag <persistence-unit>. JTA è il valore di default altrimenti può assumere il va-lore RESOURCE_LOCAL;

• <jta-data-source>: nome JNDI del datasource;• <non-jta-data-source>: nome JNDI del datasource;• <mapping-file>: file XML, in alternativa alle annota-

zioni, dove specificare le regole di mapping per le entity class;

• <jar-file>: archivio dove cercare le entity class disponibi-li per la persistence unit;

• <class>: le classi disponibili per la persistence unit;• <exclude-unlisted-classes>: se questo elemento è presen-

te solo le entity class o gli archivi definiti con i tag map-ping-file, jar-file e class sono disponibili nella persistence unit;

• <properties>: proprietà specifiche del provider JPA.

Conclusioni

In questo primo articolo abbiamo trattato i fondamenti della specifica JPA. Nel prossimo articolo parleremo del-la gestione dell’ereditarietà e delle query statiche e dina-miche.

Riferimenti

[1]: http://www.jboss.com/[2]: http://www.mysql.com/[3]: http://www.hibernate.org/

Bibliografia:

[4] R. P. Sriganesh, G. Brose, M. Silverman “Mastering Enterprise JavaBeans 3.0”, Wiley Publishing, Inc., 2006.

[5] R. R. Kodali, J. Wetherbee e P. Zadrozny “Beginning EJB 3 Application Development”, Apress, 2006.

Page 28: j2007 03 jj4
Page 29: j2007 03 jj4

SPEECH Login TopicFREE

§ il protocollo di interazione;§ l’interfaccia del servizio;

Il primo punto è possibile in quanto i consumatori (requester) ed i fornitori (provider) di un servizio non sono accoppiati in una relazione punto a punto, ma l’interazione è mediata dallo Enterprise Service Bus. Ad esempio, un servizio può essere eroga-to da uno o più fornitori e questi possono essere aggiunti o ri-mossi in modo trasparente al consumatore del servizio. L’astra-zione rispetto al protocollo di interazione (protocol switch) è possibile in quanto i partecipanti ad una interazione non de-vono necessariamente condividere il medesimo protocollo di comunicazione. Per esempio, un messaggio può essere invia-to nel bus come richiesta di tipo Web service, basata sul proto-collo SOAP su HTTP, e poi la richiesta è risolta da un fornitore che comunica attraverso il protollo RMI (Java Remote Method

Un “mezzo di trasporto”… per SOA: l’Enterprise Service Bus

Nel precedente numero abbiamo definito una architettura a servizi (SOA) e alcune tecnologie correlate a questo paradigma di sviluppo (Web Service e BPEL). In questo numero introdu-ciamo il concetto di Enterprise Service Bus (ESB), evidenziando-ne il ruolo, fondamentale, in una infrastruttura enterprise co-struita sul modello SOA.

Un ESB è un prodotto di integrazione che funge da collante tra i fornitori di servizi ed i consumatori in un ambiente eterogeneo sia per le tecnologie sia per i protocolli di comunicazione (Figura 1). At-traverso l’uso di un ESB è possibile “astrarre”:

§ la localizzazione e l’identità dei fornitori dei servizi;

ORIZZONTI ENTERPRISE

Tutto ciò che è tendenza nel mondo JEE>> di Fabio Staro ([email protected])

FIGURA 1 Architettura di un Enterprise Service Bus, mediatore tra i requester ed i provider di servizi.

n.4 - settembre/ottobre 200729

Page 30: j2007 03 jj4

LINUXSPEECH Login TopicFREEORIZZONTI ENTERPRISE

Invocation). Il terzo punto, ossia l’astrazione rispetto alla in-terfaccia di un servizio, è possibile poiché i fornitori di un ser-vizio ed i consumatori di questo non devono necessariamen-te condividere la medesima interfaccia. L’Enterprise Service Bus “riconcilia” e “media” le differenze, trasformando i messag-gi inviati al bus in una forma corretta per il fornitore del ser-vizio. Ad esempio, attraverso una trasformazione XSLT è pos-sibile trasformare un messaggio che soddisfa lo schema di un consumatore in un messaggio che rispetti lo schema di un for-nitore del servizio.

Ma quali sono i servizi minimi che deve fornire un Enterprise Service Bus?

Questi possono essere facilmente ricordati grazie all’acronimo TRANS definito da Jeff Hanson [1]. TRANS sta per:

§ Transforming;§ Routing;§ Augmenting;§ Notifying;§ Securing.

Infatti un Enterprise Service Bus:

§ trasforma i messaggi da un formato in un altro per soddisfa-re l’interfaccia esposta dal provider di servizi;

§ gestisce il routing dei messaggi verso i diversi fornitori, ga-rantendo allo stesso tempo la qualità del servizio (QoS, acronimo di quality of service);

§ arricchisce (augmenting) il contenuto di un messaggio con in-formazioni provenienti da sorgenti dati esterne (per esem-pio un database);

§ notifica un messaggio ai diversi listener registrati (interazione del tipo publish-subscribe);

§ gestisce la sicurezza nelle comunicazioni (autorizzazione del-le richieste, encryption e decryption del contenuto dei messag-gi, ecc.).

Inoltre, un ESB, mediando la comunicazione tra i fornitori ed i consumatori, può garantire servizi di monitoring, auditing au-tomatico, affidabilità nella consegna dei messaggi, ecc. Concludendo: le soluzioni di Enteprise Application Integra-tion (EAI) sono state, anche nel recente passato, caratterizza-te da soluzioni basate su tecnologie non standard e proprietarie (vendor lock-in). Viceversa, un Enterprise Service Bus è un prodot-to per l’integrazione basato su standard di mercato (JMS, JMX, SOAP, WSDL, XSLT, XQuery, XPath, ecc.) e su un’architettura orientata ai servizi. Tuttavia, la Java Community propone un ul-teriore e sostanziale salto di qualità. Attraverso la proposta della specifica JBI (Java Business Integration) [2], è possibile creare una serie di componenti che possono essere usati con un qual-siasi ESB aderente allo standard. In sintesi, JBI definisce il con-tratto che esiste fra un ESB ed i componenti che l’ESB gestisce. Nel prossimo numero ritorneremo a parlare della specifica JBI e analizzeremo come potrà evolvere il modo di fare integrazio-ne in ambito JEE.

Bibliografia

[1]: Jeff Hanson, Implementing an Enterprise Service Bus in Java http://www.devx.com/Java/Article/28127

[2]: JSR 208: Java Business Integrationhttp://jcp.org/en/jsr/detail?id=208)

n.1 - novembre/dicembre 2006 30

Page 31: j2007 03 jj4
Page 32: j2007 03 jj4

JAVA Journal

32 n.4 - settembre-ottobre 2007

educational JAVA Journal

n.4 - settembre-ottobre 2007 33

educational

Xp e dintorni

Troppo spesso lo sviluppo del software è un’attività caotica. Per ovviare a ciò sono nati i metodi ingegneristici, spesso troppo articolati e burocratici. L’esigenza di approcci più agili ha portato alla Extreme Programming (XP). Da alcuni percepita in contrapposizione al RUP, in origine ha diviso il cosmo degli sviluppatori tra entusiasti e scettici.Ma forse le cose non sono così semplici e distinte…

>> di Andrea Zoleo ([email protected])

In questo articolo vedremo come si è giunti alla nascita delle metodologie agili di sviluppo ed in particolare all’Extreme Programming (XP). Da-remo un rapido sguardo ai principi e ai valori, alle pratiche e alle fasi che contraddistinguo-no questa metodologia di sviluppo. Infine, con-

fronteremo l’XP con altre metodologie: l‘intramon-tabile RUP (Rational Unified Process), la metodolo-gia Iconix e la nascente CoRE (Community-oriented Real-time Engineering).

In origine regnava il caos

Il più primitivo fra i metodi di sviluppo è il cosiddet-to code & fix (scrivi e correggi). Il software viene scrit-to, eseguito e corretto senza seguire un processo di sviluppo preciso (Figura 1). Di volta in volta si ri-solvono i problemi che si presentano puntando sol-tanto ad avere un programma che svolge il compito momentaneamente in esame. Mancando di una vi-sione di insieme, questo approccio è sostenibile per software di piccole dimensioni, ma non appena il si-stema cresce, diventa più difficile aggiungere nuo-ve funzionalità senza corrompere le vecchie o dover correggere i bachi che immancabilmente emergono. In assenza di un metodo fondato su pratiche, anche un programmatore esperto incorre in grossi proble-mi non appena cerca di integrare il suo lavoro con quello di altri sviluppatori, o quando deve reagire al cambiamento dei requisiti del cliente. Per progetti di dimensioni apprezzabili diventa necessario un meto-do di gestione del ciclo di vita di un progetto softwa-re che armonizzi gli aspetti di analisi dei requisiti, di progettazione, di implementazione, di test, di collau-do e di manutenzione del prodotto realizzato. In uno scenario come questo, il codice eseguibile è solo uno dei prodotti, forse il più importante, ma di sicuro non è l’unico.

La reazione

Il concetto di metodo ingegneristico (plan-driven) consiste in una procedura disciplinata nella realizza-zione di un progetto software che persegue il fine di rendere questa attività maggiormente prevedibile ed efficiente. Inizialmente si accostò il processo di sviluppo del software a quelli caratteristici dell’ingegneria civi-le o meccanica. Questi metodi enfatizzavano l’im-portanza di formulare un progetto preciso prima di costruire. Questo approccio, quando riferito alla co-struzione del software, viene detto waterfall (a casca-ta), in quanto tutto il processo, dalla progettazione alla messa in opera, viene percorso una sola volta. La maggior parte dell’attività creativa è svolta dai pro-gettisti, mentre la fase di costruzione e di test può es-sere portata avanti anche da personale non dotato di una particolare capacità progettuale.Tuttavia, da questo approccio nasce una domanda fondamentale: si riesce, nella progettazione del sof-tware, ad ottenere un progetto che sia in grado di ri-durre la realizzazione del codice ad un’attività preve-dibile? E se sì, la realizzazione di questo progetto è sufficientemente economica da essere vantaggiosa? Nell’ingegneria civile, infatti, i costi e i tempi di pro-gettazione sono nettamente minori rispetto a quel-li di realizzazione dell’opera (in un rapporto di circa uno a dieci). Ebbene, nello sviluppo del software le cose non van-no affatto così. La fase di progettazione è, nella mi-gliore delle ipotesi, paragonabile per tempi e costi a quella di realizzazione. Realizzare un progetto, an-che tramite strumenti specifici come quelli forniti dall’approccio RUP, che tenga conto di tutte le pro-blematiche e le insidie di implementazione è presso-ché impossibile. Inoltre, chiunque scriva del codice di una certa qualità, sa come anche il singolo metodo vada in qualche modo progettato localmente.

Page 33: j2007 03 jj4

JAVA Journal

32 n.4 - settembre-ottobre 2007

educational JAVA Journal

n.4 - settembre-ottobre 2007 33

educational

Per un team di sviluppo,

restare agganciato a

tecnologie obsolete per

la paura di provarne di

nuove, significa non

essere mai produttivo,

ma sempre sulla rampa

iniziale della curva di

apprendimento.

Queste e altre considerazioni simili portano ad un cambio radicale di prospettiva che suggerisce che il codice sorgente sia esso stesso un documento di progettazione. La fase analoga alla costruzione in ingegneria civile sareb-be, dunque, per lo sviluppo del software, la compilazione e il linking. Quindi, nello sviluppo del software la costruzio-ne è gratis: quasi tutto è progettazione creativa, quasi nulla è totalmente prevedibile. Non c’è molto spazio per il perso-nale con scarsa inclinazione alla progettazione.

Agilità

Per un lungo periodo di tempo si è cercato di applicare i metodi inge-gneristici, senza che si dimostras-sero mai terribilmente efficienti. Anzi, sono diventati ben presto meno che popolari. Il loro aspetto meno sopportabile è senza dubbio la mole di scartoffie prodotte che soffoca il progetto, fino al punto di rallentarlo invece che agevolar-lo. Questa massa di documenti di progettazione è il risultato del ten-tativo di progettare a priori tutti gli aspetti di un’attività impreve-dibile. I metodi agili si pongono come compromesso fra l’assenza di un processo e l’eccesso di processo. La nascita delle metodologie agili coincide con il periodo di diffusio-ne massiccia di Internet alla fine

degli anni 1990, quando la produzione del software ha su-bito un drastico cambiamento, passando da un ciclo di vita dell’ordine degli anni a quello dell’ordine dei mesi. I meto-di agili sono meno orientati ai documenti di progettazione e si concentrano maggiormente sulla chiarezza del codice e dei relativi commenti. Tuttavia sono altre due le differenze sostanziali dei metodi agili rispetto ai metodi precedenti. La prima è che i meto-di agili sono adattativi invece che predittivi. I metodi inge-gneristici cercano di prevedere una larga parte del proces-so di sviluppo del software con un buon dettaglio. Questa previsione ha un valore tanto maggiore quanto maggiore è la tendenza dei requisiti a restare immutati dal momen-to della progettazione a quello del rilascio. Per questa ra-gione questi metodi tendono a resistere il più possibile al-l’aggiunta di cambiamenti dopo la fase di raccolta dei re-quisiti. Tuttavia, come già menzionato da Kent Beck “Tutto cambia nel software. I requisiti cambiano. La progettazione cambia. Gli aspetti commerciali cambiano. La tecnologia cambia. I membri del team cambiano. Il problema non è il cambiamento di per sé, perché i cambiamenti avverranno; il problema, piuttosto, è l’ina-bilità di far fronte ai cambiamenti quando essi avvengono”. L’im-portanza di ammortizzare i cambiamenti si comprende bene confrontando la Figura 2 (costi classici) e la Figura 3 (costi agili).I metodi agili puntano a realizzare un processo di svilup-po propenso ai cambiamenti, fino al punto di mutare sé stesso se necessario. La seconda differenza è che i meto-di agili sono orientati alla persona invece che al processo. Lo scopo dei metodi ingegneristici è definire un processo che funzioni indipendentemente da chi siano coloro che lo praticano, al fine di renderlo robusto al cambiamento delle risorse umane impiegate. Al contrario, le metodolo-gie agili asseriscono che non esiste processo che possa so-stituire le competenze del gruppo di sviluppo. Il processo deve limitarsi ad assistere e supportare il team nel miglior modo possibile.

FIGURA 1 La filosofia alla base del metodo “code & fix” è ben raffigurata in questa vignetta. Si prova e riprova fino ad ottenere il risultato cercato. Se l’obiettivo è critico, il prezzo da pagare è spesso troppo alto.

Page 34: j2007 03 jj4

JAVA Journal

n.4 - settembre-ottobre 200734

educational JAVA Journal

n.4 - settembre-ottobre 2007 35

educational

La nascita dell’XP

Durante la prima fase di notorietà dei metodi agili, alla fine degli anni 1990, il metodo detto Extreme Programming fu quello che raggiunse la maggiore popolarità. Le radici dell’XP risalgono alla comunità Smalltalk, ed in partico-lare alla stretta collaborazione fra Kent Beck e Ward Cun-ningham alla fine degli anni 1980. Entrambi raffinarono le proprie strategie in numerosi progetti nei primi anni 1990, estendendo le loro idee su uno sviluppo del software basa-to sulla adattabilità e sull’orientamento alla persona. Kent continuò a coltivare queste idee fino all’approdo al progetto C3 della Chrysler. Questo progetto riscosse una grande notorietà, in quanto 12 programmatori riuscirono a scrivere in due anni il sistema di paghe mensili del grup-po (che gestiva più di 10.000 paghe al mese) composto da 1400 classi funzionali e 1700 classi di test. Questo progetto fu identificato come il progetto che diede i natali alla me-todologia XP.

I cinque valori dell’XP

L’XP si focalizza su cinque valori:

1. comunicazione; 2. feedback; 3. semplicità; 4. coraggio; 5. rispetto.

§ Comunicazione. La conoscenza è un bene prezioso nella realizzazione di un pro-getto software. Per “conoscenza” si in-tende sia quella del problema da auto-matizzare (tipica del cliente) sia quel-la sulle tecnologie (propria del team di sviluppo). È fondamentale, quindi, che non resti isolata. Ciò vuol dire favorire la comunicazione sia fra il cliente e il team di sviluppo, ma anche fra gli elemen-

ti del team stesso. Questa comunicazione deve essere mantenuta per tutta la durata del progetto. Ad esempio, l’interazione fra cliente e il team di sviluppo non deve inter-rompersi dopo la fase di raccolta dei requisi-ti.

§ Feedback. La verifica continua dei ri-sultati ottenuti (e di quelli mancati) è un aspetto fondamentale. Permette di tarare i criteri di giudizio dei tempi e dei costi per le fasi successive del progetto. Avvicina il pun-to di vista del cliente e del team di sviluppo, spingendoli a collaborare per la realizzazio-ne di uno scopo comune, invece di arroc-carsi su posizioni inamovibili e contrappo-ste. Evita che il team di sviluppo si allontani dalla “retta via” sviluppando soluzioni che hanno poco interesse per il cliente, e aiuta il

cliente a capire quali sono le richieste tecnologicamen-te ragionevoli e quali non lo sono.

§ Semplicità. Nel caso dei sistemi informatici, la semplici-tà non è solo un fattore che rende migliore un sistema rispetto ad un altro. Spesso è un fattore determinante per il funzionamento del sistema. L’XP impone sempre di mantenere i requisiti minimi necessari per coprire le richieste del cliente. Ogni complessità aggiunta per motivi teorici o estetici è un inutile orpello che prima o poi ci si rivolterà contro. Ciò non vuole dire che l’XP ri-fiuta l’approccio di una progettazione teorica, o che ri-pudia la ricerca di soluzioni eleganti.

§ Coraggio. Un pizzico di spericolatezza non guasta! Nel-lo sviluppo del codice, soprattutto dopo l’avvento della grande rete, la vecchia prudenza a tutti i costi, sban-dierata come virtù da molti project manager, si rivela spesso l’anticamera del fallimento. Per un team di svi-luppo, restare agganciato a tecnologie obsolete per la paura di provarne di nuove, significa non essere mai produttivo, ma sempre sulla rampa iniziale della cur-va di apprendimento. Allo stesso modo, aver paura di riscrivere porzioni consistenti di un sistema, una volta

FIGURA 2 Diagramma dei costi “classici”

FIGURA 3 Diagramma dei costi “agili”

Page 35: j2007 03 jj4

JAVA Journal

n.4 - settembre-ottobre 200734

educational JAVA Journal

n.4 - settembre-ottobre 2007 35

educational

che si è individuata una soluzione migliore (leggi più semplice o generale), è una politica che porta alla ro-vina. Il successo delle tecnologie open-source ha ormai dimostrato che la qualità del lavoro accorcia i tempi di sviluppo. Pensare che scrivere il codice più in fretta si-gnifichi scriverlo male, è una favola a cui credono solo i project manager sopra menzionati. Coraggio signifi-ca anche non aver paura di confrontare le proprie opi-nioni con quelle degli altri, e soprattutto ricordare che le regole esistono, ma possono anche essere cambiate, qualora il team ne abbia valutato le conseguenze e ab-bia raggiunto una visione concorde.

§ Rispetto. Vi ricordate l’orientamento alla persona? Uno degli aspetti dei metodi ingegneristici è di considerare i membri di un team come “componenti” sostituibili. Secondo questi processi ci sono analisti, programma-tori, tester, manager, ecc. Gli individui non contano; solo i ruoli che ricoprono sono presi in considerazione. L’XP rifiuta completamente questa visione. Considera le qualità individuali un aspetto chiave nel team. Un buon metodo di gestione di un progetto deve valoriz-zare le qualità di ciascuno, innalzare il morale, spinge-re tutti a dare il massimo (e a voler dare il massimo). Del resto se ci si aspetta che i propri sviluppatori siano dei componenti sostituibili invece che persone, le risor-se valide si cercano un posto migliore, e ciò che resta è proprio ciò che si voleva: un ammasso di componenti sostituibili.

Decidere che le persone vengono prima è una grossa deci-sione per un’azienda. Tuttavia va segnalato che lo sviluppo del software è un’attività creativa e male si adatta ai prin-cipi del Taylorismo.

Le cinque fasi dell’XP

Il Ciclo di vita dell’XP (Figura 4) consiste di 5 fasi:

1. esplorazione; 2. pianificazione;3. iterazioni fino al rilascio;4. produzione; 5. mantenimento fino alla morte (del progetto, natu-ralmente).

§ Nella fase esplorativa il cliente scrive delle storie (user-story, una versione ri-dotta dei casi d’uso del RUP) per presentare le funzioni che vorrebbe fossero inclu-se nel primo rilascio del si-stema. Nel frattempo il team di sviluppo testa e acquisisce familiarità con le tecnologie e gli strumenti che (proba-bilmente) dovrà utilizza-re. Questa fase può durare

da alcune settimane a un massimo di pochi (due/tre) mesi. Per storie particolarmente rischiose l’XP preve-de l’utilizzo di spike architetturali, cioè di “piccoli pro-grammi usa e getta” per sperimentare una certa solu-zione.

§ Nella fase di pianificazione, che dura circa un paio di

giorni, i programmatori danno una prima stima dello sforzo richiesto per l’implementazione di ogni storia. In base a ciò il cliente e il team raggiungono un accor-do sulla priorità delle storie e sul contenuto del primo rilascio. Il cliente formalizza anche i test di accettazio-ne delle storie.

§ Durante le iterazioni fino al primo rilascio, le storie del cliente vengono frammentate o raggruppate, a seconda dell’entità di ciascuna, fino a renderle compatibili con iterazioni della durata di qualche settimana (da una ad un massimo di tre/quattro). Le storie vengono asse-gnate a coppie di sviluppatori e l’iterazione comincia. La prima iterazione si occupa di costruire l’architettura per l’intero sistema, scegliendo come iniziali quelle sto-rie che coprono tutti gli aspetti architetturali. Il cliente decide quali storie vanno implementate nelle iterazio-ni successive. I test funzionali sono creati del cliente e vengono eseguiti alla fine di ogni iterazione. Il periodo di un rilascio, può durare da tre settimane a tre mesi. La cosa fondamentale è che ogni rilascio produca un si-stema funzionante che permetta al cliente di provare il prodotto e fornire un parere. Alla fine dell’ultima itera-zione, il prodotto è pronto per la fase successiva.

§ La fase di produzione richiede una serie ulteriore di test, compresi i controlli di efficienza prima che il prodotto possa essere rilasciato al cliente. Durante questa fase possono essere individuati ancora possibili cambia-menti, ed è necessario decidere se vanno inclusi in que-sto rilascio o nel successivo. Durate questa fase la dura-ta delle iterazioni deve essere accorciata e deve durare

FIGURA 4 Ciclo di vita dell’XP

Page 36: j2007 03 jj4

JAVA Journal

n.4 - settembre-ottobre 200736

educational JAVA Journal

n.4 - settembre-ottobre 2007 37

educational

stema in produzione informazioni utili ai rilasci suc-cessivi. Questo approccio ha lo scopo di mitigare il ri-schio di un processo poco prevedibile com’è lo sviluppo di un sistema software.

3. Metafore. Il sistema è definito da una metafora o da un set di metafore fra il cliente e i programmatori. Queste storie condivise guidano tutto lo sviluppo descrivendo come deve funzionare il sistema. Le storie ricordano i casi d’uso del RUP, anche se si differenziano da questi per la brevità. Infatti, le storie puntano ad avere una comprensibilità a 360 gradi, cioè paritetica per il clien-te e per gli sviluppatori, più che ad una descrizione det-tagliata di tutti i possibili flussi di programma che il si-stema può percorrere.

4. Semplicità. Viene enfatizzata la progettazione della so-luzione più semplice in ogni momento. La complessità inutile o il codice extra vengono rimossi alla partenza. Naturalmente, la semplicità assoluta non esiste, poi-ché alcuni processi o algoritmi sono intrinsecamente complessi. Quello a cui si deve tendere, dunque (anche a costo di ritocchi successivi in fase di sviluppo), è per-seguire sempre la più semplice delle soluzioni che via via si delineano.

5. Test, test e ancora test. Molte delle pratiche adottate dal-l’XP si trovano già nel RUP o in altri metodi ingegne-ristici. Tuttavia l’XP estremizza l’importanza di alcune di esse. In particolare modo l’XP mette la pratica dei test a fondamento del metodo di sviluppo. I test di unità vengono scritti prima del codice stesso e vengono ese-guiti di continuo. Questo approccio ha numerosi bene-fici. Per prima cosa, il momento migliore per scrivere un test è quando si sta per scrivere il codice da testare e si hanno ancora freschi in mente tutti gli aspetti del problema in esame. In secondo luogo, scrivere prima i test, costringe lo sviluppatore a concentrarsi su cosa deve fare il software, prima che su come potrà farlo, e forza alla programmazione per interfacce e disaccop-piata. Infine, i test disponibili nelle fasi iniziali di un progetto consentono di manipolare il codice con mag-giore serenità, in quanto si dispone di uno strumento per verificare di continuo che i cambiamenti introdotti non compromettano le funzionalità del sistema.

6. Refactoring. Il codice del sistema viene continuamen-te ricostruito, rimuovendo duplicazioni, aumentando il riutilizzo, introducendo interfacce, rafforzando con-venzioni sui nomi, ecc. Questa pratica è in stretta re-lazione con quella della semplicità, anche se in questo caso è più corretto parlare di comprensibilità. L’attività di refactoring è spesso malvista dai project manager e dai programmatori inesperti, perché dà la sensazione di ritoccare un po’ dappertutto un codice che maga-ri finalmente funziona. Al contrario, i programmatori più navigati, che non tollerano di considerare il siste-ma qualcosa che “va anche se non si sa come”, sono spesso favorevoli ad un refactoring che consolidi i ri-sultati a fatica ottenuti sul campo. Del resto la maggior parte del refactoring è un attività lunga ma ripetitiva,

al massimo una settimana. Le idee e i suggerimenti per le release successive vanno annotati e conservati.

§ Dopo che è avvenuto il primo rilascio all’utente, il pro-getto XP deve essere sia mantenuto in produzione, sia evoluto con nuove iterazioni verso rilasci successivi. In questa fase di mantenimento è richiesto un ulteriore sforzo per dare un supporto continuo al cliente. Per-tanto lo sviluppo vero e proprio può essere rallentato. Questa fase rappresenta anche un buon momento per inserire nuove figure nel team di sviluppo o per modi-ficarne in generale la struttura.

§ La morte del progetto comincia quando il cliente non ha più nuove storie da raccontare al team, ed il sistema soddisfa il cliente per efficienza e affidabilità. Questo è il momento per il team di scrivere la documentazio-ne completa del prodotto, perché d’ora in poi le cose non cambieranno più. Oltre all’eutanasia, comunque, la morte può sopraggiungere anche perché il sistema non ha mai raggiunto i requisiti del cliente, o è diven-tato troppo costoso svilupparlo.

Nel ciclo di vita XP non esistono fasi di analisi e di design distinte, come avviene invece nel RUP, ma sono fuse assie-me alla fase di implementazione. Pertanto, il progetto evol-ve insieme al codice. Ciò garantisce una notevole flessibili-tà alle modifiche, ma tuttavia impone agli sviluppatori una notevole capacità di progettazione, rendendo il metodo XP inadatto a team di programmatori inesperti.

Le 14 pratiche dell’XP

Nelle successive revisioni che Kent fece del metodo XP, i cinque valori trattati nel paragrafo precedente vennero trasformati in 14 pratiche. Queste pratiche discendono dai valori già discussi e risultano esserne un’applicazione con-creta. Vediamo di elencarle e di dare, di ognuna, una bre-ve spiegazione.

1. Il gioco della pianificazione. Una stretta interazione tra il cliente e il team di sviluppo. I programmatori stima-no lo sforzo e le risorse necessarie per l’implementa-zione delle storie del cliente, mentre il cliente stabilisce l’ambito e la sequenza dei rilasci. È importante a que-sto punto spiegare uno degli aspetti peculiari dell’ap-proccio XP. In questa fase di negoziazione per l’imple-mentazione delle storie, le variabili in gioco sono quat-tro: costo, tempo, qualità e portata. Negli approcci classici il management o il cliente decidono i valori di tutte e quattro queste variabili (purtroppo). In XP solo tre di queste variabili sono decise a priori, la quarta è il grado di libertà concesso al team di sviluppo, il quale può fis-sarne il valore in funzione delle altre.

2. Rilasci frequenti. Piccole porzioni di sistema vengono portate in produzione rapidamente, almeno una vol-ta ogni due o tre mesi. Nuove versioni sono quindi ri-lasciate anche giornalmente, ma non più che mensil-mente. Il cliente e il gruppo di lavoro traggono dal si-

Page 37: j2007 03 jj4

JAVA Journal

n.4 - settembre-ottobre 200736

educational JAVA Journal

n.4 - settembre-ottobre 2007 37

educational

e se supportata da un buon tool di sviluppo può essere quasi completamente automatizzata.

7. Programmazione in coppia. Due sviluppatori per ogni computer. Questo permette di aumentare la qualità del codice scritto, sottoponendolo ad una continua verifica e discussione nel momento stesso in cui viene scritto. Le coppie di programmatori dovrebbero essere cambia-te spesso, in modo che ciascun programmatore si trovi a lavorare su tutte le sezioni del progetto. Questa prati-

ca permette anche la crescita degli sviluppatori, soprat-tutto quelli meno esperti, grazie all’interazione di cia-scun membro del team con tutti gli altri.

8. Possesso comune. Ciascuno può cambiare qualsiasi parte del codice in qualsiasi momento. Ad esempio, se qual-cuno si accorge della possibilità di migliorare un meto-do o una classe, semplificandoli, deve farlo senza pro-blemi, anche se non è lui il creatore di quella classe. Questa attività è agevolata dall’uso di uno stile stan-dardizzato nella scrittura del codice ed è resa sicura dall’adozione dei test di non regressione.

9. Integrazione continua. Una nuova porzione di codice vie-ne integrata nel repository contenente il codice del si-stema non appena è pronta. Il sistema viene comple-tamente ricostruito e testato. Tutti i test devono essere completati con successo affinché le modifiche apporta-te vengano accettate.

10. 40 ore alla settimana. Gli straordinari sono proibiti. Gli sviluppatori devono lavorare al massimo 40 ore setti-manali. Se vengono fatti straordinari, vanno conside-rati come un problema (un baco nel processo). Se ne studia la causa e si cerca di risolverla.

11. Cliente sul posto. Il cliente deve essere presente e dispo-nibile in qualunque momento per il team di sviluppo. Questo è uno degli aspetti più difficilmente attuabili nella realtà dello sviluppo quotidiano del software, so-prattutto nel caso (così comune in Italia) in cui si svi-luppi codice per grandi enti statali o per la Pubblica Amministrazione, dove le distanze fra i committenti e

FIGURA 5 Schema della metodologia RUP

Pensare che scrivere

il codice più in fretta,

significhi scriverlo

male è una favola a

cui credono solo i

project manager sopra

menzionati

Page 38: j2007 03 jj4

JAVA Journal

n.4 - settembre-ottobre 200738

educational JAVA Journal

n.4 - settembre-ottobre 2007 39

educational

il team di sviluppo possono essere siderali.

12. Codice standardizzato. Sono dichiarate e seguite scrupo-losamente delle regole di scrittura del codice, in modo che i sorgenti abbiano un solo stile di codifica noto a tutti. Questa regola non fa riferimento tanto all’aspet-to di formattazione del codice, quanto alle convenzioni sui nomi da dare alle variabili di classe, ai metodi, alla assegnazione di variabili, piuttosto che all’uso innesta-to delle chiamate e così via.

13. Spazio aperto. Una grande sala con piccoli cubicoli è pre-feribile a numerosi uffici separati. Le coppie di svilup-patori dovrebbero essere messe al centro dello spazio.

14. Semplicemente regole (quella che preferisco). Il team deve seguire delle regole, ma deve anche ricordare che sono solo regole e possono essere ridiscusse e adatta-te in qualsiasi momento. I cambiamenti devono, natu-ralmente, essere concordi e il loro impatto deve essere previsto.

Conclusioni

Per concludere, vorrei esporre alcune mie convinzioni ine-renti alle metodologie di sviluppo. Abbiamo visto che nel corso degli anni si sono susseguite molte metodologie, spesso in profonda antitesi l’una con l’altra. Ciascuna di esse ha introdotto, a proprio modo, qualcosa di innovati-vo; ma nessuna si è arrogata il ruolo di soluzione migliore o definitiva. Alcune, tuttavia, rappresentano a mio parere più di altre dei punti di riferimento: si tratta delle meto-dologie RUP, XP, Iconix e CoRE. Vediamo quali sono i loro aspetti peculiari.La metodologia RUP (Figura 5) è probabilmente la più completa per numero di artefatti e dettaglio nella gestio-ne dei vari workflow. Per questo motivo, può essere oggi considerata come una metodologia limite, a cui attingere quando si realizza la propria metodologia. Tuttavia un’ese-cuzione completa delle pratiche RUP, appare oggi un’ope-ra titanica, non più alla portata di nessuna azienda, consi-derato il numero di nuove tecnologie e la velocità richiesta nella messa in produzione dei sistemi odierni. Allo stesso modo l’XP sta subendo oggi una simile sorte, anche se per motivi diametralmente opposti. Anch’esso sta diventando una tecnologia limite, dalla quale però non vengono attin-te le specifiche degli artefatti o dei workflow, ma i valori orientati alla persona, l’agilità e la pratica dei test e delle costruzioni automatiche continue. Anche l’XP, comunque, ha mostrato i suoi limiti poco realistici, soprattutto rela-tivamente alla presenza continua del cliente, allo spazio comune di lavoro e alla richiesta di motivazione continua da parte di tutto il team. Da un alleggerimento del RUP è nata Iconix che, mantenendo solo un piccolo numero degli artefatti e dei workflow, ha ricondotto il processo ad una dimensione compatibile con le odierne tempistiche di svi-luppo. Allo stesso modo, da una mitigazione dell’approccio XP sta oggi affermandosi CoRE. Questa metodologia, pro-veniente dalle esperienze dello sviluppo open-source, al-leggerisce le richieste di presenza continua del cliente, di

un ambiente comune di sviluppo e della lotta al documen-to scritto, proprie dell’XP. Pur mantenendo le caratteristi-che di testing spinto e di costruzione continua, accentra lo sviluppo del software attorno alla Community. Il gruppo di sviluppo, clienti compresi, è mantenuto costantemente coeso dalla continua interazione tramite appositi strumen-ti attorno ad un sito ufficiale di sviluppo del progetto. Questo sito è per la maggior parte prodotto da strumenti automa-tizzati a partire dallo stato corrente del codice sorgente e dei documenti che gli strumenti di collaborazione hanno prodotto di giorno in giorno (FAQ, issue tracking, mailing list, forum, groupware, ecc.). Chissà se più in là, dal ma-trimonio di Iconix con CoRE, non nasca qualcosa di anco-ra più equilibrato e universale. Ma questa è una storia che solo il futuro potrà raccontare.

Bibliografia

[1] Kent Beck, “eXtreme Programming eXplained”, Addison-Wesley, 1999, ISBN 0201616416.

[2] Ivar Jacobson, Grady Booch, James Rumbaugh, “The Unified Software Development Process”, Addison-Wesley, 1999, ISBN 0201571692.

[3] Rosenberg Doug, Scott, Kendall, “Applying Use Case Driven Object Modeling with UML: An Annotated E-Commerce Example”, Addison-Wesley, 2001, ISBN 9780201730395.

[4] Glenn Niemeyer, Jeremy Poteet, “Extreme Programming with Ant”, SAMS, 2003, ISBN 0672325624.

[5] César F. Acebal, Juan M. Cueva Lovelle, “A new method of Software Development:eXtreme Programming”, UPGRA-DE, 2002, http://www.upgrade-cepis.org/issues/2002/2/up3-2Acebal.pdf.

[6] Pekka Abrahamsson, Outi Salo, Jussi Ronkainen, “Agile software development methods, review and analy-sis”, JULKAISIJA-UTGIVARE-PUBLISHER, 2002, 9513860094.

Riferimenti

[7] http://www.extremeprogramming.org[8] http://www.martinfowler.com/articles/

newMethodology.html[9] http://www.agilealliance.org/[10] “Software Design Using CRC Cards” http://www.realtime-info.com[11] “Lo sviluppo ruota intorno all’utente” http://www.nwi.it/nwi_arretrati/p12a0101.htm[12] “Processi e metodologie di sviluppo”, MokaByte N.85 http://www.mokabyte.it/2004/05/metod-2.htm

Note Biografiche

Federico Paparoni si occupa prevalentemente di sviluppo sulle piattaforme JavaME e JavaEE. Gestisce il portale JavaStaff.com per la pubblicazione di notizie e articoli sul mondo Java.

Page 39: j2007 03 jj4

JAVA Journal

n.1 - novembre/dicembre 2006 35

focus

Page 40: j2007 03 jj4

JAVA Journal

40 n.4 - settembre/ottobre 2007

focus JAVA Journal

n.4 - settembre/ottobre 2007 41

focus

Database con SuperWaba per PDA e SmartPhone

SuperWaba è una piattaforma di svi-luppo software open-source per PDA (Personal Digital Assistant o più co-munemente noti come palmari) e SmartPhone, basata sui Java tool. SuperWaba deriva direttamente dal

progetto Wabasoft, nato nel 2000, che si ripromet-te di definire un linguaggio, una macchina virtuale, un formato di classi e un set di API per lo sviluppo di programmi su periferiche portabili. Nonostante Waba non sia esattamente Java, la sua sintassi per-mette ai programmatori Java di apprenderlo veloce-mente. Inoltre, l’SDK SuperWaba contiene una serie di classi per lo sviluppo di applicazioni direttamen-te in Eclipse, aiutando ulteriormente gli sviluppatori Java ad avvicinarsi alla piattaforma.

SuperWaba: l’SDK e i suoi vantaggi

Al momento, il kit di sviluppo di SuperWaba (scarica-bile dal sito www.SuperWaba.com) consiste di:

§ SWVM (SuperWaba Virtual Machine): una Virtual Machine SuperWaba che utilizza il principio “Wri-te once run anywhere”, ossia un principio base di Java.

§ Librerie di base ed estese: sono delle API che permet-tono lo sviluppo di applicazioni (anche commer-ciali). La libreria di Driver PDB (Personal DataBa-se), che verrà trattata in questo articolo, è una li-breria open source che permette la costruzione di un motore database funzionante su PDA.

§ Strumenti di sviluppo e di distribuzione: sono gli stru-menti adatti a sviluppare e installare le applicazio-ni su diversi tipi di periferiche.

§ Esempi e documentazione.

Come è detto nel sito del progetto, le applicazioni scritte con SuperWaba hanno molteplici vantaggi. Eccone alcuni:

§ Basso costo di creazione e mantenimento delle applicazio-ni. Grazie al principio del “write once run anywhe-re”, è molto semplice scrivere applicazioni per una gamma più ampia di periferiche passando velo-cemente, ad esempio, dalla piattaforma PDA agli SmartPhone.

§ Minore costo di installazione delle applicazioni. La piat-taforma è completamente royalty-free e non ha costo di licenza per periferica. L’unico costo è la

In questo articolo verrà descritta la piattaforma SuperWaba e come utilizzarla per realizzare un breve programma per gestire i PDB (Personal DataBase), ossia dei database utilizzabili direttamente da un palmare o da uno SmartPhone.

>> di Jacopo Giudici ([email protected])

Page 41: j2007 03 jj4

JAVA Journal

40 n.4 - settembre/ottobre 2007

focus JAVA Journal

n.4 - settembre/ottobre 2007 41

focus

sottoscrizione annuale per i programmi distribuiti, un servizio che offre aggiornamenti automatici della Vir-tual Machine e il supporto per lo sviluppo.

§ Migliori prestazioni. Paragonato ad altre piattaforme (il sito del progetto cita .NET Compact Framework e J2ME) SuperWaba dimostra un miglior utilizzo della memoria del dispositivo, unitamente a buone presta-zioni.

L’installazione del sistema

Dopo l’accesso al sito, è richiesta una registrazione gratuita per poter scaricare l’SDK SuperWaba e la Virtual Machine adatta alla periferica sulla quale installare SuperWaba. Per l’installazione dell’SDK e degli esempi forniti, sono dispo-nibili un file eseguibile per Windows e dei pacchetti auto-installanti rpm e deb per Linux. Anche se in questo articolo utilizzeremo Windows, il procedimento è identico, o molto simile, per ogni altro sistema operativo, e la guida fornita con il prodotto spiega passo passo come procedere. Dopo aver installato l’SDK, avremo una cartella SuperWabaSDK contenente gli eseguibili per la creazione dei programmi, le librerie Waba e gli esempi forniti.Per installare la Virtual Machine (VM) sul palmare, dob-biamo innanzitutto scegliere l’eseguibile adatto al nostro

sistema. Una volta scelta la VM adatta, le instal-lazioni variano per sistemi PalmOS e PocketPC.Nel primo caso, l’installazione della VM, cioè la copia dell’eseguibile nelle cartelle adatte, deve essere fatta manualmente. In particolare, in ogni versione di PalmOS il file SuperWaba.pdb deve es-sere copiato nella cartella xplat, contenente i file di configurazione della piattaforma. Dopo aver copiato questo file, per ogni versione del sistema operativo esiste una particolare cartella: il ma-nuale di SuperWaba a corredo dell’SDK indica in quale cartella copiare la VM e i metodi nativi. Ad esempio, con sistemi PalmOS 5 o superiori, i due file SuperWaba.prc (la VM) e SWNatives.prc (i meto-di nativi) devono essere copiati nella cartella

palm/PalmOS5_or_16bpp_only

Come ho già detto, rimando alla guida per gli ul-teriori chiarimenti. Nel secondo caso, ossia per PocketPC, oltre al file batch CEinstall_RunMe.bat, che permette l’installazione sulla periferica col-legata tramite ActiveSync ad un PC, è possibile utilizzare il file .cab adatto al processore ed al Si-stema Operativo prescelto, lanciandolo diretta-mente dalla periferica; cosa da non sottovaluta-re, in quanto permette anche l’installazione del sistema tramite inserimento di schede SD o CF preparate con un file autorun. Inoltre, seguendo le istruzioni riportate nella guida, è possibile an-che su piattaforma PocketPC installare il prodotto manualmente, copiando i file giusti nelle cartelle predefinite. Dopo l’installazione, su PocketPC do-

FIGURA 1 Ad installazione avvenuta tra i programmi disponibili sul PocketPC appare anche SuperWaba

SuperWaba deriva dal

progetto Wabasoft, nato

nel 2000, e implementa

una macchina virtuale

per l’esecuzione

di programmi su

dispositivi portabili

Page 42: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200742

focus JAVA Journal

n.4 - settembre/ottobre 2007 43

focus

vrebbe comparire, nella schermata dei programmi dispo-nibili, anche SuperWaba, come si vede in Figura 1. Per verificare di aver eseguito correttamente tutti i passaggi, proviamo ad installare uno degli esempi forniti con l’SDK. Come ogni linguaggio di programmazione che si rispetti, anche SuperWaba ha il suo esempio HelloWorld che trovate nella cartella SuperWabaSDK sotto

bin/installers/samples/<nome del sistema>/app/ HelloWorld.

Per installare l’applicazione su PocketPC, lanciate il pro-gramma HelloWorld_Install.bat dopo aver collegato la perife-rica al computer tramite ActiveSync. Il programma ricono-scerà il sistema utilizzato dal palmare e utilizzerà il file .cab appropriato per l’installazione. Dopo l’installazione, sul palmare troverete un nuovo programma, HelloWorld, che, se lanciato, visualizzerà la schermata di Figura 2.

Una prima applicazione in SuperWaba

Siamo quindi pronti a creare la nostra prima applicazione. L’ambiente di sviluppo che andrò ad utilizzare è il Tauschke MobileCreator (Riquadro 1). Il programma d’esempio con-siste in una applicazione grafica SuperWaba per poter in-serire dei dati relativi ad una videoteca in un database por-tabile. Naturalmente, viene utilizzato questo esempio per creare una struttura standard da poter utilizzare per l’in-serimento e la ricerca dei dati in un qualsiasi database con poche modifiche. Cominciamo dalla definizione della clas-se Videoteca che ospiteremo nel file Videoteca.java:

import waba.ui.*;import waba.fx.*;

public class Videoteca extends MainWindow { // casella di testo per l’inserimento di un titolo

Edit edtFilm;

// metodo costruttore public Videoteca () { super(“Videoteca”,TAB_ONLY_BORDER); }

public void onStart() {

// aggiunge una label add(new Label(“Film “), LEFT, AFTER+2);

// aggiunge la casella di testo edtFilm add(edtFilm = new Edit(“ “));

//posizionamento e modifica della grandezza di edtFilm edtFilm.setRect(RIGHT, SAME-1, PREFERRED+50, PREFERRED); } }

Il package waba.ui fornisce l’implementazione della clas-se MainWindow, la classe di base per creare delle finestre in SuperWaba. Innanzitutto, definiamo la variabile edtFilm di tipo Edit (una casella di testo). Quindi utilizziamo il co-struttore della classe che permette di impostare il nome e il BorderStyle della finestra, impostando il primo a Videoteca

FIGURA 2 Il programma d’esempio HelloWorld in esecuzione sul PocketPC.

RIQUADRO 1

Tauschke MobileCreator

Studiato appositamente per creare applicazioni con SuperWaba, questo ambiente di sviluppo, di facile in-stallazione, crea automaticamente i file per installare e distribuire le applicazioni con SuperWaba utilizzan-do una struttura visuale alla Eclipse. Questa distribu-zione permette di utilizzare in automatico le classi Warp ed Exegen che creano, rispettivamente, un file di tipo .pdb con il programma SuperWaba sotto for-ma di package, e un file eseguibile per l’esecuzione dello stesso. Inoltre, Tauschke MobileCreator fornisce un’anteprima grafica dell’applicazione, utilizzando le classi installate nel PC di sviluppo. Il programma (con licenza d’uso personale gratuita) è reperibile all’indi-rizzo Web http://www.tauschke.com.

Page 43: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200742

focus JAVA Journal

n.4 - settembre/ottobre 2007 43

focus

e il secondo a TAB_ONLY_BORDER, uno stile senza bordi visibili. All’attivazione dell’applicazione partirà il metodo onStart(), che in genere è incaricato di creare la struttura grafica della finestra. Da notare il particolare metodo con cui SuperWaba inserisce i vari controlli in una finestra: il metodo si chiama sempre add(), come nelle applicazioni Swing, ma viene utilizzato con dei modificatori particola-ri. Durante l’inserimento di un componente, in SuperWa-ba si possono utilizzare due tipi di posizionamento: nume-rico oppure logico. Con il posizionamento numerico, si esprime la posizione fissa di un componente tramite i valori delle coordinate; ad esempio possiamo inserire un controllo uti-lizzando il metodo:

add(Control control, int x, int y)

Ciò serve a posizionare in modo assoluto il controllo nel-la finestra (x e y sono valori calcolati in pixel a partire dal punto in alto a sinistra di MainWindow). Con il posizio-namento logico (detto anche posizionamento smart) ogni componente viene inserito in MainWindow utilizzando un criterio relativo, grazie a dei metodi che permettono il po-sizionamento rispetto all’ultimo componente inserito. Nel nostro caso, ad esempio, abbiamo inserito il primo control-lo utilizzando il comando:

add(new Label(“Film “), LEFT, AFTER+2);

Nella fattispecie, non essendoci altri controlli, il posizio-namento ha come riferimento l’angolo in alto a sinistra di MainWindow. Il componente verrà posizionato con alli-neamento a sinistra e in basso di tre posizioni (rispetto al bordo superiore). Il secondo componente (edtFilm), invece, viene prima aggiunto a MainWindow e poi viene posizio-nato e ingrandito con il comando: edtFilm.setRect(RIGHT, SAME-1, PREFERRED+100, PREFERRED);

Questa invocazione, oltre a posizionare il componente (con allineamento a destra nella posizione SAME-1), permette la definizione della grandezza del controllo, grazie agli ulti-mi due valori, PREFERRED+100 e PREFERRED. Utilizzan-do questa tecnica di posizionamento e ridimensionamen-to dei componenti, si possono creare applicazioni in grado di ridimensionarsi automaticamente su periferiche diver-se; ed è quindi altamente consigliata. Invocando lo stesso metodo andremo a inserire e posizionare i campi di testo edtRegista, edtDurataMin, edtAnno; inoltre, andremo a siste-mare un controllo di tipo checkbox con le seguenti righe:

Check chkDVD; …add(chkDVD = new Check(“DVD”), LEFT, AFTER+2);

A questo punto, aggiungiamo tre controlli, btnIndietro, bt-nAvanti e btnInserisci, di tipo Button:

Button btnIndietro, btnAvanti, btnInserisci;

add(btnIndietro = new Button(“<”),LEFT, AFTER+2);

add(btnInserisci = new Button(“NEW”),AFTER, SAME);add(btnAvanti = new Button(“>”),AFTER, SAME);

Da notare fra doppi apici il testo assegnato a ciascun pul-sante. Il risultato è la finestra mostrata nella Figura 3.

FIGURA 3 L’interfaccia dell’applicazione Videoteca descritta nell’articolo.

Rispetto al .NET

Compact Framework

e a J2ME SuperWaba

garantisce un migliore

utilizzo della memoria e

buone prestazioni.

Page 44: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200744

focus JAVA Journal

n.4 - settembre/ottobre 2007 45

focus

Compilazione e test dell’applicazione

È quindi giunto il momento di compilare e testare l’ap-plicazione. Per la compilazione, dobbiamo aggiungere al classpath i file SuperWaba.jar e SuperWabaTools.jar che si tro-vano nella cartella SuperWabaSDK/lib. Il mio consiglio è di aggiungerli alla variabile di sistema classpath, in quanto verranno utilizzati più volte (durante la compilazione e l’esecuzione). Per maggiore chiarezza, giusto per dichiara-re in modo esplicito dove si trovano questi file, nel primo comando di compilazione della classe utilizzo il formato esteso:

javac -classpath C:\SuperWabaSDK\lib\SuperWaba.jar Videoteca.java

Una volta compilato il file e creata la classe Videoteca.class, dobbiamo eseguire ancora due passaggi:

§ creare un package che contiene la classe (utilizzando la classe Warp);

§ creare l’eseguibile (meglio se in un .cab di installazione) utilizzando la classe Exegen.

Per il primo passaggio, il comando è il seguente:

java superwaba.tools.Warp c Videoteca Videoteca.class

Questo comando crea il file Videoteca.pdb con le classi da eseguire con la VM SuperWaba: nel nostro caso solamen-te la classe Videoteca.class. È un comando che potrebbe dare qualche messaggio di errore (che al momento possiamo ignorare) durante l’esecuzione con JDK superiori all’1.3. Il secondo comando, invece, è il seguente:

java superwaba.tools.Exegen /E /Z Videoteca Videoteca

Dopo averlo lanciato, vengono creati un file .cab di in-stallazione (/Z) per ogni piattaforma disponibile nei tool SuperWaba, dei file eseguibili per PocketPC (/E) e un file batch simile a quello utilizzato per l’installazione di Hel-loWorld che installa l’applicazione via ActiveSync diretta-

mente sul PDA. Le due stringhe Videoteca alla fine del co-mando sono rispettivamente la main-class del pacchetto (Videoteca.class) e il package .pdb da utilizzare per creare il file .cab (Videoteca.pdb).

Creare e utilizzare un PDB

Un PDB, un tipo di file che abbiamo già incontrato, è un database portabile (Portable Database) che permette di ve-locizzare le operazioni di immissione e di ricerca dei dati in un dispositivo portatile. Il lavoro che esegue la VM Su-perWaba durante l’utilizzo dei PDB è analogo, in maniera meno potente rispetto alle versioni desktop, a un motore DBMS: collega al filesystem alcuni dati o indici mantenu-ti in una memoria veloce, permettendo il rapido recupe-ro delle informazioni. Per l’utilizzo dei PDB esistono delle particolari classi che permettono l’inserimento di dati in un catalogo e la lettura degli stessi tramite puntatori a re-cord. Nella Tabella 1 viene riportata una lista di classi che verranno utilizzate per scrivere e leggere i dati dal PDB.Per completare la nostra Videoteca, andremo a scrivere due ulteriori classi: la classe Film e la classe CatalogoFilm. La prima (Film) conterrà semplicemente i dati per definire un film, i metodi accessori get e set e un costruttore compren-dente tutti i dati e sarà quindi simile alla seguente:

public class Film {

private String titolo private String regista; private int anno private int durata; private boolean DVD;

public Film(String titolo, String regista, int anno, int durata, boolean DVD) { this.titolo=titolo; this.regista=regista; this.anno=anno; this.durata=durata; this.DVD=DVD; }

TABELLA 1 Classi per la lettura e la scrittura di dati sul PDB

Classe Scopo di utilizzo

Catalog Permette di creare un PDB e di posizionarsi con dei puntatori su particolari record

ResizeStream Viene utilizzata per creare un record di grandezza fissa

DataStream Classe wrapper per dati da inserire in un flusso (nel nostro esempio: un record)

Page 45: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200744

focus JAVA Journal

n.4 - settembre/ottobre 2007 45

focus

FIGURA 4 Utilizzo dell’applicazione Videoteca.

public void setTitolo { this.titolo = titolo; }

public String getTitolo { return titolo; }

// altri metodi accessori …}

La seconda classe (CatalogoFilm), invece, si preoccuperà di mantenere il catalogo dei film, compresa la posizione del record corrente e i metodi per inserire e scorrere la lista dei film. Vediamola nel dettaglio:

import waba.io.*; import waba.sys.*; import waba.util.*;

public class CatalogoFilm { private Catalog cat; private ResizeStream rs; private DataStream ds; public int indice =0; public int datiTotali; //public per comodità anche se errato!

public CatalogoFilm() throws Exception { cat = new Catalog(“FILMDB.”+Settings. appCreatorId+”.DATA”, Catalog.CREATE); datiTotali = cat.getRecordCount(); rs = new ResizeStream(cat, 256); ds = new DataStream(rs); } public Film getFilm(int indice) { cat.setRecordPos(indice); this.indice = indice; return new Film(ds.readString(), ds.readString(), ds.readInt(), ds.readInt(), ds.readBoolean()); } public void insertFilm(Film nuovoFilm) { rs.startRecord(); ds.writeString(nuovoFilm.getTitolo()); … ds.writeInt(nuovoFilm.getDurata()); … rs.endRecord(); datiTotali++; }}

La classe contiene tre istanze (di tipo Catalog, ResizeStream e DataStream) che permettono ai metodi getFilm() e insert-Film() di recuperare e scrivere dei dati all’interno del PDB. Inoltre, due dati di tipo int manterranno il numero dei dati contenuti nel PDB e l’indice del record corrente. Il costrut-

tore della classe crea il PDB all’interno della cartella dove si trova il programma. Inoltre, istanzia una variabile di tipo DataStream che contiene i dati da scrivere nel record e una di tipo ResizeStream che permette di ridimensionare a 256 byte i record che gli vengono passati. Il metodo getFilm() posiziona il puntatore su uno specifico record e, con i dati contenuti nello stesso, crea un’istanza di Film da restitui-re al metodo chiamante. I dati vengono letti con i metodi read<tipo>() forniti dalla classe DataStream. Ad esempio, readString() legge una String nel record fino a quando non incontra il terminatore di stringa “\0”; rea-dByte() legge un Byte e così via. Infine, il metodo insert-Film() inserisce un nuovo record al termine del PDB utiliz-zando i metodi write<tipo> e recuperando i dati dall’istan-za di Film che gli viene passata. Il procedimento per inseri-re un nuovo record alla fine del PDB è il seguente: 1. si apre il record con la chiamata

2. si scrivono i dati con i metodi write<tipo>()

3. si chiude il record e lo si scrive nel PDB

il che, tradotto in pseudocodice è simile al seguente esem-pio:

rs.startRecord();writeString(nuovoFilm.getDurata());rs.endRecord();

Page 46: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200746

focus

Infine, il metodo aumenta il valore datiTotali. Per utilizzare queste classi devono essere inserite alcune nuove righe nel file Videoteca. Innanzitutto, servono i metodi per inizializza-re un’istanza di CatalogoFilm:

CatalogoFilm mioCatalogo = new CatalogoFilm();

E quindi serve il metodo onEvent() che gestisce tutti gli eventi dei pulsanti dell’applicazione:

public void onEvent(Event e){ if(e.target == btnInserisci) { mioCatalogo.insertFilm(new Film( edtFilm.getText(), edtRegista.getText(), Convert.toInt(edtDurataMin.getText()), Convert.toInt(edtAnno.getText()), chkDVD.getChecked() )); } else if(e.target == btnAvanti) { mioCatalogo.indice++ %= mioCatalogo.datiTotali; visualizza(mioCatalogo.getFilm (mioCatalogo.indice)); } else if(e.target == btnIndietro) { … }}

In base al pulsante utilizzato, il metodo onEvent() utilizza

il metodo Catalogo.insertFilm() passando una nuova istanza di Film creata recuperando i dati dalle caselle di testo (se viene premuto btnInserisci); oppure modifica l’indice del re-cord corrente e lancia il metodo visualizza() per inserire i dati recuperati dal PDB nei campi della finestra (se vengo-no premuti i tasti btnAvanti o btnIndietro). Le uniche particolarità di questo metodo (rispetto alle normali applicazioni Java) sono i due utilizzi del metodo Convert.toInt() che converte una String in un int. Il metodo differisce da Integer.parseInt() in quanto la conversione vie-ne fatta utilizzando la giusta grandezza degli int per il di-spositivo su cui è stata lanciata l’applicazione. Per comple-tezza, riporto il metodo visualizza() della classe Videoteca (anch’esso con qualche omissis), che permette di visualiz-zare i dati recuperati dal PDB nel form:

private void visualizza(Film daVisualizzare) { edtFilm.setText(daVisualizzare.getTitolo()); … edtDurataMin.setText(“”+daVisualizzare. getDurata); … chkDVD.setChecked(daVisualizzare.DVD);}

Nell’applicazione finale, dopo aver completato il form del-l’applicazione, basterà premere il pulsante NEW per inse-rire un nuovo record nel database, mentre i pulsanti “<” e “>” serviranno a scorrere i titoli, come è possibile vede-re in Figura 4.

Note Biografiche

Andrea Colleoni si occupa professionalmente di sviluppo di sof-tware dal 1996 e di Java dal 2000. Attualmente svolge l’attività di consulente attraverso la sua società, coordinando gruppi di lavoro su progetti software di dimensioni medie o grandi in am-bito finanziario/bancario e industriale prevalentemente con tec-nologie legate a J2EE, ma anche con Microsoft.NET. Si occupa anche di formazione; insegna Informatica alla Facoltà di Eco-nomia dell’Università di Bergamo e in altri corsi più specifici organizzati da vari enti di formazione. Vive a Seriate in provin-cia di Bergamo con mia moglie Elena e la sua piccolina, Greta, arrivata cinque mesi fa.

La funzione eseguita

dalla VM SuperWaba

nell’utilizzo dei PDB

è analoga a quella di

un compatto motore

DBMS.

Page 47: j2007 03 jj4
Page 48: j2007 03 jj4

JAVA Journal

48 n.4 - settembre/ottobre 2007

focus JAVA Journal

n.4 - settembre/ottobre 2007 49

focus

Grafici nelle applicazioni Java

La maggior parte delle applicazioni che dobbiamo realizzare ha a che fare con i dati. Di qualsiasi genere siano, sempre dati sono: tabelle di database, file da or-ganizzare, contatti da gestire. In queste situazioni talvolta è necessario visualiz-

zare uno schema di questi dati, un report, una qualsi-voglia statistica. In Java esistono diverse librerie che permettono ciò, ma una fra tutte è quella più utilizza-ta, sia per la completezza sia per la lunga serie di fun-zionalità offerte: JFreeChart (http://www.jfree.org/jfreechart/)

JFreeChart

JFreeChart è una libreria open source realizzata ini-zialmente da David Gilbert e rilasciata sotto licenza LGPL (Lesser General Public License) che permette di utilizzarla in applicazioni commerciali. Questa li-breria consente, essenzialmente, di realizzare nelle proprie applicazioni dei grafici che rappresentano i dati da trattare e che vogliamo rappresentare in for-ma grafica. Per approfondire questo tema, grazie a JFreeChart, andremo a provare tutte le funzionalità offerte da questa libreria. Purtroppo, pur essendo un progetto open source, c’è enorme scarsità di artico-li sull’argomento (anche perché la guida ufficiale di questo progetto è a pagamento). Perciò, in questo ar-ticolo andremo a scoprire gradualmente quali sono le funzionalità disponibili.

Grafico a torta

Per introdurre il funzionamento della libreria utiliz-ziamo un classico grafico a torta. I dati su cui base-remo l’esempio sono cablati nel codice sorgente, tra-

mite variabili predefinite. In una situazione reale, i dati per la creazione dei grafici verranno gestiti di-namicamente. La classe che rappresenta il grafico a torta è DefaultPieDataset, che fa parte del package org.jfree.data.general. Si tratta di un’implementazione di default di PieDataset, un’interfaccia che specifica i metodi che qualsiasi implementazione (come appun-to lo è DefaultPieDataset) deve supportare per poter ge-stire grafici a torta all’interno di JFreeChart. Pertan-to, per un primo grafico a torta non dobbiamo far al-tro che istanziare un oggetto DefaultPieDataset e de-finire alcuni valori:

DefaultPieDataset pieDataset = new DefaultPieDataset();

pieDataset.setValue(“Java”, new Integer(55));pieDataset.setValue(“PHP”, new Integer(25));pieDataset.setValue(“C#”, new Integer(15));pieDataset.setValue(“Ruby”, new Integer(5));

In questo modo, abbiamo definito un grafico a tor-ta con quattro spicchi, specificando i valori da visua-lizzare per ogni spicchio. Un semplice programma di visualizzazione del grafico è riportato nel Listato 1. Come si osserva nell’esempio, viene prima creato l’oggetto DefaultPieDataset; successivamente, grazie alla classe ChartFactory, realizziamo il grafico vero e proprio, invocando il metodo statico createPieChart() la cui firma è:

static JFreeChart createPieChart (java.lang.String title, // titolo del diagramma PieDataset dataset, // dataset da rappresentare (oppure null) boolean legend, // presenza della legenda?

In questo articolo utilizzeremo una famosa libreria open source per la realizzazione di grafici: JFreeChart.

>> di Federico Paparoni ([email protected])

Page 49: j2007 03 jj4

JAVA Journal

48 n.4 - settembre/ottobre 2007

focus JAVA Journal

n.4 - settembre/ottobre 2007 49

focus

FIGURA 1 Grafico a torta

boolean tooltips, // presenza di tooltip da mostrare? boolean urls) // generazione di URL?

Se mandiamo in esecuzione il programma, otteniamo il ri-sultato mostrato nella Figura 1. Ma vediamo come cam-biando una semplice riga del programma possiamo varia-re la rappresentazione grafica dei dati. Come si evince dal Listato 1, il metodo utilizzato per realizzare un JFreeChart, createPieChart() di ChartFactory, prevede il passaggio di un parametro PieDataset. Scorrendo la documentazione Java-doc di JFreeChart vediamo che possiamo utilizzare la stes-sa rappresentazione dei dati per creare un grafico, sempre a torta, ma tridimensionale. Per farlo, basta invocare il me-todo createPieChart3D (la cui firma è identica al meto-do già visto):

JFreeChart chart=ChartFactory.createPieChart3D(“PieDataSet Demo”, pieDataset, true, false, false);

In questo modo abbiamo realizzato un grafico a torta tridimensionale (Figura 2). Il motivo per cui la libre-ria è organizzata in questa maniera è abbastanza com-prensibile: possiamo fare, ad esempio, un parallelismo con il pattern MVC (Model View Controller). In questo caso, i dati da gestire sono rappresentati dall’interfac-cia PieDataset (il Model). Nel momento in cui vogliamo visualizzare queste informazioni passiamo attraverso il ChartFactory che genera un JFreeChart (il View) che poi possiamo utilizzare. Nel Listato 1, dopo la creazione

del JFreeChart, abbiamo salvato questo grafico su un file, per poterlo poi visualizzare a schermo. Ciò è stato possibile attraverso la classe ChartUtilities:

try { ChartUtilities.saveChartAsJPEG(newFile (“chart.jpg”), chart, 500,300);}catch (IOException ex) { ex.printStackTrace();}

BufferedImage image = chart.createBufferedImage (500,300);

FIGURA 2 Grafico a torta tridimensionale

Page 50: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200750

focus JAVA Journal

n.4 - settembre/ottobre 2007 51

focus

Questo metodo di salvataggio dei grafici è semplice e age-vole, ma è scomodo da utilizzare se vogliamo semplice-mente visualizzare il grafico e non intendiamo salvarlo. Nei prossimi paragrafi vedremo come utilizzare ChartPanel, un pannello realizzato in JFreeChart che permette di inse-rire il grafico direttamente nell’interfaccia grafica senza il salvataggio su disco.

LISTATO 1 Classe che crea e visualizza un PieDataSet

/* * PieDatasetDemo.java */import java.awt.*;import java.awt.image.*;import java.io.*;import javax.swing.*;

import org.jfree.data.general.*;import org.jfree.chart.*;

public class PieDatasetDemo extends JFrame { public PieDatasetDemo() { DefaultPieDataset pieDataset = new DefaultPieDataset(); pieDataset.setValue(“Java”, new Integer(55)); pieDataset.setValue(“PHP”, new Integer(25)); pieDataset.setValue(“C#”, new Integer(15)); pieDataset.setValue(“Ruby”, new Integer(5)); JFreeChart chart=ChartFactory.createPieChart (“PieDataSet Demo”,pie Dataset, rue,false,false); try { ChartUtilities.saveChartAsJPEG(new File(“chart.jpg”), chart,500,300); } catch (IOException ex) { ex.printStackTrace(); }

BufferedImage image = chart.createBufferedImage(500,300); JLabel lblChart = new JLabel(); lblChart.setHorizontal- Alignment(JLabel.CENTER); lblChart.setVertical-Alignment(JLabel.CENTER); lblChart.setIcon(new ImageIcon(image));

this.getContentPane().set-Layout(new BorderLayout()); this.getContentPane().add-(lblChart, BorderLayout.CENTER); this.setSize(600,400); this.setVisible(true);

} public static void main(String[] args) throws Exception { PieDatasetDemo pieDatasetDemo = new PieDatasetDemo(); }}

Istogramma

Appreso il meccanismo di base di ge-nerazione dei grafici tramite JFree-Chart, passiamo a un altro interessan-te esempio di utilizzo: andremo a crea-re un Dataset (che rappresenta i dati) e a mostrarli in un istogramma. La classe che permette di creare insiemi di dati per questo tipo di rappresenta-zione è DefaultCategoryDataset, che im-plementa l’interfaccia CategoryDataset. Utilizzando questa classe possiamo definire i dati che andranno rappre-sentati dall’istogramma. Nel Listato 2 è riportato un esempio di generazione di un grafico di questo tipo. Come nel caso dei diagrammi a torta, dobbiamo popolare il Dataset con dei valori. Il ri-sultato dell’esecuzione del program-ma è mostrato in Figura 3. In questo caso, abbiamo voluto visualizzare l’an-damento agli esami degli studenti Pip-po e Pluto. Per ogni studente sono sta-ti inseriti tre diversi valori (prima pro-va, seconda prova e orale). Queste infor-mazioni sono state inserite nel Dataset, unitamente al voto ottenuto dagli stu-denti (il valore sull’asse delle ordinate di ciascun istogramma)

dataset.addValue(6.0, series1, category1);

dataset.addValue(9.0, series1, category2);

dataset.addValue(7.0, series1, category3);

dataset.addValue(8.0, series2, category1);

dataset.addValue(7.0, series2, category2);

dataset.addValue(8.0, series2, category3);

Per creare l’istogramma si ricorre al metodo createBarChart() di ChartFactory la cui firma è:

static JFreeChart createBarChart (java.lang.String title,

java.lang.String categoryAxisLabel, // etichetta asse dominio java.lang.String valueAxisLabel,

// etichetta asse valori CategoryDataset dataset, PlotOrientation orientation, // orientamento orizz/vert boolean legend, boolean tooltips, boolean urls)

Page 51: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200750

focus JAVA Journal

n.4 - settembre/ottobre 2007 51

focus

FIGURA 3 Istogramma

Per cui, nel nostro caso scriveremo:

JFreeChart chart=ChartFactory.createBarChart (“Istogramma”, “Esame”, “Voto”, dataset, PlotOrientation.VERTICAL, true,true,false);

Ed infine abbiamo utilizzato la classe ChartPanel per ag-giungere il grafico direttamente nella nostra interfaccia

ChartPanel chartPanel = new ChartPanel(chart);

chartPanel.setPreferredSize(new Dimension (500, 300));setContentPane(chartPanel);setVisible(true);

Anche in questo caso abbiamo seguito gli stessi passi effet-tuati per il diagramma a torta: creazione del dataset, po-polamento del dataset, creazione del JFreeChart attraver-so ChartFactory e visualizzazione. Per visualizzare altri grafici, che possono essere generati a partire dal codi-ce del Listato 2 senza effettuare troppi cambiamen-ti, basta modificare il metodo utilizzato per la gene-razione del JFreeChart. Ad esempio, andiamo a riscri-vere il codice sostituendo l’invocazione del metodo di ChartFactory con la seguente riga:

JFreeChart chart=ChartFactory.createBarChart3D (“Istogramma 3D”,”Esame”,”Voto”, dataset,PlotOrientation. HORIZONTAL, true,true,false);

Così facendo, abbiamo modificato il grafico in un istogramma 3D e abbiamo modificato l’orientamento selezionando il valore PlotOrientation.HORIZONTAL.

Il risultato di questo cambiamento è visibile nella Figu-ra 4.

Grafici dal database

Come abbiamo detto precedentemente, JFreeChart offre una vasta gamma di servizi per la rappresentazione grafi-ca dei dati. Un caso molto comune è avere dei dati memo-rizzati in un database da visualizzare graficamente. All’in-terno di JFreeChart troviamo un package che fa proprio al caso nostro: org.jfree.data.jdbc. In questo package sono sta-ti definiti tre diversi Dataset, simili a quelli già visti ma che riescono a caricare le informazioni dal database. Ciò che avviene in queste classi è molto semplice (così come avremmo fatto se JFreeChart non offrisse questa funzio-nalità): a questi Dataset vengono passati come parametri una connessione JDBC e una query SQL. Il Dataset effettua la query sul DB e memorizza le informazioni restituite. Il passo successivo è visualizzare questi dati, come abbiamo

FIGURA 4 Istogramma tridimensionale orientato in orizzontale

Page 52: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200752

focus JAVA Journal

n.4 - settembre/ottobre 2007 53

focus

LISTATO 2 Classe che crea e visualizza un CategoryDataSet

fatto precedentemente. Come risultato abbiamo un grafico dei dati con poche e semplici righe di codice:

Connection conn = DriverManager.getConnection (db, username, password);JFreeChart chart; String sql = “select val1, val2 from table”; JDBCXYDataset chartData = new JDBCXYDataset (conn, sql); xyData = (XYDataset) chartData; chart = ChartFactory.createXYLineCha (“”, “”, “”, xyData, PlotOrientation.HORIZONTAL,true, true, false);

JFreeChart e applicazioni Web

Gli esempi visti finora ri-guardano sempre applica-zioni desktop in cui uti-lizziamo JFreeChart. Però, l’utilizzo di questa libreria si rivolge anche alle appli-cazioni Web, ed ora vedre-mo come inserire un gra-fico in una semplice appli-cazione Java Server. I gra-fici che abbiamo generato, per il momento, sono stati salvati su file (primo esem-pio con grafico a torta) o visualizzati attraverso un componente ad hoc (se-condo esempio con l’isto-gramma). Vediamo quindi la prima parte della nostra applicazione Web, una JSP dove creiamo un diagram-ma a torta 2D:

<%@page contentType=”text/html”%><%@ page import=”com. java staff.stats.*” %><%@ page import=”java.util.*” %><%@ page import=”org.jfree.data.general. DefaultPieDataset” %><%@ page import=» org.jfree.chart.*» %><html> <head> <title>Demo Web</title> </head> <body>

<% DefaultPieDataset pieDataset = new DefaultPieDataset(); pieDataset.setValue(“Java”, new Integer(55)); pieDataset.setValue(“PHP”, new Integer(25)); pieDataset.setValue(“C#”, new Integer(15)); pieDataset.setValue(“Ruby”, new Integer(5)); JFreeChart chart = ChartFactory. createPieChart(“Demo Web”, pieDataset,true,false,false); application.setAttribute(“chart”,chart);

import java.awt.*;import java.awt.image.*;import java.io.*;import javax.swing.*;

import org.jfree.data.category.*;import org.jfree.chart.*;import org.jfree.chart.plot.*;

public class CategoryDemo extends JFrame { public CategoryDemo() { setSize(500,300); final String series1 = “Pippo”; final String series2 = “Pluto”;

final String category1 = “Prima prova”; final String category2 = “Seconda prova”; final String category3 = “Orale”;

final DefaultCategoryDataset dataset = new DefaultCategoryDataset();

dataset.addValue(6.0, series1, category1); dataset.addValue(9.0, series1, category2); dataset.addValue(7.0, series1, category3);

dataset.addValue(8.0, series2, category1); dataset.addValue(7.0, series2, category2); dataset.addValue(8.0, series2, category3);

JFreeChart chart=ChartFactory.createBarChart (“Istogramma”, ”Esame ”,”Voto”, dataset,PlotOrientation.VERTICAL, true,true,false); final ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPreferredSize(new Dimension(500, 300)); setContentPane(chartPanel); setVisible(true); } public static void main(String[] args) throws Exception { CategoryDemo categoryDemo = new CategoryDemo(); }}

Page 53: j2007 03 jj4

JAVA Journal

n.4 - settembre/ottobre 200752

focus JAVA Journal

n.4 - settembre/ottobre 2007 53

focus

%> <IMG src=»ChartServlet»> </body></html>

In questa JSP abbiamo creato un grafico e abbiamo salvato l’oggetto JFreeChart nell’oggetto implicito application (ov-vero il Context della Web Application). In questa pagina, abbiamo demandato la creazione del grafico ad una Serv-let, anche perché non avremmo potuto includere l’imma-gine utilizzando solo questa JSP, perché il ContentType del-la pagina è semplicemente HTML e, quindi, non avremmo potuto aggiungere un contenuto come un’immagine. La Servlet ChartServlet in questo caso dovrà generare il grafi-co, prendendo l’oggetto JFreeChart dal contesto e stampan-do in output l’immagine, come nel caso in cui viene salva-ta su file. Qui di seguito viene riportato il metodo doGet() di ChartServlet

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

JFreeChart chart = (JFreeChart)getServlet Context().getAttribute(“chart”); response.setContentType( “image/png” ); BufferedImage buf = chart.createBufferedImage (640, 400, null); PngEncoder encoder = new PngEncoder( buf, false, 0, 9 ); response.getOutputStream().write( encoder.pngEncode() ); }

Come si è detto, l’oggetto JFreeChart viene recuperato dal contesto dell’applicazione. Viene quindi impostato il con-tent type della risposta come image/png, e viene creata un’immagine e viene scritta nello stream di output.

Conclusioni

JFreeChart è un’ottima libreria per la generazione di gra-fici in Java. Navigando tra la documentazione Javadoc (l’unica ufficialmente disponibile) è possibile scovare pia-no piano molte caratteristiche interessanti per le nostre applicazioni. Esistono moltissime tipologie di grafico, mo-dificabili fin nei minimi dettagli: possiamo cambiare colo-ri, font, immagini di sfondo. Ad esempio, un’altra tipologia di grafico realizzabile attraverso questa libreria è il Gantt, definito nel package org.jfree.data.gantt, come potete vedere in Figura 5 che visualizza uno degli esempi di JFreeChart. Chiaramente l’utilizzo di questa libreria può essere un no-tevole valore aggiunto per le nostre applicazioni.

FIGURA 5 Grafico per la visualizzazione di un Gantt

Note Biografiche

Federico Paparoni si occupa prevalentemente di sviluppo sulle piattaforme JavaME e JavaEE. Gestisce il portale JavaStaff.com per la pubblicazione di notizie e articoli sul mondo Java.

Page 54: j2007 03 jj4
Page 55: j2007 03 jj4

SPEECH Login TopicFREE

JJ: Quando avete pensato di realizzare il progetto JUG Avis?

FG: È necessaria una piccola premessa: ai primi del 2005, abbia-mo percepito che il nostro JUG dovesse fare un salto di qualità. Andare oltre la consueta attività didattico-formativa per appas-sionati, tipica di ogni JUG, per applicare le nostre conoscenze in un progetto comune. Dedicando il nostro tempo non al solito progetto per ipertecnici (librerie, framework, ecc.) ma al “mon-do reale”. Costruire qualcosa di utile, semplice e di grande effet-to, ovviamente in Java! Da là, l’idea di sviluppare un’applicazio-ne che facilitasse la comunicazione tra i Centri AVIS ed i dona-tori di sangue (per emergenze, scadenze di donazioni, solleciti) è stata quasi immediata, poiché molti di noi, me compreso, sono donatori. In Sardegna l’emergenza sangue è molto sentita. Al-l’inizio, da tecnici entusiasti, ipotizzammo un “sistemone” che faceva un sacco di cose. Poi, grazie al fondamentale aiuto del Centro AVIS di Sestu, che ha svolto il ruolo di Centro Pilota, abbiamo capito meglio cosa realmente serviva e come organiz-zarci. Ad esempio, una cosa a cui non avevamo pensato inizial-mente, è che una migliore capacità di comunicazione (via SMS, email, eccetera) è utile ai Centri anche per la normale vita asso-ciativa, in occasione di assemblee, convocazioni e anche... augu-ri di Natale! Il nostro applicativo, che grazie a Java ed ai Web Service consente ai Centri di scegliere in autonomia i propri for-nitori SMS, è stato letteralmente calzato sulle loro esigenze. Ma nulla di più, se non fargli risparmiare tempo e denaro. È gente estremamente concreta, che contribuisce a salvare le vite uma-ne: in tali contesti la “fuffa”” serve a poco. Infine, la ciliegina sulla torta è stata l’installazione presso il più importante ospe-dale della Sardegna, che gestisce un proprio Centro Trasfusiona-le. Non solo AVIS, dunque, ma anche Sanità Pubblica, che ov-viamente ha le sue specificità. È stata una sfida affascinante.

JJ: Massimiliano, qual’ è l’architettura del software JUG Avis? Quali tecnologie avete utilizzato?

MD: L’architettura del Jug Avis Web è three layer (Figura 1), costruita utilizzando Spring. Spring MVC e JSP-JSTL per il layer di presentazione, dei POJO gestiti da Spring con transa-zioni AOP per il layer business logic e iBATIS per il data layer. L’importazione dei donatori può avvenire tramite file .csv o file Excel, l’esportazione con Jasper Report in pdf, csv, xls e html. Axis viene usato per l’invocazione dei web service già imple-mentati dalla versione Swing, per quelli di nuova costruzione XFire. Per l’invio delle mail abbiamo utilizzato javamail, Rome per i feed Rss, mentre per le statistiche con i grafici JFreeChart. Il database è Postgres (Figura 2). L’applicazione consente un

Nel primo numero di Community Watch abbiamo introdotto la community Java italiana (intesa come insieme delle communi-ty locali e tematiche del nostro Paese): numerosa, vivace e ap-passionata, raduna i programmatori della penisola, organizzan-do eventi e promuovendo progetti di sviluppo. Viste le molte-plici iniziative in corso, avremo modo di dare spazio a tutti in questa rubrica. Questo mese presentiamo il Java User Group Sardegna Onlus, che l’anno scorso è stato premiato per il progetto JUG-AVIS du-rante la JavaOne Conference a San Francisco con il prestigioso Duke Award. Per parlare del gruppo e del progetto abbiamo in-tervistato due dei fondatori del JUG Sardegna: Fabrizio Gian-neschi e Massimiliano Dessì.Fabrizio è presidente del JUG, Java Champion e coor-dinatore della Community dei JUG su java.net (http://www.jugsardegna.org/vqwiki/jsp/Wiki?FabrizioGianneschi). Massimiliano è co-fondatore e consigliere del JUG, coordina-tore degli User Group Italiani su Spring, Jetspeed e Groovy, at-tualmente è consulente presso Centro Servizi della Regione Au-tonoma della Sardegna (http://wiki.java.net/bin/view/People/MassimilianoDessi).

JJ: Fabrizio, com’è nato il JUG Sardegna?

FG: Il JUG Sardegna nasce nei primi mesi del 2002, da un’idea mia e di alcuni amici, tra cui Max, dato che al tempo la Sar-degna era priva di gruppi dedicati a Java. Iniziammo subito a contattare potenziali interessati, ed in breve mettemmo in pie-di una mailing list, che ancora oggi è il nostro principale mez-zo di comunicazione interna. Fondamentale fu l’aiuto dell’Uni-versità. Il successo fu immediato e tra alti e bassi siamo a strut-turarci sempre meglio. Dal 2005 siamo infatti un’Associazione e dal 2006 siamo iscritti al Registro del Volontariato della no-stra Regione.

COMMUNITY

n.4 - maggio/ottobre 200755

COMMUNITY WATCH Ü di Stefano Sanna ([email protected])

Note Biografiche

Stefano Sanna si occupa di sviluppo di applicazioni multi-mediali per piattaforma Savaje presso Beeweeb Technolo-gies (http://www.beeweeb.com). Ha lavorato per sette anni nel gruppo Network Distributed Applications del CRS4, oc-cupandosi di mobile computing e applicazioni network-orien-ted per cellulari e PDA. Collabora attivamente con JIA, JUG Sardegna e Java Mobile Developers Forum. Il sito sito web personale è http://www.gerdavax.it

Page 56: j2007 03 jj4

LINUXSPEECH Login TopicFREE COMMUNITY

utilizzo centralizzato dei centri di donazione. Ognuno ha i suoi dati accessibili solo al coordinatore del centro, il quale può av-visare i donatori tramite sms, mail e feed rss, può gestire i dati dei donatori, importandoli o esportandoli nel formato oppor-tuno, e può visualizzare le statistiche delle comunicazioni per gestire al meglio ad esempio l’acquisto degli sms, che in questo modo possono essere acquistati congiuntamente con altri cen-tri ottenendo prezzi più favorevoli. La versione swing standa-lone utilizza hypersonic per conservare i template dei messag-gi, e axis per la spedizione via web-service dei messaggi. L’ap-plicazione importa da file csv i cellulari dei donatori e invia un messaggio che viene scritto dal responsabile del centro, vengo-no conservati vari template con i messaggi.

JJ: Quali sono state le maggiori difficoltà incontrate?

MD: I “clienti” non sanno esattamente cosa vogliono! Scherzi a parte, è importante che in caso di invio, se l’applicazione va giù per qualsiasi motivo, non si perdano le “code” di spedizio-ne delle mail o degli SMS: quindi ci sono dei sistemi di sche-duling, salvataggio e successivo recupero. Naturalmente l’ap-plicazione deve essere testata automaticamente dal DB alle in-terfacce utente.

JJ: Ricevere il Duke Award è di grande prestigio, ma anche grande emozione: ci racconti com’è andata?

FG: Beh, in poche parole ... da Sestu (CA) ai grattacieli della

California! Il Duke Award è stato all’inizio solo una scommessa fatta così per caso (mai avrei pensato infatti che potessimo vin-cere) ed alla fine si è trasformato in uno dei più bei ricordi del-la mia vita. Siamo stati infatti il primo JUG al mondo, ed i pri-mi in assoluto in Italia anche contando le aziende, a vincerlo. E vincerlo così, con un’applicazione apprezzata non tanto dal punto di vista tecnico ma per quello che è stato sin dall’inizio il nostro obiettivo, cioè l’utilità, l’innovazione applicata al socia-le, è stato grandioso. L’ennesima dimostrazione della tanto mi-tizzata “creatività italiana”, ma anche, consentitemelo, un gran-de orgoglio come sardo. Ho avuto l’opportunità di ricevere il premio da James Gosling, di conoscere un sacco di gente (il Ja-vaOne è una vera e propria Babele) e di stabilire rapporti im-portanti per il nostro JUG, in una “5 giorni” in cui avrò dormi-to meno di tre ore a notte. Raccontare tutti i dettagli portereb-be via troppo spazio; chi fosse interessato può leggere un reso-conto dell’avventura sul mio blog: http://www.jroller.com/page/bitog?entry=l_avventura_del_duke_s JJ: Quali saranno le prossime tappe?

MD: Per l’aspetto tecnico, una volta terminata l’intera infra-struttura, test automatici compresi, si cercherà di introdurre in-terfacce utente che utilizzano AJAX, e come novità si proverà ad aggiungere funzionalità di comunicazione VOIP per le quali si è offerta una società con competenze nel settore. Per l’aspetto organizzativo, cercare volontari che possano lavorare con conti-nuità per abbreviare i tempi di sviluppo.

n.4 - maggio/ottobre 2007 56

Page 57: j2007 03 jj4

Non perdertiComputer Programming

di Settembre!Ordinalo direttamente da

www.infomedia.it

Non perdertiComputer Programming

di Settembre!Ordinalo direttamente da

www.infomedia.it

Page 58: j2007 03 jj4