Você está na página 1de 64

www.infomedia.

it EDITORIALE

JAVA Journal
BIMESTRALE - ANNO 1 - N.3

DIRETTORE RESPONSABILE
Ajax: ritorno
MARIALETIZIA MARI
(MMARI@INFOMEDIA.IT)

DIRETTORE ESECUTIVO
MICHELE SCABARRÀ
al passato
(MICHELE.SCIABARRA@JAVAJOURNAL.IT)

EDITORIAL BOARD
Tempi complicati per noi programmatori Java, almeno per chi ha voglia di indiriz-
UGO LANDINI, STEFANO SANNA, zare la propria carriera in una direzione ben precisa. Fino a poco tempo fa non c’era
F A B I O S T A R O , TO N Y M O B I L Y dubbio che programmare in Java spesso significava programmare per il Web.
Oggi le cose si sono fatte meno certe: da un lato assistiamo allo sviluppo della piatta-
REDAZIONE forma Micro Edition, dall’altra all’attecchire di Java come piattaforma di sviluppo a
MIRELLA DI GIROLAMO tutto tondo, quindi perfettamente accettabile anche per applicazioni Desktop (cosa
fino a quale anno fa una via di mezzo tra follia ed eresia).
COLLABORATORI Allora, cosa siamo diventati? In un certo senso, lo sviluppo di Java è omogeneo con
MATTEO BACCAN lo sviluppo del Web. Java è prima di tutto e soprattutto, un linguaggio multipiat-
ANDREA COLLEONI taforma. Il terreno fertile per la prima ondata è stato quello della programmazione
JACOPO GIUDICI Web, con la sua moltitudine di server di tipo diverso.
UGO LANDINI Ma il Web è cresciuto, è diventato pervasivo, onnipresente, omnicomprensivo. Via
FE D E R I C O PA P A R O N I http ci passa di tutto, che siano file, email o transazioni di qualunque tipo. E quindi
STEFANO SANNA le applicazioni che in qualche modo hanno a che fare con il Web si sono moltiplicate.
ROBERTO SIDOTI Per esempio le applicazioni mobili, per chi lavora nell’ambiente Micro Edition, sono
FA B I O S T A R O in realtà nella maggior parte dei casi client di applicazioni Web, o browser specia-
D O M E N I C O VE N T U R A lizzati di servizio Web. Lo stesso si può dire di molte applicazioni Desktop scritte in
LUIGI ZANDERIGHI Java, che si collegano in qualche modo, soprattutto usando i Web Service, a qualche
sito web per scambiare informazioni. Sono quindi dei cosiddetti “rich-client”.
I rich-client in realtà sono la ri-edizione del vecchio modello client-server di molti
anni fa, con gli elementi innovativi del supporto multipiattaforma e dell’essere di-
stribuiti su rete geografica anziché locale. Ma il problema è che i rich-client sono
delle applicazioni Desktop che vanno installate. E non sempre conviene. Aumenta i
costi di manutenzione, e non di poco.
GRUPPO EDITORIALE INFOMEDIA SRL Il web si è dimostrato da molto tempo migliore, con le sue pagine HTML che in
V I A V A L D E R A P. 1 1 6 pratica sono pezzi di una applicazione che non richiedono di essere installate, ma
5 6 0 3 8 PO N S A C C O ( P I ) I T A L I A vengono caricate on-demand.
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2 A voler proprio fare analogie, le applicazioni Web sono la riedizione dei vecchi ter-
E-MAIL INFO@INFOMEDIA.IT minali a carattere, in cui comandava il server e il terminale non faceva altro che
S I T O W E B W W W. I N F O M E D I A . I T “obbedire” visualizzando le informazioni. Una comodità preziosa che si è persa con
l’avvento delle GUI. Naturalmente la relativa staticità del modello Web, che prose-
gue inesorabilmente, pagina dopo pagina, ha sempre sofferto della scarsa interatti-
DIREZIONE vità rispetto alle applicazioni GUI.
N A T A L E FI N O (NFINO@INFOMEDIA.IT) A chiudere il cerchio sembra averci pensato la riscoperta del JavaScript potenziato
con la necessità di non dover ricaricare le pagine, e arricchito di un formato dati, che
CONTATTI in teoria sarebbe l’XML (e che in pratica è più spesso il JSON).
Ma l’acronimo AJAX è orami rimasto incollato nelle nostre menti per descrivere la
TE C H N I C A L B O O K tecnica di Asincronous Javascript And XML. L’idea è semplice, l’implementazione è
(BOOK@INFOMEDIA.IT) complessa. Questa tecnica è in pratica il ritorno alle origini. Quasi subito nell’html
è stato aggiunto il javascript, dotato poi della capacità di cambiare la pagina senza
MARKETING & ADVERTISING ricaricarla (il vecchio DHTML). Ma tra Java applet prima, Flash dopo, e nel mezzo
SEGRETERIA: 0587736460 tanta confusione, ci si era dimenticati del fatto che tutto questo si poteva fare sem-
MARKETING@INFOMEDIA.IT plicemente in JavaScript. Ci ha pensato Google a ricordarcelo, con il suo approccio
AMMINISTRAZIONE a riconsiderare in maniera nuova quello che già c’è. E Google Maps e Gmail ci
(AMMINISTRAZIONE@INFOMEDIA.IT) hanno mostrato che si possono realizzare applicazioni quasi desktop usando solo il
JavaScript.
SEGRETERIA La quantità di librerie che sono venute fuori in pochi anni è sconvolgente. Anche se
(INFO@INFOMEDIA.IT) ancora non è chiaro chi o cosa prevarrà o diventerà pervasivo. Il nostro speciale cerca
comunque di indagare su questi aspetti e si occupa in dettaglio degli strumenti ad
GRAFICA oggi più importanti per trattare questa tecnica.
STEFANO BELLANI Concludo con due comunicazioni di servizio. La prima è l’entrata di Fabio Staro
(GRAFICA@GRUPPOINFOMEDIA.IT) nell’editorial board, con la sua nuova rubrica Orizzonti Enterprise. E la seconda è la
decisione di offrire il Video Corso Java a tutti gli abbonati a JavaJournal, senza più
limitazioni di data di abbonamento. Basta abbonarvi e richiederlo, e vi sarà dato
UFFICIO ABBONAMENTI l’accesso.
TE L 0 5 8 7 7 3 6 4 6 0 F A X 0 5 8 7 7 3 2 2 3 2
ABBONAMENTI@INFOMEDIA.IT
W W W. I N F O M E D I A . I T
Michele Sciabarrà
JAVA E TUTTI I MARCHI DERIVATI Direttore Esecutivo
SONO MARCHI O MARCHI REGISTRATI Java Journal
DI SUN MICROSYSTEMS, INC. NEGLI
U S A E I N A L T R I PA E S I . I L G R U P P O
EDITORIALE INFOMEDIA È INDIPEN-

n.3 - marzo/aprile 2007 3


JAVA Journal numero 3

SOMMARIO Marzo/Aprile 2007

Speciale AJAX
AJAX e Java:un’accoppiata vincente
di Luigi Zanderighi 8
AJAX facile con prototype.js
di Domenico Ventura 14
Google Web Toolkit
di Jacopo Giudic 20

Educational
Introduzione agli EJB 3.0 - Prima parte
di Fabio Staro 31
Tutto Java in un Hello World
di Federico Paparoni 40

Focus
Introduzione a Struts
di Andrea Colleoni 47
Programmazione AOP con AspectJ
di Matteo Baccan 54

Rubriche
Orizzonti Enterprise
Tutto ciò che è tendenza nel mondo JEE
di Fabio Staro 28

Idiomatica
Tutto ciò che è tendenza nel mondo JEE
di Ugo Landini 61

n.3 marzo/aprile 2007


I NV E
IN VE TI
TR RN
INAA
Il manuale del giovane Special Edition
hacker Using Microsoft®
3. ed. Windows® Vista
di W. Wang di R. Cowart, B. Knittel

Il testo, completamente rivisto e


aggiornato dal punto di vista dei Il libro offre una vasta gamma
contenuti, ma inalterato dal punto di consigli per IT managers che
di vista dell’informazione e del- vogliamno sviluppare Windows in
l’esposizione dei concetti, prende maniera semplice ed efficiente.
Tecniche Nuove in considerazione tutti gli ultimi Que Vengono mostrate le caratteristi-
416 pp - 19,90 Euro sviluppi in fatto di attacchi e frodi 1512 pp - 44,95 Euro che per il setup di rete, hardware
ISBN 8848120059 digitali. ISBN 9780789734723 incluso.

La parte abitata della Rete Visual Basic® 2005


di S. Maistrello La Guida Completa
di Ron Petrusha

Ogni argomento viene spiegato


illustrando la sintassi dei comandi,
riportando esempi di codice ed
esempi di programmi reali. Le
Il libro prende avvio dalla geografia appendici, disponibili online, con-
del mondo digitale ed esamina gli tengono informazioni su costanti
strumenti con cui se ne acquisisce ed enumerazioni, compilazione di
la residenza, per poi approfondire applicazioni dalla riga di comando
i processi che determinano i com- e conversione dei dati. Il libro può
portamenti online, i meccanismi trovare la sua collocazione sulla
Tecniche Nuove della collaborazione e il modo in Mc Graw Hill scrivania di ogni programmatore,
184 pp - 14,90 Euro cui si misurano i benefici individuali 930 pp - 60,00 Euro sia per la fase di codifica sia per
ISBN 9788848119726 e collettivi. ISBN 9788838644696 quella di debug.

Ajax on Java Effective Prototyping for


di S. Douglas Olson Software Makers
di J. Arnowitz, M. Arent
e N. Berger

Una guida pratica pensata per gli Il libro, ricco di illustrazioni a co-
sviluppatori Java. lori e di esempi, offre linee guida
Il libro mira a rendere le applica- spiegate nel dettaglio per 9 comuni
zioni web in Java più responsive e tecniche di prototipazione.
O’Reilly dinamiche; include strategie per Morgan Kaufmann I template e le risorse citate nel
228 pp - 32,00 Euro integrare Ajax in applicazioni JSP e 624 pp - 57,40 Euro testo sono disponibili sul Web per
ISBN 9780596101879 JSF e per usare Ajax con Struts. ISBN 9780120885688 il riutilizzo.

HTML, XHTML e CSS Beginning JBoss®


di E. Castro Seam: From Novice to
Professional
di di J. F. Nusairat

Con questa guida, best-seller as- Il libro introduce i fondamenti di JSF


soluto alla sesta edizione originale, and EJB 3 che Seam usa. Offre in-
scoprirete che standardizzazione formazioni sia di base che avanzate
non significa monotonia e unifor- sulle funzioni e sui tools di Seam.
mità, e che la creazione di siti web L’autore e’ uno sviluppatore esperto
Tecniche Nuove Apress di Java/J2EE, da anni consulente
456 pp - 34,90 Euro creativi ma rigorosi è davvero possi- 376 pp - 49,50 Euro
bile, anzi: è facile e divertente! per applicazioni Java innovative e
ISBN 9788848119146 ISBN 1590597923 robuste.

6 n.3 - marzo/aprile 2007

10 Computer Programming - n. 167 - Aprile 2007


JAVA JOU
CRPN1A6L7 3
Founders at Work: Stories JavaServer(TM) Faces
of Startups’ Early Days La Guida Completa
di J. Livingston di C. Schalk e E. Burns

Il volume si apre con un’introdu-


zione che consente di creare con
Il testo presenta una collezione di la massima rapidità una prima
interviste ai grandi dell’informatica, applicazione JSF. Quindi esamina
persone che oggi sono celebrità: in dettaglio ogni singolo aspetto di
fondatori come Steve Wozniak (Ap- JSF: il ciclo di vita per l’elaborazio-
ple), Caterina Fake (Flickr), Mitch ne delle richieste, la navigazione fra
Kapor (Lotus), Max Levchin (PayPal) le pagine, lo sviluppo di componen-
e Sabeer Bhatia (Hotmail) raccon- ti, AJAX (Asynchronous JavaScript
Apress tano idee e scommesse del tempo Mc Graw Hill and XML), le attività di conversione/
456 pp - 35,00 Euro in cui hanno iniziato a metter su le 780 pp - 56,00 Euro convalida, la localizzazione e la
ISBN 1590597141 proprie aziende. ISBN 9788838644726 sicurezza.

Windows Vista Scrivi


Scrivi book@infomedia.itspecificando
Scriviaaabook@infomedia.it
book@infomedia.it specificando
specificando
The Definitive Guide nell’oggettodella
nell’oggetto
nell’oggetto dellae-mail:
della e-mail:
e-mail:
di W. R. Stanek
IN VETRINA
IN VETRINA Computer JAVA
Java Journal n.32n. 167
JOURNAL
Programming
OPPURE
OPPURE
OPPURE
inviaciilililcoupon
inviaci
inviaci couponalal
coupon alnumero
numerodidi
numero difax 0587/732232
fax0587/732232
fax 0587/732232

Potraiacquistare
Potrai
Potrai acquistarei ilibri
acquistare i libri
libriqui
quiriportati
qui riportati
riportati
Una guida completa per migliorare conuno
con
con uno SCONTOECCEZIONALE
unoSCONTO
SCONTO ECCEZIONALE
ECCEZIONALE
le prestazioni del sistema operativo
e per la manutenzione del computer del
del 10%anche
10%
del10% anchesese
anche seacquisti
acquistisolo
acquisti soloun
solo unlibro
un libro
libro
O’ Reilly
942 pp - 47,20 Euro indipendentemente dalla versione OPPURE
OPPURE
OPPURE
di Windows Vista posseduta.
ISBN 9780596528003
del 20%
20%sese
del20%
del acquisti33
seacquisti
acquisti 3libri
libri
libri

JAVA JOURNAL
CP 167 3
speciale AJAX JAVA Journal

AJAX e Java:
un’accoppiata
vincente
Capire come funziona AJAX non è un optional

>> di Luigi Zanderighi (luigi.zanderighi@javajournal.it)

JavaScript

D
Il primo passo per capire AJAX è studiarne le tecno-
opo mesi di scetticismo e perplessità logie abilitanti, ossia le tecnologie che messe insieme
su AJAX, avete finalmente deciso di rendono possibile sviluppare con la tecnica AJAX.
fare il grande passo e introdurre que- Partiamo con dal ruolo di Javascript lato client. Già
sta tecnologia all’interno di un nuovo alla fine degli anni ’90 si faceva uso di DHTML, ma
progetto. Senza preoccuparvi di come l’uso di Javascript non ha mai trovato ampio con-
funziona il meccanismo sottostante senso per mancanza di standard. Negli ultimi tempi
avete scaricato uno script che fa al caso vostro. Ma il divario tra le API e le funzionalità offerte dai vari
ora sudate freddo. Le cose non funzionano. Lo script browser si è notevolmente ridotta e ora si può conta-
che avete scaricato per qualche motivo si è rotto e re su un insieme molto esteso di funzioni sovrappo-
non sapete dove mettere le mani. Prima era sempli- nibili. Questa sovrapposizione non è ancora completa
ce, ora con AJAX in mezzo non si capisce dove può e tutti gli script devono tenerne conto.
essere il problema. Capite che è giunto il momento La grossa differenza, che ha sempre contraddistinto
di fare ciò che avete evitato fino ad ora: capire come MS Internet Explorer dagli altri browser, è il modo
funziona AJAX. con cui si recupera il riferimento di un elemento a cui
è stato assegnato un id all’interno del codice HTML,
AJAX, a differenza delle altre tecnologie con cui ossia:
siamo abituati a trattare, non gode di specifiche
tecniche: in effetti AJAX non è né un linguaggio né document.getElementById(id)
un framework, ma definisce una tecnica di sviluppo
costituita da un insieme di tecnologie. oppure
AJAX significa letteralmente Asynchronous Java-
script and XML, e nasce dall’unione di HTML, Java- document.all[id]
script, dell’oggetto XMLHttpRequest (XHR) e di una
o più tecnologie lato server. Per mascherare questa diversità, di solito si fa uso
Un grosso limite dell’HTML è sempre stato la man- di uno script “wrapper” che contempla ambedue le
canza di comunicazione tra client e server. Microsoft precedenti notazioni.
per prima ha aggirato questo problema già nei brow- Il frammento che segue è un esempio di codice Java-
ser IE4, con il controllo ActiveX Microsoft.XMLHTTP. script in grado di recuperare gli elementi indipenden-
Nell’Aprile 2006 il consorzio W3 ha rilasciato le temente dal browser:
specifiche per l’oggetto XHR che definisce le API che
forniscono le funzionalità di trasferimento dati tra // Funzione per recuperare un elemento dall’id
client e server, aprendo così ufficialmente le porte
alla interoperabilità tra client e server. function getElement(id) {
var element;

8 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

TABELLA 1 Stati dell’oggetto XMLHttpRequest ricavabili dalla proprietà onreadystatechange

Valore Stato Descrizione


0 Uninitialized Non è stato ancora richiamato alcun metodo
1 Open È stato richiamato il metodo open() ma non il metodo send()
2 Sent È stato richiamato anche il metodo send()
3 Receiving Viene ricevuta la risposta del server
4 Loaded La risposta è stata interamente letta

if(document.getElementById) indirizzate solo verso la URL da cui proviene il Javascript


element = document.getElementById(id); che esegue la chiamata remota.
else Questa limitazione porta ad una considerazione impor-
element = document.all[id]; tante: deve necessariamente essere sviluppata una com-
return element; ponente server, che deve essere distribuita sullo stesso
} server da cui scaricate il Javascript. Immaginate di voler
inserire nella vostra pagina HTML un Javascript, che legge
Questa funzione serve agli script AJAX per recuperare gli tramite XHR un feed RSS da una URL esterna e mostra il
elementi HTML con cui interagire. uno script ajax in ge- contenuto nella pagina. Per farlo, dovrete scrivere un po’
nere viene attivato a seguito di un evento che si verifica di codice lato server che funga da proxy nei confronti del
nella pagina HTML (onclick, onmoueover,....), esegue una feed esterno.
richiesta al server e modifica il codice HMTL della pagina
sulla base del risultato ottenuto.

XMLHttpRequest

Il cuore di AJAX risiede nell’oggetto XHR che consente ai


client di interagire con il server. I metodi standard che pos- AJAX significa
sono essere invocati su questo oggetto sono quelli definiti
dalle specifiche del consorzio W3C (Listato 1), ossia: letteralmente
• open
• send Asynchronous
• abort
• getAllResponseHeaders
• getResponseHeader
Javascript and XM
La chiamata “open” può essere eseguita sia in modalità
sincrona (bloccante) sia in modalità asincrona e quindi
non bloccante. Nel caso di chiamata asincrona occorre
gestire l’evento di risposta del server. Le chiamate asincro-
ne vengono fatte registrando un EventListener sull’evento
onreadystatechange dell’oggetto XHR. Esempio pratico: verifica dinamica dei form
Anche per l’oggetto XHR occorre un codice Javascript
particolare per garantire la compatibilità con le vecchie Vediamo un esempio pratico di utilizzo di AJAX. Esegui-
versioni di Explorer, quando XHR non era standard ma era remo la verifica lato server di un campo di un form prima
già largamente utilizzato da Microsoft. Il Listato 2 riporta che venga eseguito il submit del form stesso. Controlli di
uno dei meccanismi per recuperare l’oggetto XHR anche questo tipo possono essere eseguiti, ad esempio, durante la
per le vecchie versioni dei browser. compilazione dei form da parte dell’utente, per evidenziare
problemi nei dati inseriti prima che venga premuto il pul-
sante di submit, oppure suggerendo direttamente i valori
Lato server alternativi (nickname in uso, email già registrata, ecc.).
In questo esempio, verifichiamo che la lunghezza del va-
Ogni controllo AJAX necessita di una componente lato ser- lore di un campo inserito dall’utente sia di 5 caratteri. Se
ver che deve essere sviluppata, anche quando si vogliono la lunghezza del testo inserito è 5 caratteri, mostriamo una
utilizzare servizi XML già disponibili sul web. stringa di conferma; in tutti gli altri casi mostriamo un
L’oggetto XHR ha infatti una limitazione, imposta per messaggio d’errore.
motivi di sicurezza e di privacy: le richieste possono essere Come prima cosa definiamo la struttura dell’XML della

n.3 - marzo/aprile 2007 9


speciale AJAX JAVA Journal

risposta del server:


Anche qui abbiamo assegnato un id per recuperare l’ele-
<message><status>$STATUS</status><text>$TEXT</text></message> mento dallo script. Ora scriviamo il codice della funzione
check():
Il frammento XML è molto semplice: con status indichiamo
l’esito della verifica e con text il messaggio esteso generato function check(){
dal server.
Ora creiamo la pagina JSP form.jsp in cui inseriamo un Recuperiamo il valore inserito dall’utente:
form con un campo di input:
var valore=getElement(‘ajax_field’).value;
<form>
Inserisci testo: Recuperiamo l’oggetto XHR in funzione del browser:
<input type=”text” id=”ajax_field”
size=”20” onblur=”check()”/> var xhr = getXMLHttpRequest();
</form>
Recuperiamo la zona in cui scrivere il messaggio di ajax:
Il pulsante di submit e la action del form sono volutamente
omessi perché irrilevanti ai fini dell’esempio. var msg = getElement(‘ajax_msg’);
Occorre notare i seguenti particolari:
Eseguiamo la richiesta verso il server:
• al campo di input viene assegnata una funzione Ja-
vascript sull’azione onblur, ossia quando viene perso il xhr.open(“get”,”AjaxServlet?value=”+escape(valore),true);
fuoco
• al campo di input viene assegnato un id per consentir-
ne l’identificazione dalla funzione Javascript AJAX. • il primo parametro indica che la request è di tipo get (i
valori ammessi sono get/post);
A questo punto, dobbiamo creare nella pagina la sezione • il secondo indica la URL;
in cui andiamo a inserire il messaggio prodotto dallo script • con il terzo parametro indichiamo che la richiesta è
AJAX, come risposta del server. Ciò viene fatto, banalmen- asincrona, quindi non bloccante.
te, con una sezione <div> di cui possiamo manipolarne il
contenuto tramite l’invocazione al metodo innerHTML(). Assegniamo ora una funzione sul cambio di stato della
Subito dopo la chiusura del tag <form> inseriamo il se- request (la funzione verrà chiamata anche quando lo stato
guente codice HTML: passa a completato):

<div id=’ajax_msg’></div> xhr.onreadystatechange = function() {

interface XMLHttpRequest {
attribute EventListener onreadystatechange;
readonly attribute unsigned short readyState;
void open(in DOMString method, in DOMString url);
void open(in DOMString method, in DOMString url, in boolean async);
void open(in DOMString method, in DOMString url, in boolean async, in DOMString user);
void open(in DOMString method, in DOMString url, in boolean async, in DOMString user,
in DOMString password);
void setRequestHeader(in DOMString header, in DOMString value);
void send();
void send(in DOMString data);
void send(in Document data);
void abort();
DOMString getAllResponseHeaders();
DOMString getResponseHeader(in DOMString header);
readonly attribute DOMString responseText;
readonly attribute Document responseXML;
readonly attribute unsigned short status;
readonly attribute DOMString statusText;
};
}

LISTATO 1 Definizione completa dell’interfaccia XHR

10 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

function getXMLHttpRequest() {

var XHR = null;

if(typeof(XMLHttpRequest) === “function” || typeof(XMLHttpRequest) === “object”)


XHR = new XMLHttpRequest();
else if(window.ActiveXObject) {
var clientAgent = navigator.userAgent.toUpperCase();
if(browserUtente.indexOf(“MSIE 5”) < 0)
XHR = new ActiveXObject(“Msxml2.XMLHTTP”);
else
XHR = new ActiveXObject(“Microsoft.XMLHTTP”);
}
return XHR;

LISTATO 2 Funzione Javascript per recuperare l’oggetto XHR

di produzione (ad esempio: errore o mancata risposta del


Lo stato 4 equivale al completamento della richiesta al server, limitazione di accesso al servizio XML, ecc.).
server. Nel Riquadro 1 troviamo l’elenco di tutti gli stati Sarebbe buona prassi, per un lavoro fatto a regola d’arte,
possibili per l’oggetto XHR che fossero coinvolte tre figure professionali: sviluppatore
lato server, sviluppatore Javascript e grafico specialista in
if(xhr.readyState === 4) { HTML. Uno scenario di questo tipo è difficile che si presen-
ti, sopratutto in Italia dove gli sviluppatori sono chiamati a
Se la richiesta al server è andata a buon fine, (stato HTTP conoscere qualunque cosa. Alcuni framework aiutano nel-
200), scriviamo il codice HTML nella sezione dedicata, in la realizzazione di controlli e funzionalità AJAX, rendendo
caso di errore scriviamo il codice dell’errore HTTP e il mes- trasparente allo sviluppatore il dialogo client/server e la
saggio completo: componente Javascript.

if(xhr.status === 200) {


msg.innerHTML = parse(xhr.responseXML);
}else{
msg.innerHTML = “ERROR “+xhr.status+” - “+xhr.statusText
}
} La chiamata ‘open’
}
può essere eseguita sia
Dopo aver registrato le funzione di callback possiamo ese-
guire la chiamata:
in modalità sincrona
(bloccante) sia in
xhr.send(null);
modalità asincrona e
L’ultimo passo, prima di poter eseguire questo semplice
esempio, è scrivere il codice lato server. In una servlet che quindi non bloccante
mappiamo come /AjaxServlet scriviamo nel metodo doGet
il codice del Listato 3. Il codice è molto semplice e non
necessita di particolari commenti.

Strumenti e framework
GWT
Nell’esempio che abbiamo visto poc’anzi, abbiamo scritto
sia il codice client sia il codice server, partendo da zero. Il primo framework che vediamo è il Google Web Toolkit.
Per farlo abbiamo dovuto sfoggiare le nostre competenze Utilizzando GWT ci occuperemmo solo di scrivere il con-
nei linguaggi HTML, Javascript e Java. L’esempio era però trollo lato server. Ogni elemento “attivabile” con AJAX
molto semplice: non ci siamo preoccupati di aggiungere dispone di una classe, che possiamo estendere per fornire
quei controlli che sarebbero indispensabili in un ambiente le funzionalità client dinamiche. Ad esempio disponiamo

n.3 - marzo/aprile 2007 11


speciale AJAX JAVA Journal

PrintWriter out = response.getWriter();

String text = null;


String color= null;

if (request.getParameter(“value”)==null || request.getParameter(“value”).equals(“”)) {
text=”Valorizzare il campo”;
color=”grey”;
} else if (request.getParameter(“value”).length()==5) {
text=”La lunghezza della stringa è corretta”;
color=”green”;
} else {
text=”La lunghezza (“+request.getParameter(“value”).length()+
“) della stringa non è corretta”;
color=”red”;
}
}
out.print(“<message><color>”+color+”</color><text>”+text+”</text></message>”);
out.close();

LISTATO 3 La servlet client del nostro esempio

dell’oggetto Button() con tutti i metodi definiti in DHTML le chiamate AJAX. In genere con JSF accade che, come per
come ad esempio onclick(). i componente swing, chi sviluppa utilizza ciò che trova già
Tra le caratteristiche interessanti di GWT troviamo un pronto, eventualmente con qualche estensione. Solo in
wizard da riga di comando che genera lo scheletro di una casi eccezionali ci si cimenta nella sviluppo di componenti
prima applicazione e i file di progetto per Eclipse. Altra ca- completamente nuovi con tutte le problematiche annesse.
ratteristica importante è la possibilità di eseguire il codice JSF è quindi un ottimo candidato per applicazioni che fan-
in “hosted mode”, ossia senza l’intervento di un browser no uso di AJAX; ma l’uso di JSF non è indice dell’utilizzo
esterno, ma utilizzando un browser speciale che viene for- di AJAX. Occorre trovare i componenti giusti per disporre
nito insieme con il framework. di controlli avanzati AJAX.
Riporto un blocco di codice tratto dal sito del webtoolkit Alcuni esempi di componenti JSF/AJAX si possono trovare
per mostrare la semplicità del codice: nella sandbox di myfaces. Tra le cose interessanti troviamo
dropdown che si popolano sulla base di valori di altri ele-
public class Hello implements EntryPoint { menti di un form, suggerimenti dinamici in fase di digita-
public void onModuleLoad() { zione e verifica della validità dei valori su onblur.
Button b = new Button(“Click me”, new ClickListener() {
public void onClick(Widget sender) {
Window.alert(“Hello, AJAX”);
}
});
RootPanel.get().add(b);
}
}

Al campo di input
JSF
viene assegnato un
JSF (Jave Server Faces) basa la propria architettura sul-
l’uso di componenti. Ogni componente esegue il rendering id per consentirne
di bean specifici (chiamati backing-bean). A ogni compo-
nente possono essere assegnati degli actionListener su
eventi che si verificano sul client su cui viene renderizzato
l’identificazione
il bean. L’approccio è molto simile a quello adottato dalle
interfacce swing per la gestione degli eventi.
Questo tipo di architettura si è mostrata terreno molto
fertile per lo sviluppo di funzionalità AJAX.
In JSF poter disporre di funzionalità AJAX significa avere
dei componenti che per costruzione sono in grado eseguire

12 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

ECHO2 Conclusioni

È probabilmente quanto di più completo si possa tro- Sviluppare con la tecnica AJAX consente di realizzare vere
vare oggigiorno in Java su AJAX. ECHO2 è un web e proprie applicazioni client. Il browser non mostra più
framework che dispone di una libreria molto completa semplici pagine ma potenzialmente una singola pagina
di componenti per realizzare applicazioni con frontend che continua ad aggiornarsi dinamicamente in funzione
molto ricchi e complessi. ECHO2 dispone anche di un delle interazioni con l’utente. Per capire a fondo le poten-
ambiente di sviluppo visuale avanzato, in grado di zialità basta vedere Gmail di Google, con il suo sistema di
aiutare notevolmente in fase di sviluppo. Le librerie di chat o il nuovo frontend per la posta di Yahoo!.
ECHO2 sono disponibili con licenze lgpl o mpl, mentre AJAX comporta una serie di conseguenze, che impongono
l’ambiente di sviluppo è proprietario. Per utilizzare un attento studio prima di essere utilizzato indistintamente.
ECHO2 non è indispensabile utilizzare l’ambiente vi- Le prime considerazioni sono sull’accessibilità. Una applica-
suale anche se si perdono molti dei benefici della piat- zione AJAX sarà difficilmente accessibile da altri sistemi, in
taforma, come i wizard e i suggerimenti. particolare dai motori di indicizzazione. Siti per i quali è fon-
Gli esempi presenti sul sito del produttore (http: damentale l’indicizzazione o per i quali è previsto l’accesso
//demo.nextapp.com) descrivono le potenzialità del fra- da altre piattaforme non dovrebbero fare uso di Javascript
mework meglio di qualunque descrizione testuale. e quindi di AJAX. Un’altra considerazione è sulla sicurezza:
esporre servizi web è come mostrare il fianco al nemico. Oc-
corre utilizzare tutti gli accorgimenti per evitare che altri ne
Firebug abusino (ad esempio con un blocco su referrer) e per i dati
sensibili occorre sempre proteggere l’accesso e fornire i dati
Uno dei problemi di chi sviluppa con AJAX è monitorare solo in HTTPS. Sono accorgimenti comuni ma spesso trascu-
il dialogo client/server per individuare facilmente dove rati, per la percezione errata che nessuno conosce il servizio
possono annidarsi eventuali problemi. L’ultimo stru- e quindi nessuno lo chiamerà direttamente.
mento che consiglio è Firebug. Si tratta di un plugin
per Firefox in grado di intercettare, tra le altre cose, Note Biografiche
l’uso del oggetto XHR, mostrando sia la chiamata che Luigi Zanderighi è Ingegnere del software ed è esperto nella pro-
la risposta. gettazione di architetture distribuite e di software Java.

Dada S.p.A. è una Internet Company quotata alla Borsa di Milano


e presente sui principali mercati internazionali, leader nel settore dei
servizi Community ed Entertainment (Internet & Mobile).

Il nostro è un mondo con una forte componente internazionale, in cui


ogni dipendente e collaboratore si identifica con l’Azienda, un mondo
dove la passione per le nuove tecnologie contribuisce al successo
dell’Azienda, oltre che alla crescita personale e professionale.
Siamo convinti che dal confronto delle idee nascano le soluzioni più
brillanti, che il team-working sia un valore condiviso ed una realtà
quotidiana radicata nel piacere di rapportarsi con gli altri.

A seguito della forte crescita del nostro business ricerchiamo


Sviluppatori per il prodotto Dada.net (www.dada.net)
Il candidato ideale ha maturato una significativa esperienza di sviluppo software per il WEB.
Requisiti:
o Formazione in ambito informatico o elettronico
o Buona conoscenza della lingua inglese
o Comprovata conoscenza di uno o più linguaggi di programmazione:
• PHP
• Perl
• J2ME
• HTML, CSS e Javascript
• Javascript e Actionscript

Titoli preferenziali:
Passione per il mondo Internet, le nuove tecnologie, l’integrazione tra sistemi, lo studio e la realizzazione di community dedicate al
mondo consumer dell’entertainment (web e mobile).
Completano il profilo autonomia e spirito d’iniziativa, orientamento ai risultati e motivazione ad inserirsi in un contesto giovane e
molto dinamico.

Sede di lavoro: Firenze.


Se siete interessati ad incontrarci, aspettiamo le vostre candidature (Rif.: DEV07) all’indirizzo recruiting@staff.dada.net (autorizzando il tratta-
mento dei dati personali ai sensi del D.Lgs. 196/03). Per approfondimenti, visitate il nostro sito istituzionale: http://dada.dada.net/it/.

n.3 - marzo/aprile 2007 13


speciale AJAX JAVA Journal

AJAX facile con


prototype.js
Prototype è una libreria Javascript che rende facile e divertente la programmazione Javascript
per le pagine web. Impariamo ad usarla e a sfruttarne le potenzialità AJAX e di manipolazio-
ne del DOM

>> di Domenico Ventura (domenico.ventura@javajournal.it)

src=”prototype.js” > </script>

L
A questo punto la nostra pagina è pronta per utilizza-
a maggior parte dei framework e delle re in pieno tutte le potenzialità di Prototype!
librerie opensource che si trovano in
rete hanno l’ambizione di semplificare la
vita al programmatore. Prototype è fra le
poche che raggiunge pienamente questo
scopo. Nata con l’obiettivo di rendere la
programmazione Javascript meno confusionaria, più
strutturata, in poche parole più divertente, Prototype
è nota per essere la libreria Javascript distribuita e
usata in Ruby on Rails per gestire le chiamate AJAX
Prototype è fra le poche
lato client. Ciò nonostante Prototype può tranquilla-
mente essere usata in qualunque progetto web.
librerie che realmente
Tra i numerosi punti di forza di Prototype, e sono tan-
ti, non può però essere annoverata la documentazio- semplificano il compito
ne, che (almeno sino al lancio del nuovo sito, a fine
febbraio) è sempre stata carente, se non completa- del programmatore
mente mancante, costringendo quasi sempre il pro-
grammatore ad andare per tentativi o a leggere diret-
tamente il sorgente all’interno della libreria. Questo
articolo fornisce una panoramica su Prototype, sulle
funzionalità e sugli oggetti base, in particolare quelli
legati al supporto per AJAX, alla gestione dei form e
del DOM.
Tutti quei $ $ $ qua e là

Per iniziare Una delle prime cose che saltano agli occhi esami-
nando del codice che utilizza Prototype (o analiz-
L’ultima versione di Prototype, che attualmente è zando direttamente il sorgente di Prototype) sono
la 1.5.0, può essere scaricata dal sito ufficiale http: le tante chiamate $(...), $F(...), $$(...), che danno
//www.prototypejs.org/. La libreria si compone di un un po’ l’impressione di un listato Perl. In realtà que-
solo file, prototype.js appunto, che deve essere inclu- ste sono funzioni di utilità generale, tra quelle che
so all’interno delle pagine web con il tag <script>: maggiormente adempiono al dovere di semplificarci
la vita, evitandoci di scrivere del codice ripetitivo. Ve-
<script type=”text/javascript” diamone alcune nel dettaglio.

14 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

TABELLA 1 Opzioni per le richieste AJAX

Opzione Descrizione Default


‘application/
Indica l’header contentType della richiesta x-www-form-
contentType
HTTP che verrà effettuata urlencoded’

encoding Indica l’encoding dei contenuti della richiesta ‘UTF8’


AJAX

method Specifica se la richiesta deve essere fatta in get ‘post’


o in post

L’elenco dei parametri da passare alla richie-


parameters sta, URL encoded. Questi verranno passati ‘’
nella URL per le richieste Get, o nel corpo della
richiesta per gli altri tipi di richieste.
Utilizzato solo da Ajax.updater, indica
insertion dove i nuovi contenuti verranno inseriti. undefined
Può essere Insertion.Before, Insertion.Top,
Insertion.Bottom. Insertion.After

Utilizzato da Ajax.PeriodicalUpdater, indica


frequency l’intervallo (e non la frequenza!) tra due chia- undefined
mate, in secondi

Utilizzato da Ajax.PeriodicalUpdater, indica di


quanto aumentare l’intervallo fra due chiama-
te consecutive, nel caso la risposta ricevuta sia
la stessa della chiamata precedente.Ad esem-
decay pio: decay=2, significa che in caso si ottengano undefined
due risposte uguali, la prossima chiamata sarà
fatta dopo 2*frequency secondi. E l’intervallo
sarà di nuovo moltiplicato per due in caso di
una nuova risposta uguale alla precedente.

Oltre che una stringa che identifica un ID, la funzione $( )


può accettare come parametro anche un riferimento ad un
La funzione $( ) elemento del DOM: in questo caso la funzione restituisce
l’elemento stesso, ma esteso con le funzionalità aggiuntive
La funzione $( ) è un collegamento alla usatissima fun- definite da Prototype. Vedremo nel proseguo cosa questo
zione DOM document.getElementByID(). Come questa, implica e come la funzione $( ) aiuti nella manipolazione
restituisce un riferimento all’elemento DOM il cui ID è degli oggetti del DOM.
passato come parametro. Ecco un esempio: Questo aspetto rende la funzione $( ) una delle principali
e basilari dell’intera libreria: viene usata all’interno di Pro-
var el = $(“unDiv”); totype un po’ come un piccolo coltellino svizzero multiuso!
alert(el.innerHTML); Ad esempio, molte delle funzioni della libreria Prototype
hanno questa struttura:
La funzione $() può accettare anche diversi ID come para-
metri, e in questo caso restituisce un array degli elementi function aFunction(element)
corrispondenti agli ID: {
element = $(element)
var elList = $(“unDiv”,”altroDiv”) //resto della funzione
for(int i=0; i < elList.length; i+) }
alert(elList[i].innerHTML);
In questo modo è possibile passare come parametro alla

n.3 - marzo/aprile 2007 15


speciale AJAX JAVA Journal

<script> tenzioni, in quanto un utilizzo poco attento


function mostraNome() potrebbe avere un notevole impatto negati-
{ vo sulle prestazioni.
alert(“Il tuo nome è: “ + $F(“nome”));
}
</script> E AJAX?

<input type=”text” id=”nome” /> Sin qui abbiamo visto una serie di funzioni
di uso generico, sicuramente molto utili
<input type=”button” value=”mostra” onclick=”mostraNome()” />
e ben fatte, ma uno degli scopi principali
per utilizzare Prototype è poter avere delle
LISTATO 1 Esempio di utilizzo della funzione $F( ) funzionalità AJAX! Vediamo allora come
utilizzare la libreria al meglio per creare
funzione sia la stringa con l’ID dell’elemento, sia l’ele- delle pagine AJAX.
mento stesso. Nel proseguo della funzione si utilizza poi Per centralizzare tutte le funzionalità AJAX, Prototype crea
l’elemento esteso da Prototype con le sue funzionalità e rende pubblico un oggetto denominato, appunto, Ajax:
aggiuntive. questo si fa carico di gestire dietro le quinte tutte le dif-
ferenze di implementazione e di utilizzo sui vari browser
dell’oggetto XMLHttpRequest, assicurando così la fruibili-
tà delle nostre applicazioni con qualunque browser.
La Funzione $F( ) Nella pratica, per la realizzazione di funzionalità AJAX,
bisogna utilizzare delle sottoclassi dell’oggetto Ajax. Vedia-
Anche la funzione $F( ) è una scorciatoia molto comoda: per- mole in dettaglio.
mette di ottenere il valore di un qualsiasi elemento di input,
passando come parametro il suo ID. Il Listato 1 riporta un
esempio che mostra un alert con il valore inserito nel campo Ajax.Request
nome quando si effettua un click sul pulsante mostra.
Il modo più semplice e immediato di creare una chiamata
AJAX è istanziare un oggetto Ajax.Request. Ad esempio:

new Ajax.Request
Document.getElementByClassName()
(“/unaURL”, { method:”get” });
Questa funzione consente di ottenere un array di tutti gli
elementi della pagina che hanno la classe CSS passata Il primo parametro del costruttore indica a quale URL
come parametro. Si può anche passare un riferimento ad indirizzare la richiesta. Il secondo parametro è un ogget-
un elemento della pagina come parametro opzionale: in to Javascript, creato in questo caso secondo la notazione
questo caso la ricerca avviene solo sui figli di tale elemen- JSON, che indica le opzioni da utilizzare per la richiesta
to. AJAX: nell’esempio indica che la richiesta HTTP deve es-
Ad esempio, se vogliamo ottenere la lista di tutti gli ele- sere fatta in GET.
menti di classe test, scriveremo: Questo secondo parametro merita qualche spiegazione in

document.getElementByClassName(“test”);
// Tutti i form della pagina:
Un altro esempio; per ottenere la lista di tutti gli elementi $$(“form”);
di classe test contenuti all’interno di un elemento (un div,
un form) di ID “login”, scriveremo: // Tutti i link della pagina
// con attributo href=”#” (wow!)
document.getElementByClassName(“test”, $(“login”)); $$(“A[href=’#’]”);

// Tutti i th di classe prezzo


La funzione $$( ) // del div di ID data
$$(“div#data th.prezzo”);
La funzione $$( ), introdotta a partire dalla versione 1.5,
è un potente mezzo di navigazione all’interno del DOM:
consente infatti di accedere agli elementi della pagina uti-
lizzando la stessa modalità e sintassi dei CSS Selector. // Tutti gli elementi di classe link
La funzione $$( ) ha come parametri una o più regole di // nei div head o foot
selezione CSS e ritorna un array di elementi del DOM che $$(“div#head .link”, “div#foot .link”);
soddisfano tali regole. Il Listato 2 mostra alcuni esempi di
utilizzo della funzione $$( ).
Questa funzione va usata con cautela e con particolari at- LISTATO 2 Esempi di utilizzo della funzione $$( )

16 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

new Ajax.Request
più: è comune a tutte le classi dell’oggetto AJAX e consente
(
di specificare le opzioni da usare in una singola richiesta
AJAX. La Tabella 1 elenca le opzioni di più comune utiliz- “/trovaUtente.do”,
zo: tutte hanno un default, di modo che possiamo specifi- {
care solo quelle che realmente si intende modificare. method:”get”,
L’esempio appena mostrato non serve realmente a molto: parameters: “userId=888”,
dopo aver invocato la URL “/unaURL” non specifica cosa onSuccess: function(resp)
fare della risposta che si ottiene. Poiché le richieste AJAX {
sono per definizione asincrone, la gestione dell’output alert(“Salve utente “ +resp.responseText);
(così come delle condizioni di errore) deve essere compiu- },
ta tramite delle callback. Anche le callback da usare vanno onFailure: function
definite nel parametro che indica le opzioni. {
Il Listato 3 mostra un altro esempio di utilizzo di
alert(“C’è stato” + “un errore...”);
Ajax.Request, completo di callback per la gestione dell’er-
}
rore e della risposta AJAX. In questo secondo esempio ven-
}
gono definite due callback: una da chiamare nel caso che
la richiesta Ajax sia andata a buon fine e una da chiamare );
in caso di errore. Nella prima callback, il parametro resp che
viene passato è l’oggetto XMLHttpRequest originario, di LISTATO 3 Esempio di una chiamata AJAX completa di
cui si possono usare le proprietà responseText o responseXML. callback
La Tabella 2 riporta l’elenco delle callback più comuni.

Supponiamo, ad esempio, di voler mostrare l’elenco dei


Ajax.Updater e Ajax.PeriodicalUpdater prodotti disponibili in un catalogo per tipologia: avremo
una tendina di selezione dei diversi tipi di prodotti dispo-
Un uso molto comune di AJAX consiste nell’utilizzarlo nibili (libri, DVD, CD, ecc.) e, al cambiamento di selezione
per aggiornare dinamicamente, e senza dover ricaricare da parte dell’utente, la lista visualizzata viene aggiornata
l’intera pagina, solo alcune sezioni della pagina stessa. A dinamicamente con una chiamata AJAX. Ecco come usare
tale scopo l’oggetto Ajax di Prototype mette a disposizione l’oggetto Updater in questo caso:
la classe Ajax.Updater. Questa, dato l’ID dell’elemento da
aggiornare e la URL da chiamare, realizza proprio questa new Ajax.Updater(“prodotti”,
funzionalità. “/prodotti.do”,

TABELLA 2 Callback per le richieste AJAX

Callback Descrizione
onComplete Chiamata alla fine del ciclo di vita di una richiesta AJAX.

Chiamata qualora durante la richiesta AJAX venga sollevata un


onException eccezione dall’oggetto XMLHttpRequest. Prende come parametri
l’oggetto XMLHttpRequest e l’eccezione incontrata.

Chiamata quando la richiesta AJAX viene completata ma la


onFailure
risposta ottenuta indica un errore (codice HTTP diverso da 2xx)

Chiamata quando la richiesta AJAX viene completata con


onSuccess successo (codice HTTP uguale a 2xx). Viene eseguita prima di
onComplete.

Dove XXX è uno specifico codice di risposta HTTP. Chiamata


quando la richiesta AJAX viene completata e il codice HTTP
onXXX della risposta è XXX. Queste callback vengono eseguita prima di
onComplete e fanno si che onFailure e onSuccess non vengano
chiamate

Usata dalla sola classe Responders: viene chiamata alla creazione


onCreate
di una qualsiasi richiesta AJAX

n.3 - marzo/aprile 2007 17


speciale AJAX JAVA Journal

{parameters:”tipo=” + $F(“tipo”)}); onComplete: function(){


$(“loadingDiv”).innerHtml = “”;}
Il primo parametro indica l’ID dell’elemento da aggior- })
nare, il secondo la URL a cui inviare la richiesta e il ter-
zo parametro specifica le opzioni da passare. Di default In questo esempio, ad ogni richiesta Ajax che viene ori-
l’aggiornamento eseguito da Updater avviene sull’intero ginata dalla pagina, nel div di ID “loadingDIV” compare
elemento, ma utilizzando tra i parametri l’opzione “in- la scritta “caricamento in corso...”, che scompare al com-
sertion” si può indicare dove inserire il nuovo contenuto pletamento delle richiesta Ajax. Un altro possibile utilizzo
rispetto all’elemento indicato. consiste nel centralizzare la gestione delle eccezioni, in
modo da registrare e definire una sola volta la callback
Di funzionamento molto simile alla classe Updater è onException.
l’oggetto PeriodicalUpdater: in questo caso l’elemento in-
dicato viene aggiornato in maniera periodica ad intervalli
prefissati. Estensioni di Prototype al DOM
Se ad esempio si volesse avere un’area della pagina dedicata
alle previsioni meteorologiche, aggiornata dinamicamente Una parte cospicua di Prototype è dedicata alle estensioni
ogni minuto, si potrebbe usare Ajax.PeriodicalUpdater in degli oggetti DOM. Prototype aggiunge tante utili funzio-
questo modo: nalità agli oggetti del DOM, di modo che utilizzando Proto-
type è possibile avere del codice come il seguente:
new Ajax.PeriodicalUpdater(“previsioni”,
“/previsioni.do”, $(“unDiv”).addClassName(“cl”).show();
{
frequency: 60, Questa linea di codice aggiunge la classe “cl” all’elemento
parameters:”provincia=” + $F(“pv”) di ID “unDIV” e lo rende visibile.
}); Prototype estende la classe Element, di modo che le
funzionalità aggiuntive sono quindi presenti in tutti gli
elementi del DOM. Per utilizzare le estensioni del DOM ci
sono due modalità. La prima prevede l’uso dei metodi della
classe Element di Prototype passando l’ID dell’elemento al
metodo da invocare. Ad esempio:

Element.update(“unDiv”, nuovoHtml);

Creare delle pagine L’altro modalità per utilizzare le estensioni del DOM di
Prototype consiste nell’utilizzare direttamente gli oggetti
estesi, ovviamente tramite la funzione $( ):
AJAX cross-broweser in
$(“unDiv”).update(nuovoHtml);

pochi secondi La funzione $( ) è abbastanza intelligente da fare in modo


che un elemento del DOM venga esteso da Prototype una
sola volta.
Fra le funzioni aggiunte dalla classe Element ci sono:

• Funzionalità di navigazione nel DOM (metodi up,


down, next, previous, remove)
• Funzionalità di manipolazione degli stili (metodi get-
Style, getWidth, addclassName, classNames, setStyle)
Ajax.Responders • Funzionalità di gestione della visibilità dell’elemento
(metodi show, hide, toggle)
Un altro oggetto molto comodo da utilizzare è
l’Ajax.Responders: consente di registrare delle callback co- Oltre a queste funzioni, comuni a tutti gli elementi del
muni a tutte le chiamate Ajax che vengono originate dalla DOM, alcuni particolari tipi di oggetti hanno altre funzio-
pagina. Ad esempio, può essere utilizzato per mostrare una nalità in più. È il caso dei form e degli elementi di input.
piccola animazione o un messaggio di caricamento in corso Questi vengono estesi da Prototype tramite le classi Form e
tutte le volte che la pagina effettua una richiesta Ajax: Form.Element. Utilizzando Prototype sui i form è possibile:

Ajax.Responders.register( • Abilitare o disabilitare l’intero form tramite le funzioni


{ enable() e disable();
onCreate: function(){ • Ottenere il primo elemento di input non hidden e non
$(“loadingDiv”).innerHtml = disabilitato e dargli il focus con le funzioni getFirstEle-
“caricamento in corso...”;}, ment() e focusFirstElement()

18 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

Il Listato 4 mostra dove il testo aggiuntivo verrà inserito a


Insertion.Before seconda della sottoclasse di Insertion che si utilizza.
<div id=mioDIV>
Insertion.Top
<p>Contenuto dell’elemento mioDIV
Insertion.Bottom
</div>
Insertion.Bottom

LISTATO 4 Differenze tra le sottoclassi di Insertion


Funzioni semplici di
• Ottenere una stringa da utilizzare per le richieste Ajax
(cioè qualcosa del tipo “nome=paolino&cognome=pap
manipolazione del DOM
erino”) a partire da tutti i campi di un form con la fun-
zione serialize().
e per creare effetti
Funzionalità simili sono presenti per gli elementi di input visuali
dei form.

Controllare i cambiamenti sui form

Con Prototype è possibile monitorare un form (o solo un


suo elemento), in modo da eseguire delle azioni ogniqual-
volta questo venga modificato. Le classi che consentono Conclusioni
questo sono Form.Observer o Form.EventObserver (op-
pure le analoghe Form.Element.Observer e Form.Elemen Prototype è una libreria Javascript di grande utilità, che
t.EventObserver per i singoli elementi di input). Ecco un permette di creare pagine per applicazioni Web 2.0 in
esempio di utilizzo: maniera rapida e efficace. In questo articolo ci siamo par-
ticolarmente concentrati nel dare una visione d’insieme
new Form.Observer($(“mioForm”), 1, validaInput) delle funzionalità AJAX, di manipolazione e di gestione
del DOM, ma Prototype offre molto di più. Ad esempio
new Form.Element.EventObserver($(“email”), controllaEmail) non abbiamo parlato delle estensioni alla classe Array e
della classe Enumerable, delle funzionalità correlate alla
In entrambi i casi viene registrata come callback una fun- creazione di oggetti, della gestione dei tipi Hash.
zione di validazione dell’input. La differenza tra le due Il nuovo sito, lanciato con la versione 1.5 della libreria, è
classi sta nel fatto che Observer controlla periodicamente inoltre un notevole passo in avanti per quanto la riguarda
(nell’esempio di sopra ogni secondo) se il form in oggetto la documentazione. Prototype è anche un ottimo esempio
è cambiato, mentre EventObserver è basato sugli eventi. di codice Javascript ottimamente scritto. Prova di questo è
La callback in questo secondo caso viene quindi invocata anche il fatto che altre ottime librerie Javascript per AJAX,
solo quando un evento indica che il form (o l’elemento di scriptaculous e moo.fx fra tutte, siano basate proprio su
input) è stato modificato. Questo implica che EventObser- Prototype.
ver può essere utilizzata solo con elementi che supportano
gli eventi onChange o onClick.
Links

Oggetto Insertion [1] Sito ufficiale: http://www.prototypejs.org


[2]_Ottimo tutorial e reference guide:
L’oggetto Insertion di Prototype permette di inserire, in http://www.sergiopereira.com/articles/prototype.js.html
maniera dinamica e portabile su tutti i browser, blocchi [3] Scriptaculos: http://script.aculo.us
di HTML all’interno o intorno ad un dato elemento della [4] Moo.fx: http://moofx.mad4milk.net/
pagina. Per selezionare in maniera accurata dove inserire i
contenuti aggiuntivi rispetto all’elemento indicato, Inser-
tion ha quattro sottoclassi: Before, After, Top e Bottom. Ad
Note Biografiche
esempio, per inserire il testo “ciao mondo!” dopo l’ele-
mento di ID “titolo”: Domenico Ventura si è laureato in ingegneria informatica al Po-
litecnico di Torino nel 1999 e da allora si occupa di system in-
tegration e di realizzare applicazioni web. Attualmente lavora
new Insertion.After(“titolo”, come senior consultant presso Reply s.p.a., dove si occupa di so-
“<p> ciao <b>mondo!</b> </p>”) luzioni di Knowledge Management, di Enterprise Content Ma-
nagement e di Business Intelligence. É membro e coordinatore
del Jug Torino.

n.3 - marzo/aprile 2007 19


speciale AJAX JAVA Journal

Google Web
Toolkit
Creare un progetto AJAX partendo da zero comporta una ottima conoscenza di javascript ol-
tre che di XML, HTML, CSS e delle compatibilità dei vari browser. Tuttavia, il progetto GWT
(Google Web Toolkit) permette agli sviluppatori Java di creare siti in AJAX senza dover scrive-
re neanche una linea di codice javascript.

>> di Jacopo Giudici (jacopo.giudici@javajournal.it)

I
L’installazione dei GWT e la creazione del pri-
l Google Web Toolkit [1] è un framework svi- mo progetto
luppato dal Google Team che permette di com-
pilare del codice Java trasformandolo in pagine
che utilizzino la tecnologia AJAX. I Google Web Toolkit (da ora GWT) sono delle libre-
Con la nascita dell’acronimo AJAX, le grandi rie Java con a corredo una serie di programmi che
compagnie di software hanno realizzato meto- permettono la creazione rapida di classi Java trasfor-
di più o meno efficaci per semplificare il lavoro degli mabili tramite compilazione in pagine HTML-AJAX.
sviluppatori creando dei framework per la creazione I progetti creati con i GWT sono pronti per essere
di pagine contenenti la nuova tecnologia a partire dai modificati, compilati o valutati tramite strumenti
linguaggi di programmazione proprietari. Microsoft tipici della programmazione Java, quali, ad esempio,
ha sviluppato Atlas per ASP.NET [2], Yahoo ha reso Eclipse, Ant e JUnit. Il nucleo dei GWT è composto da
disponibile le User Interface Library [3] e anche la una serie di librerie Java e quindi indipendenti dalla
comunità Open Source si è prodigata nella creazione piattaforma; tuttavia, alcuni programmi contenuti
di svariati progetti, tra i quali il più famoso è proba- nel pacchetto sono dei file di script dipendenti dal
bilmente Sarissa [4]. sistema operativo. Proprio per questo, i GWT posso-
L’approccio di Google è, tuttavia, originale e permette no essere scaricati in due versioni: per Windows e
ai puristi Java di creare degli interi siti AJAX inte- per Linux/MacOS. Dopo aver scaricato il file adatto
grandoli con le tecnologie che già utilizzano quali, ad al vostro sistema operativo e averlo decompresso,
esempio, Servlet, JSP e EJB, senza dover necessaria- l’installazione è terminata. L’unico ulteriore passo,
mente conoscere javascript. non necessario ma consigliato, è l’inserimento nel
PATH della cartella creata dalla decompressione del
file, contenente i vari script per creare o modificare
progetti e classi GWT.
All’interno della cartella decompressa contenente i
L’approccio di GWT, esistono due file di script: projectCreator e ap-
plicationCreator: file .cmd sotto Windows e .sh sotto
Google è originale e Linux/MacOS. Per creare un nuovo progetto, creiamo
una cartella chiamata JavaJournal che conterrà il pro-
permette di creare siti getto e quindi navighiamo fino a quella cartella con
AJAX senza conoscere la shell dei comandi. Da qui, lanciamo il comando:

javascript projectCreator –eclipse javajournal –ant javajournal

Il comando funziona solo se abbiamo inserito la

20 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

FIGURA 1 L’applicazione di base Reviews

cartella contenente i GWT nel PATH, altrimenti dovremo


fornire il percorso completo per utilizzare l’applicazione:
ad esempio C:\gwt-1.3.3-windows\projectCreator … .
Questo comando crea un progetto pronto ad essere utiliz-
zato con Eclipse e Ant all’interno della cartella in cui ci
Le interfacce utenti
troviamo. Tra i file che vengono creati, oltre a quelli neces-
sari per poter utilizzare il progetto con Eclipse, viene creato create con GWT sono
un file chiamato javajournal.ant.xml che serve a compilare
l’applicazione con Ant la cui sintassi è stata trattata nel simili nei metodi di
numero 2 di JavaJournal.
Dopo aver creato il progetto con l’utilità projectCreator, utilizzo a quelle create
creiamo l’applicazione che verrà trasformata in codice
AJAX da GWT con il comando applicationCreator in que- con Swing
sto modo:

applicationCreator –eclipse javajournal it.jj.client.Reviews

Questo comando crea, all’interno della struttura presente,


una serie di file, tra cui la classe principale, nel nostro caso L’applicazione di base
Reviews, che si deve sempre trovare in un package di nome
client, nel nostro caso it.jj.client. Oltre a questo file, vengono Ogni volta che creiamo un’applicazione con il comando
creati nella cartella principale due script che permettono la applicationCreator, viene preparata una classe java che,
compilazione e il test immediato della nostra applicazione. compilata, da come risultato la pagina HTML di figura1.
Per vedere il risultato dei nostri sforzi, proviamo a eseguire La pagina è già dinamica e utilizza javascript, come si com-
il file Reviews-shell.cmd. Il risultato dovrebbe essere quello prende facendo click sul pulsante Click Me. Questa sempli-
di figura1. ce pagina sarà il progetto principale da cui partiremo per

n.3 - marzo/aprile 2007 21


speciale AJAX JAVA Journal

creare la nostra applicazione AJAX. package it.jj.client;


Per meglio capire come avvenga questa tra-
sformazione, vediamo i file più importanti import com.google.gwt.core.client.EntryPoint;
creati dall’esecuzione di applicationCreator import com.google.gwt.user.client.ui.Button;
e, per farlo, carichiamo innanzitutto il pro- import com.google.gwt.user.client.ui.ClickListener;
getto in Eclipse con questi passaggi: import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
1. selezioniamo File->New->Project… import com.google.gwt.user.client.ui.Widget;
2. dalla finestra che compare selezioniamo
Java Project e facciamo click su Next
public class Reviews implements EntryPoint {
3. diamo un nome al progetto, selezionia-
mo la voce Create project from existing public void onModuleLoad() {
source e selezioniamo alla voce Di- final Button button = new Button(“Click me”);
rectory: la cartella javajournal creata in final Label label = new Label();
precedenza.
button.addClickListener(new ClickListener() {
Facendo quindi click su Finish avremo public void onClick(Widget sender) {
un nuovo progetto in Eclipse con i colle- if (label.getText().equals(“”))
gamenti alle librerie GWT necessarie alla label.setText(“Hello World!”);
compilazione. else
All’interno della struttura dell’applicazio- label.setText(“”);
ne, oltre ai file visti in precedenza, altri file }
sono necessari per la creazione della pagina
});
AJAX:

− Il file Reviews.java che si trova nel package RootPanel.get(“slot1”).add(button);


it.jj.client. Aprendo questo file, che andre- RootPanel.get(“slot2”).add(label);
mo poi a modificare, vediamo come esso }
sia composto interamente da codice java }
che Eclipse riconosce senza segnalarci
errori. LISTATO 1 Il codice dell’applicazione di base
− Il file Reviews.html che si trova nel packa-
ge it.jj.public. Il file Reviews.html è un semplice file che deve essere compilata per creare il modulo stesso.
HTML che contiene lo scheletro HTML dell’applicazione, In particolare, si noti come it.jj.client.Reviews sia definito
oltre ai vari riferimenti a codici javascript esterni, a fogli come Entry Point, il che significa che la classe it.jj.client.R
di stile e, soprattutto, ai moduli GWT che verranno iniet- eviews.java verrà trasformata nel primo modulo javascript
tati nella pagina durante il suo caricamento. eseguito dalla pagina Reviews.html.
− Il file Reviews.gwt.xml che si trova nel package it.jj. Questo
file fornisce alcune variabili necessarie alla compilazione Ora che conosciamo i passaggi che definiscono quale clas-
dei moduli GWT. Nell’applicazione di base, nel file c’è un se verrà trasformata nel modulo GWT Reviews, vediamo
riferimento alla libreria com.google.gwt.user.User necessa- il codice contenuto nell’applicazione di base riportato nel
ria al compilatore per la creazione del modulo. Inoltre, listato1.
sempre nel file, c’è il riferimento alla classe principale Cominciamo dicendo che le interfacce utenti create con
GWT sono simili nei concetti e nei metodi di utilizzo a
quelle create con Swing. Nonostante in queste pagine
AJAX ci sia la possibilità di accedere direttamente al DOM
tramite particolari interfacce fornite dai GWT, è senz’altro
più semplice utilizzare le classi grafiche messe a disposi-
zione dal framework e lasciare che il compilatore crei le
pagine automaticamente.
In particolare, nel codice della classe Reviews vengono
dichiarate delle variabili di tipi simili a quelli che potrem-
mo trovare in una classe Swing: Button e Label. Come è
possibile vedere nella pagina Widget Gallery nella documen-
tazione online dei GWT, la prima di queste variabili verrà
visualizzata in HTML come un pulsante e la seconda come
una semplicissima etichetta di testo. Quindi, prima che
questi due oggetti vengano inseriti nella pagina web, viene
collegata un istanza della classe ClickListener alla variabile
button, in modo simile a quello che faremmo con un pul-
sante Swing attribuendogli un ActionListener:
FIGURA 2 Il progetto caricato in Eclipse

22 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

letro della pagina. In particolare, il codice che ci permette


button.addClickListener(new ClickListener() { di localizzare la posizione dei nostri moduli GWT è il se-
public void onClick(Widget sender) { guente:
if (label.getText().equals(“”))
label.setText(“Hello World!”); <td id=”slot1”></td><td id=”slot2”></td>
else
label.setText(“”); Al lancio del codice javascript, verranno recuperati gli
} oggetti della pagina in cui inserire i moduli GWT tramite
}); il comando getElementById(), che, come dice il nome, è in
grado di trovare una parte della pagina HTML semplice-
Con questo codice viene creata la pagina di esempio vi- mente grazie al suo attributo id. Per collegare agli elemen-
sta in precedenza e, facendo click sul pulsante Click Me, ti HTML i nostri moduli GWT scritti in Java, utilizziamo
nell’etichetta comparirà la scritta “Hello World”, mentre quindi il seguente codice:
facendo click una seconda volta, il contenuto dell’etichetta
verrà eliminato. RootPanel.get(“slot1”).add(button);
L’ultimo passaggio del codice permette di inserire le due RootPanel.get(“slot2”).add(label);
componenti nella pagina HTML Reviews.html che, come
detto prima, contiene già il codice che produrrà lo sche-
Il RootPanel può essere visto come il ContentPane in una
classe Swing, ossia come il contenitore
<html> superiore al quale vengono poi aggiun-
ti i vari componenti. In questo caso, il
<head>
modulo Reviews recupererà durante il
<title>JavaJournal Reviews</title>
caricamento dell’HTML i due oggetti
<style> di tipo <td> identificati dagli id slot1 e
body,td,a,div,.p{font-family:arial,sans-serif} slot2 e inserirà nel primo l’oggetto but-
div,td{color:#000000} ton e nel secondo l’oggetto label creati
a:link,.w,.w a:link{color:#0000cc} in precedenza.
a:visited{color:#551a8b}
a:active{color:#ff0000}
.gwt-MenuBar { L’applicazione Reviews
background-color: #C3D9FF;
border: 1px solid #87B3FF; L’applicazione Reviews, che verrà creata
cursor: default; dall’applicazione di base, visualizzerà
} una lista di articoli dei primi due nu-
meri di JavaJournal in una struttura
.gwt-MenuBar .gwt-MenuItem {
ad albero. I nomi degli articoli saranno
padding: 1px 4px 1px 4px;
selezionabili e, facendo click su un titolo
/*font-size: smaller;*/ nell’albero, dovranno comparire in una
cursor: default; finestra popup l’eventuale link all’arti-
display: block; colo e il link per comunicare via email
} con l’autore.
.gwt-MenuBar .gwt-MenuItem-selected { Per creare questa applicazione, avremo
background-color: #E8EEF7; bisogno di modificare il file Reviews.html
} e il file Reviews.java. Il listato2 e il
.myPopup { listato3 riportano, rispettivamente, il
background-image: url(gray_ codice della pagina Reviews.html e della
gradient.gif); classe Reviews.java.
background-repeat: repeat-x; Nel file HTML vengono inseriti una serie
di stili CSS per modificare i vari oggetti
border: 1px solid #AAAAAA;
creati dalla compilazione della classe
padding: 4px;
Reviews.java. Nei javadocs, forniti a
}
corredo dei Toolkit, vengono riportate
</style> le varie classi di stile per ogni oggetto
<meta name=’gwt:module’ content=’it.jj.Reviews’> inseribile dalle classi GWT nelle pagine
</head> HTML. Nel nostro esempio, il primo
<body> oggetto che andremo a creare sarà una
<script language=”javascript” src=”gwt.js”></script> struttura ad albero, derivata dalla classe
</body> com.google.gwt.user.client.ui.Menu
</html> Bar. Nei javadocs, viene specificato che,
per modificare l’aspetto delle varie parti
di una MenuBar bisogna modificare le
LISTATO 2 La pagina Reviews.html

n.3 - marzo/aprile 2007 23


speciale AJAX JAVA Journal

package it.jj.client;
import com.google.gwt.core.client.*;
import com.google.gwt.user.client.ui.*;
public class Reviews implements EntryPoint {
private VerticalPanel treeRev = new VerticalPanel();
private DockPanel page = new DockPanel();
public void onModuleLoad() {
addTree();
treeRev.setWidth(“100%”);
page.add(treeRev, DockPanel.WEST);
RootPanel.get().add(page);
}
public void addTree() {
Tree tree = new Tree();
TreeItem root1 = new TreeItem(imageItemHTML(“riviste_jj.jpg”, “#1”));
tree.addItem(root1);
root1.addItem(nuovoArticolo(“Java Server Faces”, “Michele Sciabarr&agrave;”,
“michele.sciabarra@javajournal.it”));
root1.addItem(nuovoArticolo(“Le novit&agrave di JSF 1.2”, “Andrea Nasato”,
“andrea.nasato@javajournal.it”));
root1.addItem(nuovoArticolo(“Java Card”, “Matteo Campanella”,
“matteo.campanella@javajournal.it”));
root1.setState(true);
TreeItem root2 = new TreeItem(imageItemHTML(“riviste_jj.jpg”, “#2”));
tree.addItem(root2);
root2.addItem(nuovoArticolo(“J2ME Best Practice”, “Andrea Nasato”,
“andrea.nasato@javajournal.it”));
root2.addItem(nuovoArticolo(“Apache Ant”, “Michele Ferretti”,
“michele.ferretti@javajournal.it”));
root2.setState(true);
treeRev.add(tree);
}
/*
* Le variabili recuperate dal metodo vengono definite static perchè dovranno
* essere utilizzate all’interno dell’istanza di ClickListener
*/
private HTML nuovoArticolo(final String nomeArticolo, final String autore, final String mail) {
/*
* Inserisco nell’html, come href un riferimento a javascript senza nome del metodo
* da eseguire: sarà poi il metodo addClickListener a inserire il giusto codice
*/
final HTML link = new HTML(“<a href=’javascript:;’>” + nomeArticolo + “</a>”);
link.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
MyPopupPanel popup = new MyPopupPanel(nomeArticolo, autore, mail);
int left = link.getAbsoluteLeft() + 32;
int top = link.getAbsoluteTop() + 8;
popup.setPopupPosition(left, top);
popup.show();
}
});
return link;
}
private static class MyPopupPanel extends PopupPanel {
public MyPopupPanel(String nomeArticolo, String autore, String mail) {
/*
* L’utilizzo del costruttore PopupPanel(true) permette di settare la variabile
* auto-hide a true, nascondendo il pannello popup al primo click esterno allo stesso
*/
super(true);
HTML html = new HTML(“<a href=\”#\”>” + nomeArticolo + “</a>” +
“<br /><img src=\”inbox.gif\” /> “ +
“<a href=\”mailto:” + mail + “\”>” + autore + “</a>”, true);
setWidget(html);
setStyleName(“myPopup”);
}
}
private String imageItemHTML(String imageUrl, String title) {
return “<span><img style=’margin-right:4px’ src=’” + imageUrl.toLowerCase()
+ “’>” + title + “</span>”;
}
}

LISTATO 3 La classe Reviews.java

24 n.3 - marzo/aprile 2007


JAVA Journal AJAX speciale

seguenti classi CSS: base, abbiamo deciso di non inserire uno scheletro nel corpo
della pagina HTML ma di eseguire solamente il codice conte-
.gwt-MenuBar {} nuto nel modulo javascript gwt.js con il seguente comando:
.gwt-MenuBar .gwt-MenuItem {}
.gwt-MenuBar .gwt-MenuItem-selected {} <script language=”javascript” src=”gwt.js”></script>

Il secondo oggetto che dovremo modificare tramite CSS,


invece è un oggetto di tipo PopupPanel, che non ha un CSS
che gli sia abbinato automaticamente dai GWT come la
classe MenuBar. In questo caso, oltre a definire la classe
CSS nella pagina HTML, dovremo inserire nel codice Java
la seguente riga di codice:

setStyleName(“myPopup”);
I progetti creati con i
per legare la classe dei vari popup, MyPopupPanel, della GWT sono pronti per
quale discuteremo più avanti, allo stile definito nel codice
HTML: .myPopup. In questa classe CSS viene inoltre defini-
to uno stile che necessita di una immagine per poter creare
Eclipse, Ant e JUnit
lo sfondo del popup:

background-image: url(gray_gradient.gif);

Le immagini necessarie all’applicazione, per essere inserite


nella pagina, devono essere salvate nella cartella public,
dove si trova il file Reviews.html e che è la cartella princi-
pale della nostra applicazione AJAX.
Mentre il file Reviews.html contiene i codici per definire La classe EntryPoint del nostro modulo GWT Reviews
l’aspetto della pagina HTML, il file Reviews.java contiene il dovrà creare l’applicazione gestendo completamente il
codice che definisce il comportamento della pagina, a parti- posizionamento degli oggetti. Questa suddivisione della
re dalla sua composizione. A differenza dell’applicazione di pagina viene fatta utilizzando due tipi di oggetti: panel e
widget. Panel e widget sono due super-
classi che vengono estese rispettivamen-
te dai contenitori per oggetti dinamici e
dagli oggetti stessi. Ogni oggetto grafico
in GWT estende una di queste due classi,
ereditandone i metodi necessari per es-
sere visualizzati nella pagina.
Nel metodo onModuleLoad() è contenuta
l’intera suddivisione della pagina trami-
te pannelli. Qui vengono creati e posizio-
nati due pannelli:

1. un pannello principale, di tipo


DockPanel chiamato page;
2. un secondo pannello di tipo
VerticalPanel chiamato treeRev.

Il pannello treeRev viene aggiunto al pan-


nello page con il comando:

page.add(treeRev, DockPanel.WEST);

e infine, il pannello page viene inserito


nella pagina con il comando:

RootPanel.get().add(page);

Per chi ha conoscenze di Swing, il


primo comando è semplice da com-
prendere; per chi invece non ha mai
FIGURA 3 L’aspetto finale dell’applicazione Reviews

n.3 - marzo/aprile 2007 25


speciale AJAX JAVA Journal

utilizzato Swing e il BoxLayout, basti sapere che il comando o Jsp utilizzando le RPC (Remote Procedure Calls) con parti-
page.add(treeRev, DockPanel.WEST); aggiunge a page il colari classi GWT.
pannello treeRev posizionandolo ad Ovest, cioè attaccato I GWT, come visto, permettono la creazione di pagine AJAX
al bordo sinistro del contenitore. senza dover conoscere javascript e le sue implicazioni ma
Il metodo onModuleLoad() esegue anche il comando ad- solamente inserendo particolari classi nel codice Java e,
dTree() che crea un menu ad albero utilizzando la classe soprattutto, utilizzando metodi simili a quelli che vengono
Tree. I comandi utilizzati per creare l’albero sono tre: utilizzati con altri strumenti.
Seguendo la politica di Google del “no-evil”, come riporta-
1. il comando Tree tree = new Tree(); che istanzia l’albe- to sul sito, i GWT vengono rilasciati sotto licenza Apache 2.0
ro. Open Source License permettendo la navigazione del codice
2. il comando TreeItem <variabile> = new TreeItem(); più complesso e, come auspicabile, un veloce migliora-
che crea un nodo dell’albero contenente del codice mento delle funzionalità più interessanti. In particolare,
HTML. il Google Team vuole rendere stabili, entro il 2008, i mec-
3. il comando <variabile>.addItem(<nodo>); che lega canismi di RPC che permettono la comunicazione client-
un nodo all’albero o al ramo superiore. server. Questo processo potrebbe fornire agli sviluppatori
la possibilità di creare con pochi comandi dei web-service
Quindi, con il comando setState(true); determino che utilizzando solo codice Java e client personalizzati e visua-
il nodo dell’albero sia espanso, mentre con il comando lizzabili tramite browser.
treeRev.add(tree); inserisco l’albero nel pannello treeRev, Il progetto è solo agli inizi ma, visto che Google è l’azienda
facendolo quindi visualizzare sul lato sinistro della pagi- capofila, ci si può aspettare un salto in avanti da un mo-
na. mento all’altro, cosa auspicabile sia per il programmatore
I nodi dell’albero devono essere scritti in HTML e, per esperto che per il neofita che non deve così imparare altri
inserire i vari nodi, l’applicazione utilizza due metodi linguaggi oltre a Java.
appositi per la creazione delle stringhe formattate: imageI-
temHTML() e nuovoArticolo(). Il primo di questi due metodi
crea un area di tipo <span> contenente un immagine e
un testo; il secondo crea il codice HTML della finestra Po-
pup. La finestra verrà visualizzata istanziando un pannello
particolare di tipo MyPopupPanel che, a sua volta, estende
la classe PopupPanel. La classe MyPopupPanel contiene un
oggetto di tipo HTML, ossia una Label contenente codice
HTML con i riferimenti all’articolo e all’autore, passati al I GWT vengono
metodo tramite il suo costruttore. L’oggetto HTML così
creato viene settato come widget principale della classe rilasciati sotto licenza
MyPopupPanel, diventando il corpo dell’oggetto.
Il metodo nuovoArticolo() crea quindi un altro oggetto di
tipo HTML, collegandoci un istanza della classe clickLi- Apache 2.0 Open
stener, esattamente come in precedenza veniva fatto per
il pulsante nell’applicazione di base. Il metodo onClick() Source License
istanzia una variabile di tipo MyPopupPanel e ne definisce
la posizione. Il pannello di popup viene quindi mostrato
tramite l’esecuzione del metodo show() della variabile
creata.

Conclusioni
Riferimenti
Dopo aver completato la scrittura del modulo, la compila-
zione avviene utilizzando ant oppure lanciando il comando 1 http://code.google.com/webtoolkit/
Reviews-compile.cmd. Al termine della compilazione, trove- 2 http://ajax.asp.net/
remo una cartella www con all’interno una serie di file. 3 http://developer.yahoo.com/yui
Questi file sono il risultato della compilazione del modulo 4 http://sarissa.sourceforge.net/
e della sua trasformazione in AJAX, suddivisi per browser.
Al caricamento della pagina AJAX, una serie di comandi
Note Biografiche
javascript valuteranno quale browser tenti di accedere al
codice e caricheranno al giusta versione dei moduli GWT. Jacopo Giudici si occupa di applicazioni per il Web, di RFID e di
domotica su piattaforme J2ME, J2EE e .NET. Progetta e tiene
Inoltre, la compilazione crea una cartella chiamata tomcat corsi di formazione aziendali sulla sicurezza delle reti informa-
che conterrà, al momento, una serie di file di configura- tiche e sulla programmazione Java per ambienti distribuiti.Ha
zione del server Apache Tomcat. Questa cartella serve a lavorato per Microsoft, BottegaVerde, CONAD, Confartigiana-
to e ha pubblicato una collana di 6 libri con DeAgostini Scuola
configurare Tomcat per applicazioni GWT più complesse sui Sistemi Elettronici-Informatici per il triennio degli istituti
che necessitino di comunicazione con oggetti quali Servlet tecnici superiori.

26 n.3 - marzo/aprile 2007


ORIZZONTI
FREESPEECH ENTERPRISE Login Topic

Tutto ciò che è tendenza nel


mondo JEE
>> di Fabio Staro (fabio.staro@javajournal.it) • non dipende dallo stato di altri servizi (stateless);
• è ricercabile e recuperabile dinamicamente;
• è definito dalla sua interfaccia (contract), indipendente dalla
implementazione tecnologica del servizio stesso;

Quanto riportato, evidenzia come un servizio sia debolmente


accoppiato (loosely coupled), sia da un punto di vista tecnolo-
SOA, Web Services e BPEL: un po’ di chiarezza.Orizzonti gico, in quanto il servizio può essere implementato mediante
Enterprise, rubrica su ciò che è innovativo nel mondo enterprise, tecnologie eterogenee, per esempio JEE o .NET, esponendo
si propone come un momento di analisi il cui obiettivo è collo- tuttavia una interfaccia standard, e sia da un punto di vista
care nel giusto ambito di competenza le tecnologie di … “ten- funzionale, in quanto il servizio è sì componibile insieme ad
denza”. In questo articolo definiamo una architettura a servizi e altri servizi per la costituzione di processi di business comples-
alcune tecnologie correlate a tale paradigma di sviluppo. si, ma è intrinsecamente autoconsistente.
In sintesi un servizio di business è definito da una interfaccia
Una architettura SOA, acronimo di Service Oriented pubblicabile sulla rete ed è ricercabile ed invocabile indipen-
Architecture, è una architettura software atta a supportare dentemente dal linguaggio e dalla piattaforma di implemen-
l’uso di servizi per soddisfare le richieste degli utenti. Un servizio tazione. Pertanto in una architettura SOA sono definiti i ruoli
in SOA è business driven, ossia è un componente che presenta di service consumer, service provider e service registry. Il consu-
un reale significato per gli esperti funzionali e di dominio. In mer è l’entità che richiede un servizio, il provider è l’entità che
modo puntuale un servizio: fornisce il servizio ed infine il registry è un repository in rete
di tutti i servizi consultabili e fruibili. Quanto finora espresso
• è una funzione di business auto-contenuta; presenta similitudini con i termini presenti nello sviluppo

FIGURA 1 Pila dei protocolli dei web service (adattata da: http://it.wikipedia.org/wiki/Web_service)

n.3 - marzo/aprile 2007 28


FREEORIZZONTI
SPEECH ENTERPRISE Login Topic

dei componenti web service. Ma quale rapporto intercorre ha notevolmente migliorato il supporto per i web service
tra SOA e i web service? I web service sono una specifica e al contempo lo ha semplificato attraverso l’uso delle
tecnologica attraverso la quale pubblicare e invocare sul web annotazioni (cfr: JSR 181, Web Services Metadata for the Java
dei servizi; SOA è un paradigma architetturale (architectural Platform). In particolare esporre un EJB di tipo stateless
pattern) per il software design. In sintesi i web service sono una come web service è estremamente semplice. Attraverso
implementazione, la principale, è vero, ma non l’unica (se si l’annotazione
pensa per esempio al mondo CORBA), del paradigma SOA. La
Figura 1 mappa i ruoli di una architettura SOA sui protocolli javax.jws.WebMethod
di rete utilizzati per definire, localizzare ed invocare i servizi
web. Con riferimento alla figura, possiamo definire i tre pro- è possibile identificare i metodi che saranno esposti come ope-
tocolli di riferimento: razioni del web service mentre attraverso l’annotazione

• SOAP, acronimo di Simple Object Access Protocol, è un javax.jws.WebService


protocollo in formato XML per lo scambio dei messaggi tra
componenti software; si dichiara un session bean che funge da web service endpoint.
• WSDL, acronimo di Web Services Description Language, è Di seguito è riportato un semplice listato di esempio.
un linguaggio formale in formato XML per descrivere l’in-
terfaccia pubblica di un servizio web; ed infine, …
• UDDI, acronimo di Universal Description Discovery and @Stateless(name=”CodiceFiscale”)
Integration, è un registro attraverso il quale pubblicare e @WebService
ricercare i servizi in rete. public class CodiceFiscaleBean
{
@WebMethod(operationName=”verificaCodice”)
Tuttavia, nel mondo reale le interazioni commerciali ed indu- public boolean verifica(String cf) {
striali sono complesse e non si esauriscono con l’invocazione …
di un singolo servizio, ma necessitano della composizione di }
vari servizi per il soddisfacimento dei processi di business. …
BPEL, acronimo di Business Process Execution Language, è }
un linguaggio basato su XML mediante il quale è possibile …
definire il processo di business coordinando l’invocazione di
vari servizi (web services orchestration). L’appuntamento è alla prossima puntata, dove parleremo
Come si relaziona la piattaforma JEE 5 con il mondo SOA della moda del momento: gli ESB (Enterprise Service Bus) e
ed in particolare con i web service? La piattaforma JEE 5 di BPEL.

n.1 - novembre/dicembre 2006 29


JAVA Journal educational

Introduzione agli
EJB 3.0
Prima Parte
Con la nuova specifica 3.0 la SUN ha eseguito una reingegnerizzazione della tecnologia EJB ar-
ricchendo l’API di nuove caratteristiche e semplificando, in modo radicale, lo sviluppo dei bean
enterprise.

>> di Fabio Staro (fabio.staro@javajournal.itt)

• i componenti di tipo Session Bean realizzano tipica-


Premessa mente i processi per la logica di business;
• i componenti di tipo Message-Driven Bean risolvono i
Nelle applicazioni di classe enterprise l’uso della processi di tipo asincrono;
tecnologia degli Enterprise JavaBeans è argomento • ed infine i componenti Entity Bean consentono la
controverso tra i software architect poichè i servizi persistenza dei dati essendo di fatto una tecnologia
messi a disposizione da un container EJB non sem- ORM (Object Relational Mapping).
pre bilanciano la complessità di sviluppo e deploy.
Con l’avvento degli EJB versione 2.0 il progettista Come si è detto in precedenza, le applicazioni che
J2EE aveva a disposizione una tecnologia complessa beneficiano maggiormente della presenza degli
ma matura per realizzare applicazioni di classe enter- Enterprise JavaBeans presentano componenti tran-
prise, ossia applicazioni con un forte carattere distri- sazionali e delocalizzabili. Infatti i componenti EJB
buito e transazionale. La specifica degli EJB 2.x pre- possono essere “facilmente” distribuiti su diversi ser-
senta tre tipi di Enterprise JavaBeans: i Session Bean, i ver, consentendo di fatto una migliore suddivisione
Message-Driven Bean e gli Entity Bean. Senza entrare in del carico computazionale, e possono garantire, se ve
dettaglio possiamo sintetizzare il carattere specifico ne fosse la necessità, un contesto transazionale unico
dei tre tipi di Enterprise JavaBeans (cfr. Tabella 1): interagendo con diversi resource manager, per esempio

Enterprise Bean Descrizione

Sono i componenti enterprise per lo sviluppo della logica di business.


Si suddividono in due tipi: gli Stateless Session Bean e gli Stateful
Session Bean. I primi sono senza stato, ossia ogni metodo del bean
Session Bean
rappresenta una funzione di business fine a se stessa mentre i secondi
consentono di conservare lo stato durante le varie invocazioni che
avvengono con il client.

Message -Driven Sono componenti enterprise per l’elaborazione asincrona. Sono


Bean generalmente in ascolto su una coda o un topic JMS.

Sono una tecnologia per la persistenza dei dati. Si dividono in BMP


e CMP. Nei bean di entità di tipo BMP gli statement SQL sono scritti
Entity Bean
dallo sviluppatore del bean mentre nei bean di entità di tipo CMP gli
statement SQL sono generati in automatico dal container EJB.

TABELLA1 tipi di EJB

n.3 - marzo/aprile 2007 31


educational JAVA Journal

FIGURA 1 una applicazione client invoca un bean enterprise X che esegue varie operazioni

database e/o code JMS. Mostriamo di seguito uno scenario


complesso e tuttavia realizzabile semplicemente attraverso • Supporto alle transazioni distributite;
l’uso di EJB. Si osservi la Figura 1: una applicazione client • Delocalizzazione delle componenti di business;
invoca un bean enterprise X che esegue tre operazioni. Più • Supporto per la gestione della sicurezza role-based;
precisamente: • Supporto al pooling e al caching delle istanze dei bean;
• Supporto allo sviluppo di web service.
• invia un messaggio verso un sistema di messagistica, per
esempio una coda JMS; Tuttavia a fronte dei benefici sopra elencati sviluppare un
• aggiorna i dati presenti in un primo database; EJB versione 2.x richiede una buona dose di “pazienza”
• e poi invoca un secondo bean enterprise Y (che potrebbe e una sicura competenza. Per esempio, per sviluppare un
anche risiedere su un diverso server). EJB di tipo Session Bean è necessario creare:

A sua volta il bean enterprise Y esegue una operazione di • due interfacce;


aggiornamento su un secondo database. Lo scenario de- • una classe concreta;
scritto è una complessa transazione distribuita su diversi re- • e un file XML che descrive la configurazione del compo-
source manager. Grazie ai servizi offerti dall’application server, nente.
dove risiedono i componenti EJB, assicurare la semantica
transazionale appena descritta non richiede uno sforzo Inoltre la classe concreta che rappresenta il bean vero e pro-
particolare nello sviluppo, se non l’uso delle normali API prio deve implementare l’interfaccia javax.ejb.SessionBean e,
JDBC e JMS, poiché è il server EJB a garantire il contesto di conseguenza, deve implementare una serie di metodi di
transazionale attraverso l’uso del two-phase protocol [2] e del- callback, invocati dal container EJB durante il ciclo di vita
le API JTA [3] e JTS [4]. del componente, che nulla hanno a che fare con la logica
di business. Nel caso degli Entity Bean, poi, la complessità
L’esempio presentato è un caso complesso e limite. In aumenta a tal punto che, sebbene rappresentano la tecno-
effetti i componenti EJB in una architettura Java portano logia “ufficiale” per la persistenza dei dati, molto spesso
una serie di benefici che di seguito elenchiamo riman- non sono usati nei progetti per la presenza di alternative
dando alla copiosa letteratura sul tema per gli opportuni più semplici, flessibili e performanti (cfr. Hibernate [5]).
approfondimenti: Con la specifica degli EJB 3.0 la SUN ha eseguito una

32 n.3 - marzo/aprile 2007


JAVA Journal educational

radicale reingegnerizzazione della tecnologia arricchendo conoscenza di base della specifica 2.x e delle problematiche
notevolmente l’API ma soprattutto semplificando note- inerenti alla tecnologia EJB in generale. L’esempio riporta-
volemte lo sviluppo dei componenti. A testimonianza di to è stato verificato con l’application server JBoss versione
ciò riportiamo quanto segue, direttamente dal documento 5.0 [6] e con il database MySQL versione 5.0.27 [7].
della specifica:

… Gestione di una biblioteca


La release EJB 3.0 dell’architettura Enterprise JavaBeans fornisce
allo sviluppatore di applicazioni enterprise una API nuova e sem- L’esempio da realizzare, volutamente semplice al fine di
plificata. Questa API è mirata alla facilità di sviluppo e rappresen- soffermarci sugli aspetti tecnici e non funzionali, è un
ta una semplificazione delle API definite dalle precedenti versioni componente per la gestione di una biblioteca. Il compo-
della specifica EJB. nente consente una operazione di ricerca, restituendo
… l’elenco dei libri di un autore, e una operazione di assegna-
mento di un libro presente in biblioteca ad un utente che
ne ha fatto richiesta. Pertanto la interfaccia di business del
componente è semplicemente:

public interface GestoreBiblioteca


{
Gli Entity Bean public List<Libro> getLibri(String nomeAutore);
public void assegna(Persona persona, Libro libro)
versione 3 sono in }
throws LibroNonDisponibile;

pratica un ORM Per implementare il componente gestore della biblioteca


come un EJB 3.0 di tipo session stateless è sufficiente:

• Creare una classe che implementi l’interfaccia di busi-


ness GestoreBiblioteca;
• Annotare la classe con l’annotazione @javax.ejb.Stateless;
In questo primo articolo introdurremo alcune delle princi-
pali “feature” degli EJB 3.0 e fin dai primi esempi si evi-
denzierà lo sforzo, pienamente riuscito da parte degli au- Lo stralcio di codice che segue riporta la definizione della
tori della specifica, di semplificare e razionalizzare il lavoro classe GestoreBibliotecaBean:
degli sviluppatori Java. Questo articolo è una introduzione
alla specifica 3.0 sebbene si dà per acquisita almeno una @Stateless (name=”Biblioteca”)

EJB session 2.x EJB session 3.x


Interfaccia che estende
Semplice interfaccia Java
Business interface javax.ejb.EJBObject o
eventualmente annotata.
javax.ejb.EJBLocalObject
Classe che deve implementare la
POJO che implementa la
interfaccia javax.ejb.SessionBean e di
business interface e dichiarato
Bean Class conseguenza implementare i metodi
con la annotazione @Stateless o
di callback: ejbActivate(), ejbPassivate,
@Stateful.
ejbRemove(), setSessionContext().
Obbligatoria. Deve estendere o la
Home interface interfaccia javax.ejb.EJBHome o la Non presente.
interfaccia javax.ejb.EJBLocalHome.
Non obbligatori. La via
Deployment
Obbligatori. preferenziale per caratterizzare un
Descriptor
EJB è attraverso le annotazioni
Dependency
Non presente. Presente.
Injection
TABELLA 2 Alcune differenze tra la versione EJB 2.x e 3.x

n.3 - marzo/aprile 2007 33


educational JAVA Journal

package it.articolo.ejb;
import it.articolo.ejb.interceptors.LogInterceptor;
import it.articolo.ejb.interceptors.PerformanceInterceptor;
import java.util.List;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.sql.DataSource;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionManagementType;
import javax.ejb.TransactionAttributeType;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.logging.Log;
@Stateless (name=”Biblioteca”)
@TransactionManagement(TransactionManagementType.CONTAINER)
public class GestoreBibliotecaBean implements GestoreBiblioteca {
private static Log oLogger = LogFactory.getLog(GestoreBibliotecaBean.class);
@Resource (name=”jdbc/exampleDatasource”)
DataSource theDatasource = null;
@Interceptors({PerformanceInterceptor.class, LogInterceptor.class})
public List<Libro> getLibri(String nomeAutore)
{
oLogger.info(“Invocato metodo EJB (CON INJECTION)”);
List<Libro> oListaLibri = new DAOGestoreBiblioteca().getLibri(nomeAutore,
theDatasource);
return oListaLibri;
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void assegna(Persona persona, Libro libro) throws LibroNonDisponibile {
assegnaLibro(persona, libro);
boolean result = diminuisciNumeroCopie(libro);
if (!result)
throw new LibroNonDisponibile(“Il libro: “+libro.getTitolo()
+” non è disponibile per il prestito”);
}
private boolean diminuisciNumeroCopie(Libro libro) throws LibroNonDisponibile {
boolean operationResult = new DAOGestoreBiblioteca().diminuisciNumeroCopie(libro,
theDatasource);
return operationResult;
}
private void assegnaLibro(Persona persona, Libro libro) {
new DAOGestoreBiblioteca().assegnaLibro(persona, libro, theDatasource);
}
}

LISTATO 1 La classe GestoreBibliotecaBean

public class GestoreBibliotecaBean implements e che non hanno un legame diretto con un container o con
GestoreBiblioteca un application server. Con gli EJB 3.0 non sono più obbli-
{ gatori i file XML di configurazione, i talvolta complessi e
… sicuramente prolissi deployment descriptor, essendo possibile
} definire tutte le caratteristiche di un EJB attraverso le an-
notazioni. La Tabella 2 riporta alcune differenze e sempli-
Le poche righe di codice sopra riportate sono di fatto il no- ficazioni che si hanno per gli EJB di tipo session passando
stro EJB 3.0 di nome Biblioteca e mostrano un carattere di- dalla versione 2.x alla versione 3.x.
stintivo ed innovativo degli EJB 3.0 rispetto alle precedenti
versioni 2.x e 1.x: gli EJB 3.0 sono POJO, acronimo di Plain Il carattere remoto o locale di un EJB si definisce attraver-
Old Java Object, ossia semplici classi Java che non devono so le due annotazioni
implementare interfacce particolari e/o metodi di callback

34 n.3 - marzo/aprile 2007


JAVA Journal educational


@TransactionManagement(TransactionManagementType.CONTAINER)
public class GestoreBibliotecaBean implements GestoreBiblioteca
{

@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void assegna(Persona persona, Libro libro) throws LibroNonDisponibile {
assegnaLibro(persona, libro);
boolean result = diminuisciNumeroCopie(libro);
if (!result)
throw new LibroNonDisponibile(“Il libro: “+libro.getTitolo()
+” non è disponibile per il prestito”);
}
private boolean diminuisciNumeroCopie(Libro libro) throws LibroNonDisponibile {
boolean operationResult =
new DAOGestoreBiblioteca().diminuisciNumeroCopie(libro, theDatasource);
return operationResult;
}
private void assegnaLibro(Persona persona, Libro libro) {
new DAOGestoreBiblioteca().assegnaLibro(persona, libro, theDatasource);
}

}

LISTATO 2 Metodo business assegna () della classe GestoreBibliotecaBean

@javax.ejb.Remote contemporaneamente locale e remota ma che un EJB può


implementare più interfacce di business.
@javax.ejb.Local

Un componente EJB locale può essere invocato solo da La dependency Injection


applicazioni client che risiedono nella medesima Java
Virtual Machine mentre un componente EJB che espone Il componente GestoreBiblioteca deve poter accedere al da-
una interfaccia remota può essere invocato da applicazioni tabase per poter espletare le sue funzioni di ricerca e di
client che risiedono in una diversa Java Virtual Machine ed assegnamento (cfr. Listato 1). Con la precedente versione
in generale su altri computer. Nel nostro esempio il com- 2.x degli EJB i passi necessari per accedere ad un database,
ponente gestore della biblioteca può essere invocato da dopo aver definito un oggetto datasource sull’application
applicazioni client che non girano nella medesima JVM e server, sono:
pertanto l’interfaccia di business del gestore è caratterizza-
ta dall’annotazione @Remote: • Definire una reference nel file ejb-jar.xml per il datasour-
ce;
@Remote • Connettersi al contesto JNDI;
public interface GestoreBiblioteca { • Eseguire una operazione di lookup della risorsa sull’albe-
… ro JNDI, eseguendo poi il cast opportuno;
}
Le righe di codice che seguono sono esemplificative dei
Osserviamo che una interfaccia di business non può essere passi sopra enunciati (il primo frammento di codice è re-

<?xml version=”1.0” encoding=”UTF-8”?>


<datasources>
<local-tx-datasource>
<jndi-name>theDataSource</jndi-name>
<connection-url>jdbc:mysql:///test</connection-url>
<driver-class>com.mysql.jdbc.Driver</driver-class>
<user-name></user-name>
<password></password>
<exception-sorter-class-name/>
</local-tx-datasource>
</datasources>

LISTATO 3 Definizione del datasource verso MySQL in Jboss

n.3 - marzo/aprile 2007 35


educational JAVA Journal

<?xml version=”1.0” encoding=”UTF-8”?>


<!DOCTYPE jboss PUBLIC “-//JBoss//DTD JBOSS 3.2//EN” “http://www.jboss.org/j2ee/dtd/jboss_3_
2.dtd”>
<jboss>
<unauthenticated-principal>nobody</unauthenticated-principal>
<enterprise-beans>
<session>
<ejb-name>Biblioteca</ejb-name>
<resource-ref>
<res-ref-name>jdbc/exampleDatasource</res-ref-name>
<jndi-name>java:theDataSource</jndi-name>
</resource-ref>
<method-attributes/>
</session>
</enterprise-beans>
<resource-managers/>
</jboss>

LISTATO 4 Il file jboss.xml

lativo al deployment descriptor, il file ejb-jar.xml, mentre il come le operazioni di lookup sono di fatto eliminate nella
secondo alla classe del bean). nuova specifica EJB 3.0:

… …
<resource-ref> public class GestoreBibliotecaBean implements
<description></description> GestoreBiblioteca
<res-ref-name>jdbc/exampleDatasource </res-ref-name> {
<res-type>javax.sql.DataSource</res-type> @Resource (name=”jdbc/exampleDatasource”)
<res-auth>Container</res-auth> DataSource theDatasource = null;
<res-sharing-scope>Shareable</res-sharing-scope> }
</resource-ref> …

Attraverso l’annotazione @javax.annotation.Resource è va-
… lorizzato da parte del container l’oggetto theDatasource di
// Codice per ottenere il contesto JNDI tipo javax.sql.DataSource prima che sia invocato un qualsiasi
Context initCtx = new InitialContext(); metodo di business dell’EJB da parte di un client.
// Operazione di lookup In modo analogo, attraverso l’annotazione @javax.ejb.EJB
javax.sql.DataSource ds = (javax.sql.DataSource) è possibile referenziare un secondo componente EJB. Di
initCtx.lookup(“java:comp/env/jdbc/exampleDatasource”); seguito un esempio di codice:


In generale i passi necessari per eseguire le operazioni di public class GestoreBibliotecaBean implements
lookup sull’albero JNDI per una risorsa esterna sono ripeti- GestoreBiblioteca
tivi e soprattutto sono dettati dal contesto tecnologico e {
non dalla logica di business. Inoltre, la dipendenza di un @EJB SecondEJB secondEJB;
componente EJB dall’API JNDI rende complesso il test …
unitario del componente al di fuori di un container EJB. }
Il problema è che nelle righe di codice sopra riportate la …
classe del bean enterprise ha un legame diretto con la tec-
nica attraverso la quale si recupera un riferimento ad una La sintassi equivale ad eseguire una operazione di lookup
risorsa esterna (nell’esempio un datasource, ma di fatto può dell’EJB individuato dalla reference java:comp/env/ejb/
anche essere una queue o un topic JMS, un altro EJB, ecc.). secondEJB. Per apprezzare la semplificazione introdotta
La dependency injection rovescia tale paradigma essendo il riportiamo di seguito il codice presente in un EJB 2.x per
container EJB a passare alla classe del bean enterprise una risolvere la medesima reference al secondo EJB:
reference alla risorsa esterna. Detto in altri termini, il con-
tainer EJB inietta nel bean enterprise una reference per la …
risorsa esterna prima che sia eseguito un qualsiasi metodo Context ctx = new InitialContext();
di business del bean. Lo stralcio di codice che segue mostra SecondEJBHome secondEJBHome = (SecondEJBHome)javax.rmi.Porta

36 n.3 - marzo/aprile 2007


JAVA Journal educational

bleRemoteObject.narrow(
ctx.lookup(“java:comp/env/ejb/secondEJB”), La specifica EJB 3.0 definisce due annotazioni per la ge-
SecondEJBHome.class); stione delle transazioni:
SecondEJB secondEJB = secondEJBHome.create();
… • @TransactionManagement
• @TransactionAttribute

Gestione delle transazioni Attraverso l’annotazione @TransactionManagement si di-


chiara se le transazioni sono gestite automaticamente dal
Il gestore della biblioteca ha tra le sue funzionalità la container EJB o manualmente dallo sviluppatore dell’EJB
possibilità di assegnare un libro ad un utente che ne fa attraverso l’API JTA; mentre con l’annotazione @Transac-
richiesta. L’operazione di assegnamento si compone di tionAttribute è possibile definire il comportamento transa-
due passi fondamentali: il primo passo è il vero e pro- zionale di un metodo di business dell’EJB. I valori validi
prio assegnamento del libro all’utente della biblioteca per l’annotazione @TransactionManagement sono definiti
mentre il secondo passo è la verifica che vi sia almeno nella enumerazione TransactionManagementType presente
una copia del libro in biblioteca per poterlo imprestare nel package javax.ejb e sono:
(i passi sono stati così strutturati per mostrare la gestio-
ne automatica delle transazionin da parte del container • CONTAINER
EJB). Nel caso in cui il libro risultasse non disponibile • BEAN
la precedente operazione di assegnamento deve essere
annullata. Mentre i valori validi per l’annotazione @TransactionAttri-

package it.articolo.client;
...
public class Client {

public static void main(String[] args) throws NamingException


{
Client oClient = new Client();
Object oObject = oClient.lookupEJB(“Biblioteca/remote”);
GestoreBiblioteca oEJB = (GestoreBiblioteca)oObject;
List<Libro> libri = oEJB.getLibri(null);
// VISUALIZZA A CONSOLE TUTTI I LIBRI
oClient.log(libri.toString());
Persona persona = new Persona();
persona.setCognome(“Fabio”);
persona.setNome(“Staro”);
try {
// OPERAZIONE DI ASSEGNAMENTO DI UN LIBRO
oEJB.assegna(persona, libri.get(0));
} catch (LibroNonDisponibile e) {
oClient.log(“ECCEZIONE:”+e.getMessage());
}
}

private Object lookupEJB(String nomeEJB) throws NamingException


{
Properties props = new Properties();
props.put(Context.INITIAL_CONTEXT_FACTORY, “org.jnp.interfaces.NamingContextFactory”)
;
props.put(Context.PROVIDER_URL, “jnp://localhost:1099”);
Context ctx = new InitialContext(props);
return ctx.lookup(nomeEJB);
}
private void log(String msg)
{
out.println(“[“+this.getClass().getName()+”]:”+msg);
}
}

LISTATO 5 La classe client che invoca l’EJB

n.3 - marzo/aprile 2007 37


educational JAVA Journal

}
bute sono definiti nella enumerazione TransactionAttribu- }
teType, sempre presente nel package javax.ejb, e sono: …

• NOT_SUPPORTED Attraverso l’annotazione


• REQUIRED
• REQUIRES_NEW @ApplicationException(rollback=true)
• SUPPORTS
• MANDATORY si informa il container EJB di eseguire una operazione di
• SUPPORTS rollback automatica al verificarsi della eccezione.

La semantica dei valori sopra riportati è ben schematizzata


nella Tabella 3. A titolo di esempio osservando la Tabella
3 possiamo notare che se un componente client che non
ha iniziato una transazione invoca un metodo di un EJB
per il quale il valore dell’annotazione @TransactionAttribute
è REQUIRED il container EJB inizia una transazione nella
quale esegue il metodo di business. Viceversa, se sempre
il medesimo componente client inizia una transazione e
Il Server EJB
invoca il metodo precedente dell’EJB, allora il container
non inizia una nuova transazione ma esegue il metodo di garantisce il contesto
business nel contesto transazionale del client.
Se una o entrambe le annotazioni sono omesse, varranno i transazionale
valori di default, che sono:

• CONTAINER per l’annotazione @TransactionManage-


ment
• REQUIRED per l’annotazione @TransactionAttribute

Per illustrare la gestione automatica delle transazioni da


parte del container riprendiamo l’esempio della biblioteca Metodi interceptor
e la classe GestoreBibliotecaBean. Questa presenta il metodo
di business assegna(). Il metodo fa due operazioni elemen- Un’altra interessante caratteristica degli EJB 3.0 sono gli
tari: assegna il libro richiesto ad un utente della biblioteca interceptor. La definizione di un interceptor è fornita diretta-
(operazione che si semplifica in un comando di inserimen- mente dalla specifica:
to sulla base dati) e diminuisce il numero di copie presenti
in biblioteca per il libro richiesto (operazione di aggiorna- “Un interceptor è un metodo che intercetta l’invocazione di un
mento sulla base dati). Lo stralcio di codice nel Listato 2 metodo business o di un evento callback del ciclo di vita. Un meto-
mostra il metodo di business assegna (). do interceptor può essere definito nella classe bean o in una classe
interceptor associata al bean.”
Il metodo diminuisciNumeroCopie() verifica per il libro ri-
chiesto il numero di copie presenti in biblioteca e nel caso Attraverso un metodo interceptor è possibile eseguire delle
in cui il libro richiesto risulta presente, aggiorna il numero funzionalità prima e dopo l’invocazione di un metodo di
di copie diminuendone il valore di una unità. Il metodo business. Il metodo interceptor può essere dichiarato o nella
nel caso di indisponibilità per il libro richiesto lancia la stessa classe del bean o in una classe separata che prende
eccezione applicativa LibroNonDisponibile. In caso di ecce- il nome di interceptor class. Riprendiamo ora l’esempio della
zione, la precedente operazione di assegnazione del libro biblioteca e supponiamo di voler misurare il tempo di ese-
all’utente richiedente, effettuata dal metodo assegna (), cuzione del metodo getLibri() e di voler memorizzare, per
deve essere sottoposta a rollback . L’eccezione LibroNonDi- esempio su tabella, l’utente che ha invocato il metodo e
sponibile è così definita: altre informazioni di contesto. Attraverso l’uso di due inter-
ceptor class è possibile separare l’operazione di misura della
… performance e l’operazione di logging dalla operazione di
@ApplicationException(rollback=true) business vera e propria, migliorando in tal modo la chia-
public class LibroNonDisponibile extends Exception rezza e la manutenibilità del codice. Di seguito è riportato
{ uno stralcio della classe GestoreBibliotecaBean.
public LibroNonDisponibile(String message) {
super(message); @Stateless (name=”Biblioteca”)
} public class GestoreBibliotecaBean implements
GestoreBiblioteca
public LibroNonDisponibile(String message, Throwable {
cause) { @Interceptors({PerformanceInterceptor.class,
super(message, cause); LogInterceptor.class})

38 n.3 - marzo/aprile 2007


JAVA Journal educational

public List<Libro> getLibri(String nomeAutore)


{ • getTarget(): restituisce l’oggetto sul quale sarà invocato il
… metodo di business;
} • getMethod(): restituisce il metodo di business invocato;
} • getParameters(): restituisce i parametri che saranno usati
come input nella esecuzione del metodo di business;
E, a titolo di esempio, il codice della classe interceptor • setParameters(): consente di impostare nuovi parametri di
PerformanceInterceptor: input per l’esecuzione del metodo di business;
• proceed (): esegue il metodo successivo nella catena di
… invocazione.
public class PerformanceInterceptor {
private static Log oLogger = LogFactory.getLog(Performan L’invocazione di un interceptor method avviene nello stesso
ceInterceptor.class); contesto transazionale e di sicurezza del metodo di busi-
@AroundInvoke ness e un interceptor method può rilanciare runtime exception
public Object performance(InvocationContext ctx) throws o application exception definite nella firma del metodo di
Exception { business.
long start = System.currentTimeMillis();
try {
return ctx.proceed();
Deploy del componente
}
finally Il packaging del componente come EJB 3.0 è estremamen-
{ te semplice. È sufficiente creare un file .jar che contiene la
long end = System.currentTimeMillis(); classe bean, l’interfaccia di business e le eventuali classi
oLogger.info(“IL METODO:”+ctx.getMethod().getNa interceptor. Come si è detto all’inizio dell’articolo, i file de-
me()+ ployment descriptor sono opzionali, ma se presenti devono
“ E’ STATO ESEGUITO IN: essere all’interno della cartella META-INF. Il deploy del
”+(end-start)+” MILLISECONDI”); componente nell’application server JBoss 5 è la semplice
} copia del file .jar nella directory deploy del server.
}
}

Conclusioni

In questo primo articolo abbiamo introdotto alcune ca-


Osservando il codice si nota che attraverso l’annotazione ratteristiche degli EJB 3.0 evidenziando le semplificazioni
@Interceptors è possibile dichiarare una o più interceptor class introdotte. Per quanto si è mostrato, è chiaro come gli EJB
e con l’annotazione @AroundInvoke si definisce il metodo 3.0 possano definirsi “fine-grained object” non più complessi
che agisce da interceptor. A questo metodo è fornito come di un normale bean Java con la presenza di annotazioni,
parametro di input un oggetto che implementa l’interfac- al contrario degli EJB versione 2.x visti come “corse-grained
cia InvocationContext che è così definita: heavyweight object”. Nei prossimi articoli approfondiremo
ulteriormente le nuove caratteristiche soffermandoci poi
… sui message-driven bean e sui nuovi bean di entità.
public interface InvocationContext {
public Object getTarget();
public Method getMethod();
Riferimenti
public Object[] getParameters();
public void setParameters(Object[] params); [1]: JSR 220: Enterprise JavaBeans,Version 3.0, http:
public java.util.Map<String, Object> getContextData(); //java.sun.com/products/ejb/docs.html.
public Object proceed() throws Exception; [2]: http://en.wikipedia.org/wiki/Two-phase_commit
} [3]: http://java.sun.com/products/jta/
… [4]: http://java.sun.com/products/jts/
[5]: http://www.hibernate.org/
L’interfaccia InvocationContext fornisce i metadati attraver- [6]: http://www.jboss.com/.
so i quali è possibile gestire la catena di invocazione degli [7]: http://www.mysql.com/
interceptor (nell’esempio riportato la catena di invocazione
è costituita dalle classi PerformanceInterceptor, LogInterceptor
e, ovviamente, GestoreBibliotecaBean). In particolare gli in-
terceptors in una catena di invocazione possono passarsi e
condividere dati di contesto recuperandoli attraverso il me- Note Biografiche
todo getContextData() sulla istanza dello oggetto Invocation- Fabio Staro, dottore in Fisica è Responsabile Tecnico per i pro-
Context. Gli altri metodi dell’interfaccia InvocationContext getti Java presso la Direzione Ricerca ed Innovazione di Engi-
sono: neering Ingegneria Informatica S.p.A.

n.3 - marzo/aprile 2007 39


educational JAVA Journal

Tutto Java in un
Hello World
In questo articolo vediamo come sia possibile scrivere un Hello World senza fermarci al semplice
System.out.println(). Vedremo infatti collegate diverse tecnologie Java, che si legano una con l’altra
per veicolare un messaggio di prova.

>> di Federico Paparoni (federico.paparoni@javajournal.it)

istanziato all’avvio dell’applicazione server. L’imple-

Q
mentazione dell’oggetto RMI provvede quindi ad
uante volte avete incominciato a studia- inviare ad una coda JMS (Java Message Service)
re un linguaggio di programmazione? La il messaggio testuale. In questo caso utilizzeremo
cosa più bella in questi momenti è quan- una coda JMS messa a disposizione dall’application
do ancora non sapete niente di quello che server BEA WebLogic. Dall’altro capo della coda ab-
vi trovate davanti, non avete capito bene come è or- biamo in listening un oggetto che provvede, appena
ganizzato, vi affannate per cercare di capire se c’è un arriva un messaggio, ad inserirlo tramite JDBC (Java
IDE grafico che può aiutarvi e passate un bel po’ di Database Connectivity) nel nostro database. Infine
tempo su Google per cercare qualche articolo che vi abbiamo un’applicazione classica desktop che richie-
possa illuminare. Nonostante ciò, quando si inizia a de di continuo una pagina JSP (Java Server Pages),
studiare un nuovo linguaggio, il classico HelloWorld, la quale utilizzando JSTL (JavaServer Pages Standard
un semplice programma che scrive semplicemente a Tag Library) provvederà a restituirci il messaggio ap-
schermo una stringa di testo, è la cosa che viene fatta pena questo sarà disponibile nel nostro database.
abbastanza semplicemente e vi invoglia a continua- Insomma un bel giro di classi, metodi e tecnologie.
re, anche perché pensate “Ora voglio proprio vedere Incominciamo ora a vedere la prima applicazione da
come fare….”. Purtroppo dedicandoci ad un linguag- realizzare, ovvero quella JavaME.
gio in particolare, in questo caso Java, non possiamo
provare spesso questa emozione. Oggi in questo arti-
colo proveremo a scrivere un HelloWorld che attra-
versi tutto Java (o comunque una buona parte), per
vedere come tutte le tecnologie Java possono essere
legate insieme.

Un’applicazione
Architettura dell’applicazione
JavaME che si collega
L’architettura della nostra applicazione è abbastanza
ingarbugliata e quindi richiede un attimo di attenzio- ad una Servlet
ne per essere capita. Diciamo che tutto ciò viene fatto
per legare diverse tecnologie Java insieme e quindi
bisogna capire bene dove ciascuna componente entra
in gioco. Nella Figura 1 viene riportato un diagram-
ma della nostra applicazione che ci permette di avere
un’idea chiara di quello che succede. Come punto di
partenza abbiamo un’applicazione JavaME che si JavaME
collega ad una Servlet. L’applicazione invierà tramite
una classica connessione HTTP il messaggio. Succes- L’applicazione che in questo caso dobbiamo realiz-
sivamente la Servlet invierà questo messaggio ad un zare è abbastanza semplice. Dovremo creare un’in-
oggetto RMI (Remote Method Invocation), che viene terfaccia che permette di avviare la richiesta HTTP,

40 n.3 - marzo/aprile 2007


JAVA Journal educational

FIGURA 1 Architettura della nostra applicazione

utilizzando un Form classico, come viene riportato qui di vedere l’emulatore JavaME che mostra la MIDlet dopo
seguito l’esecuzione.


d = Display.getDisplay(this);
Servlet
form=new Form(“Java Hello World”);
form.append(“To launch the Java Hello World, press La Servlet ha due fasi distinte che devono essere analizza-
Start command”); te nella nostra applicazione: l’avvio e l’elaborazione della
start=new Command(“Start”,Command.OK, 1); richiesta. Durante l’avvio dobbiamo utilizzare il metodo
exit=new Command(“Exit”,Command.EXIT, 2); init() della Servlet per inizializzare tutte le risorse di cui
form.addCommand(start); avremo bisogno per il corretto funzionamento della no-
form.addCommand(exit); stra applicazione. Qui di seguito viene riportato il metodo
form.setCommandListener(this); init(), che viene richiamato nel momento in cui l’applica-
d.setCurrent(form); zione server viene installata/avviata.

public void init() throws ServletException {
In questo modo abbiamo presentato all’utente un’in- try {
terfaccia con due comandi disponibili: Start e Exit. Per System.out.println(“Start servlet”);
intercettare i comandi che abbiamo inserito nell’inter- Registry registry = LocateRegistry.createRegist
faccia dobbiamo implementare l’interfaccia Comman- ry(1199);
dListener, ovvero è necessario implementare il metodo HelloRMIImpl helloRMIImpl = new HelloRMIImpl();
commandAction() dove faremo partire la vera e propria registry.bind(“HelloRMI”, helloRMIImpl);
connessione verso il server HTTP. Nel Listato 1 è ripor- System.out.println(“Registrato oggetto RMI”);
tata la classe che permette di inviare la richiesta HTTP,
ed è implementata estendendo la classe Thread, per evi- jmsReceiver=new HelloJMSReceiver();
tare il deadlock della nostra applicazione. Come potete System.out.println(“Avviato JMS receiver”);
vedere, viene effettuata una chiamata HTTP utilizzando }
HttpConnection, un’interfaccia standard disponibile sulla catch(Exception e) {
piattaforma JavaME. La URL che viene richiamata è System.out.println(“init: “+e.toString());
quella della Servlet che dobbiamo implementare, alla }
quale viene passato un parametro che specifica il mes- }
saggio che vogliamo inviare. Alla fine dell’esecuzione di
questo Thread, viene restituito all’interfaccia grafica il Prima di tutto viene creato un registro RMI, nel quale
messaggio di risposta della Servlet. In Figura 2 potete viene inserito un oggetto RMI che in seguito andremo ad

n.3 - marzo/aprile 2007 41


educational JAVA Journal

analizzare. In questo caso abbiamo creato direttamente un


registro all’interno di una web application, una cosa non
troppo “pulita”. Di solito, infatti, sarebbe meglio avere RMI
il registro RMI separato, creato utilizzando l’eseguibile
rmiregistry.bat (o rmiregistry.sh) incluso nella distribuzio- Abbiamo visto come nel metodo doGet() della Servlet
ne standard di JavaSE. In questo caso abbiamo fatto così abbiamo utilizzato l’interfaccia HelloRMI. Questa estende
per vedere come poter inizializzare il registro direttamente l’interfaccia java.rmi.Remote e specifica quali metodi do-
da codice Java. Oltre all’oggetto RMI, che viene inserito nel vranno essere esposti dal nostro oggetto remoto (anche
registro, dobbiamo inizializzare l’oggetto Java che si occu- se in questo caso stiamo eseguendo tutto in locale). Di
perà di mettersi in listening sulla coda JMS. Ora possiamo seguito potete vedere l’interfaccia HelloRMI che abbiamo
vedere il metodo doGet() della Servlet, che si occuperà di definito:
gestire la richiesta che proviene dal programma JavaME.
package it.javajournal;
protected void doGet(HttpServletRequest request, import java.rmi.Remote;
HttpServletResponse response) import java.rmi.RemoteException;
throws ServletException, IOException {
try { public interface HelloRMI extends Remote {
HelloRMI obj = (HelloRMI)Naming.lookup(“rmi: void sendHello(String message) throws RemoteException;
//127.0.0.1:1199/HelloRMI”); }
obj.sendHello((String)request.getParameter(“msg”));
response.setContentType(“text/html;charset=UTF-8”); L’unico metodo di questa interfaccia è sendHello(), che può
PrintWriter out = response.getWriter(); lanciare eccezioni di tipo RemoteException. Ed è quindi ciò
out.println(“HelloWorld avviato!”);
out.close();
}
catch(Exception e) {
System.out.println(“processRequest:
“+e.toString());
}
}

Questo metodo utilizza direttamente l’oggetto HttpServ-


letRequest per avere le informazioni che sono state inviate
dalla MIDlet. Come possiamo vedere, viene recuperato il
parametro msg della richiesta HTTP e viene passato come
parametro al metodo sendHello() del nostro oggetto RMI.
Infine, viene restituita alla MIDlet la stringa “HelloWorld
avviato!”, che abbiamo già visto precedentemente nella
Figura 1. In questo modo il nostro messaggio ha già
effettuato un paio di salti, dalla MIDlet alla Servlet fino
all’oggetto RMI.

Inserire un messaggio
in una coda JMS

FIGURA 2 Emulatore JavaME con l’applicazione


di Hello World avviata

42 n.3 - marzo/aprile 2007


JAVA Journal educational

FIGURA 3 Configurazione JMS su BEA WebLogic 8.1

che un client remoto può sapere di un oggetto RMI. Per JMS. Questa classe implementa l’interfaccia javax.jms.M
utilizzare un oggetto RMI, come abbiamo fatto qui, dob- essageListener e nel costruttore si collega alla coda JMS
biamo caricarlo dal registro RMI e poi richiamare i suoi che già abbiamo visto. In questo caso, però, la coda viene
metodi. È necessario che il client conosca l’interfaccia di utilizzata soltanto per ricevere i nuovi messaggi che ven-
questo oggetto, per poter invocare i metodi che esso offre. gono inseriti, quindi il nostro oggetto si comporterà come
Nel Listato 2 si può invece osservare l’implementazione consumatore, rispetto all’oggetto HelloRMIImpl che è il
dell’interfaccia HelloRMI. In questo caso, nel metodo sen- produttore. Come abbiamo visto precedentemente, que-
dHello(), si può vedere come abbiamo realizzato l’ulteriore sto oggetto viene istanziato nel metodo init() della Ser-
salto per il nostro messaggio. Per fare ciò ci siamo connessi vlet, quindi da quel momento in poi è in listening sulla
ad una coda JMS messa a disposizione dall’Application coda it.javajournal.queue. Quando viene inserito l’oggetto
Server BEA WebLogic 8.1 e abbiamo inserito il nostro mes- TextMessage nella coda, viene richiamato il metodo onMes-
saggio. In questo esempio è stata utilizzata una Queue, e sage(), che provvede ad inserire il nostro messaggio all’in-
grazie al ConnectionFactory standard di BEA abbiamo inseri- terno di un database utilizzando JDBC. In questo caso
to un TextMessage creato con il messaggio che viene passato viene utilizzato il DataSource /weblogic/jdbc/jts/HelloDS che
come parametro al metodo sendHello(). Nella Figura 3 si è stato precedentemente configurato nel nostro Applica-
osserva la configurazione della coda JMS sulla console di tion Server. Un DataSource non è altro che un’interfaccia
amministrazione di BEA. definita nelle API JDBC che permette di ottenere una
connessione verso un database. La comodità di richia-
mare un DataSource definito esternamente è relativa
JMS agli aspetti di configurazione. Praticamente, se dobbiamo
utilizzare un database diverso, un utente diverso, o un
Siamo arrivati quindi all’implementazione del listener driver JDBC diverso, non dovremo effettuare questi cam-
JMS. Anche in questo caso, come nella Servlet, dobbiamo biamenti nel codice ma direttamente nel pannello di am-
distinguere due diversi momenti, quello dell’inizializza- ministrazione del nostro Application Server. In Figura 4
zione e quello del metodo onMessage(), che viene richia- potete vedere la configurazione che viene utilizzata per il
mato ogni volta che è presente un messaggio nella coda. DataSource che abbiamo utilizzato. Qui di seguito viene
Nel Listato 3 è riportata l’implementazione della classe riportato il semplice script SQL che abbiamo utilizzato
HelloJMSReceiver, che si occupa appunto di gestire la coda per creare la tabella sul database.

n.3 - marzo/aprile 2007 43


educational JAVA Journal

FIGURA 3 Configurazione JMS su BEA WebLogic 8.1

CREATE TABLE HELLO_MESSAGE (MESSAGGIO VARCHAR2(765)); due diverse tecnologie Java, JSP e JSTL. Praticamente,
COMMIT; all’interno di una pagina JSP avremo modo di recupe-
rare le informazioni sul database grazie alle tag library
standard. Qui di seguito potete vedere il codice che rea-
lizza la funzione richiesta:

<%@ taglib uri=”http://java.sun.com/jstl/sql” prefix=”sql” %>

Esporre un oggetto
<%@ taglib uri=”http://java.sun.com/jstl/core” prefix=”c” %>

<sql:setDataSource
RMI, disponibile per var=”ds”
driver=”oracle.jdbc.driver.OracleDriver”
client remoti url=”jdbc:oracle:thin:@127.0.0.1:1521:HELLOWORLD”
user=”system”
password=”system”
/>

<sql:query var=”messaggi” datasource=”${ds}”>


SELECT * FROM hello_message
</sql:query>
JSP e JSTL

A questo punto il messaggio, che è partito dal nostro <c:forEach var=”row” items=”${messaggi.rows}”>
cellulare, è finito dentro il database. Ora dobbiamo <c:out value=”${row.messaggio}” />
occuparci di realizzare una pagina che verrà chiama- </c:forEach>
ta di continuo da un classico programma JavaSE, per
fornire il messaggio che è stato inserito nella tabella In questa pagina JSP vengono utilizzate due diverse tag li-
HELLO_MESSAGE del database. Per fare ciò utilizzeremo brary, quella relativa al database (sql) e quella base (core).

44 n.3 - marzo/aprile 2007


JAVA Journal educational

FIGURA 5 Console dove viene mostrato il risultato della nostra applicazione

All’inizio vengono dichiarate le tag library con i relativi


prefissi che verranno utilizzati nel codice. Successivamen-
te viene definito un DataSource grazie al quale possiamo public static void main(String[] args) throws Exception{
collegarci al database. Viene quindi fatta una Select sulla Timer timer = new Timer();
tabella utilizzando il tag sql:query. Il risultato di questa JavaHelloWorldDesktop task = new
query viene memorizzato nella variabile messaggi. Infine, JavaHelloWorldDesktop();
grazie alla tag library core, viene scritto tutto quello che è timer.schedule( task, 5000, 5000 );
presente nella riga MESSAGGIO della tabella HELLO_MES- }
SAGE. Chiaramente, fino a quando non sarà partito il
messaggio dal programma JavaME, questa pagina non Non resta che implementare il metodo run() della classe
restituirà niente. Vediamo ora la parte finale del nostro JavaHelloWorldDesktop, presentato nel Listato 4. Utiliz-
programma. zando il package standard java.net viene effettuata una
connessione verso la pagina JSP. Ogni volta viene letta la
pagina e viene controllato se è presente o meno del testo.
Nel momento in cui verrà restituito il messaggio, l’applica-
zione desktop lo visualizzerà a schermo e successivamente
terminerà la sua esecuzione.

Utilizziamo JSP e Conclusioni


JSTL per fornire le In Figura 5 si vede come termina il viaggio del mes-
saggio partito dal cellulare. In questo articolo abbiamo
informazioni utilizzato più tecnologie Java, concentrando il nostro
interesse sul modo in cui collegarle. Chiaramente,
ognuna delle tecnologie appena viste meritano un ap-
profondimento a sé. Ciò nonostante, dopo tanto codice
e alcune spiegazioni, possiamo goderci un semplice e
simpatico “Hello World”. Proprio come quando si inizia
a programmare.

Programma Desktop

Il programma che alla fine visualizzerà il messaggio partito


dal cellulare deve effettuare il polling della pagina JSP che
abbiamo appena visto. Per fare ciò estenderemo la classe Note Biografiche
TimerTask e utilizzeremo un vero e proprio timer che ogni 5 Federico Paparoni si occupa prevalentemente di sviluppo sulle
secondi controlla la pagina JSP. Qui di seguito viene ripor- piattaforme JavaME e JavaEE. Gestisce il portale JavaStaff.com
tato il metodo main() dell’applicazione desktop: per la pubblicazione di notizie e articoli sul mondo Java.

n.3 - marzo/aprile 2007 45


JAVA Journal focus

n.1 - novembre/dicembre 2006 35


JAVA Journal focus

Introduzione a
Struts
Struts è un framework completo e diffuso e offre le basi per sviluppare in modo organico le
applicazioni web

>> di Andrea Colleoni (andrea.colleoni@javajournal.it)

Apache Tomcat ed ora personaggio di spicco nella


progettazione di JavaServer Faces dello strato web
delle specifiche J2EE.
Applicazioni Web e Framework: MVC Oggi il popolare framework è diviso in due parti:

Le applicazioni web, funzionano tutte seguendo le • Struts Shale Framework;


stesse regole di base e quindi si assomigliano molto • Struts Action Framewok.
fra loro. Pertanto, è nata la necessità per gli sviluppa-
tori di queste applicazioni di dotarsi di infrastrutture Noi ci occuperemo di quest’ultimo che è l’evoluzione
che costituiscano l’impalcatura generale dell’applica- del framework originario.
zione, le fondamenta del progetto: i framework. Struts non è un’IDE, non ha un front-end grafico e
Parallelamente, gli ingegneri del software hanno in- non costruisce automaticamente applicazioni web. È
dividuato che, in linea generale, alcuni problemi che semplicemente una libreria di oggetti già costruiti
si presentano nell’informatica sono ricorrenti e ben che svolgono alcune funzioni di base essenziali per il
circoscritti; tipologie di problemi ricorrenti hanno buon funzionamento di applicazioni web MVC.
tipologie di soluzione altrettanto ricorrenti: i design Struts non è l’unico framework e non è necessaria-
pattern. mente il più valido, ma è oggi uno dei più utilizzati
MVC (Model View Controller) è un pattern di pro- e diffusi. Ha molte estensioni tra cui alcune discreta-
getto che si applica alle applicazioni multi tier, come mente diffuse: Tiles, di cui non parleremo, è una di
quelle web, e consiste nella separazione netta tra: queste e fornisce un comodo strumento per costruire
la view.
• modello dei dati (il model);
• controllo del flusso dell’applicazione (il control-
ler);
• presentazione dei risultati all’utente (la view).

Struts è un framework che aiuta a perseguire la


separazione indicata dal pattern MVC e dalla sua
evoluzione Model 2, fornendo un controller già fun-
zionante e una base su cui costruire la view.
MVC significa Model-
Struts: quando, dove, come e perché; orientarsi View-Controller ed è un
nel sito
Struts è un progetto sviluppato negli anni dal 2000 al
2001 ed è ospitato nel grande contenitore di progetti pattern molto usato
che è l’Apache Software Foundation. È reperibile al-
l’indirizzo http://struts.apache.org/.
L’apporto principale al suo sviluppo è venuto da
Craig McClanahan già principale fautore del progetto

n.3 - marzo/aprile 2007 47


focus JAVA Journal

Essendo le specifiche Servlet e JSP uno standard,


qualunque servlet container è adatto, ma in que-
st’articolo ci riferiremo sempre al server Apache
Tomcat versione 5.x, reperibile all’indirizzo http:
//tomcat.apache.org/ e di cui sono disponibili gli
installer per Windows o gli archivi compressi,
contenenti i file per l’installazione su tutti i siste-
mi operativi.
Nei nostri esempi il server è installato sul compu-
ter locale (localhost) e sulla porta http di default
(80) per cui gli indirizzi saranno nella forma:

http://localhost/struts-examples/welcome.do.

L’installazione delle webapp fornite con Struts


può avvenire copiando i file .WAR nella directory
webapps del servlet container, eseguendone un
upload dal pannello di amministrazione del
FIGURA 1 la mailreader demo application servlet container oppure estraendone i file con
un programma per la gestione di file compressi
tipo WinZip in una sottodirectory di webapps del
servlet container.
Per gli scopi di quest’articolo è necessario installare le se-
Download e utilizzo guenti applicazioni:

All’indirizzo http://struts.apache.org/downloads.html • struts-documentation.war


sono disponibili per il download sia le release con tutte le • struts-mailreader.war
librerie compilate e pronte per l’uso (i cosidetti “binary”) • struts-blank.war
sia i programmi sorgenti.
Nell’archivio struts-x.y.z-bin.zip (oppure tar.gz) contenente le
librerie compilate, troviamo le seguenti cartelle:
Uno sguardo alle applicazioni di esempio
• /lib: contiene tutti i file JAR necessari a far funzionare le
varie parti del framework, più tutte le DTD e le definizio- Struts viene fornito con alcune applicazioni di esempio,
ni delle tag library utilizzabili; tra cui struts-mailreader. Esplorando il contenuto all’in-
• /contrib: contiene un’estensione delle tag library di Stru- dirizzo
ts; non ci occuperemo di questa parte
• /webapps: contiene alcune applicazioni web di esempio http://localhost/struts-mailreader/Welcome.do
che utilizzano Struts, più un’applicazione web utiliz-
zabile come base di partenza per costruire applicazioni si accede ad una semplice applicazione di registrazione di
basate su Struts e la documentazione su Struts e Tiles informazioni. Tramite un form è possibile registrare un
utente, per il quale possono poi essere definiti alcuni ac-
Per far funzionare le applicazioni di esempio, per consul- count di accesso a server di posta. Una volta registrato, un
tare la documentazione e per provare gli esempi di questo utente, può rieseguire l’accesso e visualizzare l’elenco degli
articolo avremo bisogno di un servlet container in cui in- account definiti. I dati vengono conservati in un database
stallare le applicazioni. XML nel file WEB-INF/database.xml.

FIGURA 2 la struts console per editare la configurazione

48 n.3 - marzo/aprile 2007


JAVA Journal focus

<servlet-name>action</servlet-name>
// logon.jsp
<url-pattern>*.do</url-pattern>
</servlet-mapping>
...

<html:form action=”/SubmitLogon” focus=”username”


Qualunque URL che termini con .do, invoca l’Ac-
onsubmit=”return validateLogonForm(this);”>
tionServlet; quindi, a dispetto di quanto possa
...
sembrare a prima vista, non ci sono file “.do”
<html:text property=”username” size=”16” maxlength=”18”/>
nella webapp.
...
Nella sezione delle Tag Libraries, vengono cari-
<html:password property=”password” size=”16” maxlength=”18”
cate le Tag Libraries di Struts che sono presenti
redisplay=”false”/>
nella cartella WEB-INF.
...
Vediamo il contenuto di una semplice pagina
<html:submit property=”Submit” value=”Submit”/>
JSP: /index.jsp
...
<html:reset/>
<%@ taglib uri=”/tags/struts-logic”
...
prefix=”logic” %>
</html:form>
<logic:redirect action=”/Welcome”/>

...
Questo frammento di codice consente di regi-
strare l’uso della Tag library struts-logic all’inter-
LISTATO 1 La JSP per la Logincon struts no della pagina JSP e quindi di utilizzare il tag
redirect di tale libreria per eseguire un’azione di
redirect. In particolare il browser viene rediretto
Dando un’occhiata più da vicino, cerchiamo di capire come verso una Action di nome Welcome, che è definita nel file
funziona e quale plus dà Struts a questa applicazione. In di configurazione di Struts.
primo luogo osserviamo il descrittore WEB-INF/web.xml: Nella sezione action-mappings del file WEB-INF/struts-
config.xml, viene definita tra le altre l’azione Welcome:
// web.xml
… // struts-config.xml
<servlet> …
<servlet-name>action</servlet-name> <action path=”/Welcome”
<servlet-class> type=”org.apache.struts.webapp.example.Wel
org.apache.struts.action.ActionServlet comeAction”>
</servlet-class> <forward name=”failure” path=”/Error.jsp” />
<init-param> <forward name=”success” path=”/welcome.jsp” />
<param-name>config</param-name> </action>
<param-value>
/WEB-INF/struts-config.xml,
/WEB-INF/struts-config- // LogonAction.java
registration.xml
</param-value> ...
</init-param>
<load-on-startup>1</load-on-startup> public ActionForward execute(...) throws Exception {
</servlet> ...
… String username = (String) PropertyUtils.getSimplePropert
y(form,
Nella sezione relativa alla definizione dei USERNAME);
servlet, viene definito il controller del nostro String password = (String) PropertyUtils.getSimplePropert
framework MVC: l’ActionServlet. L’Action- y(form,
Servlet viene caricato all’avvio e gli vengono PASSWORD);
passati come parametri due file di configu- ...
razione scritti in XML che il servlet caricherà return (mapping.getInputForward());
all’avvio dell’applicazione e di cui vedremo tra ...
poco il contenuto. return (findSuccess(mapping));
Per essere invocato dal servlet container,
l’ActionServlet, deve essere associato ad un }
pattern URL:
...
// web.xml

<servlet-mapping>
LISTATO 2 La Action (java) per la Login con struts

n.3 - marzo/aprile 2007 49


focus JAVA Journal

ActionForm
form,

HttpServletRequest
request,

HttpServletResponse
response)
throws
Exception {

...
if
(messages.size()>0) {
...
return
findFailure(mapping);
}
return
findSuccess(mapping);
}
FIGURA 3 editiamo una azione }


Nel codice, a seconda del successo o meno di alcune
Questo frammento della configurazione, noto come istruzioni che non è nostro scopo approfondire, possiamo
ActionMapping, fa sì che quando viene richiesta l’URL decidere di “uscire con successo” o “uscire con insuccesso”
/Welcome.do (è case sensitive, quindi con la
W maiuscola), venga creato un oggetto di // La classe TextBean è molto semplice:
classe WelcomeAction, che è istanziato dal fra- // ha una proprietà di nome text di tipo String
mework, ma è definito dal programmatore. // accessibile sia in lettura che in scrittura.
Il frammento contiene anche la definizione
di due forward di nome failure e success. A TextBean.java
questi sono associate due pagine JSP, rispet- public class TextBean {
tivamente /Error.jsp e /welcome.jsp. Vediamo private String text;
cosa significano queste impostazioni e come public String getText() {
funziona un’azione Struts.
return this.text;
Aprendo il file WEB-INF/src/org/apache/struts/ }
webapp/example/WelcomeAction.java, a cui si ri- public void setText(String text) {
ferisce l’action mapping visto sopra, notiamo
che l’azione estende una classe fornita nel- this.text = text;
l’esempio: BaseAction che a sua volta estende }
la classe del framework Action introducendo }
rispetto a quest’ultima solo alcuni semplici
metodi di utilità.
Una volta individuata la classe corrispondente // TextManager ha solo un metodo
all’azione, il framework la istanzia e ne invoca // che altera il contenuto della
il metodo execute() al quale vengono passati // proprietà text del bean TextBean
tutti gli oggetti per operare con il contesto
web e due oggetti Struts: l’ActionMapping TextManager.java
che rappresenta il contenuto del file di con- public class TextManager {
figurazione e l’ActionForm. Il metodo quindi
termina restituendo al framework che l’ha public TextManager() {
invocato, un oggetto di tipo ActionForward. }

// WelcomeAction.java public void modifica (TextBean tb) {


… tb.setText(“***” + tb.getText() + “***”);
public final class WelcomeAction extends }
BaseAction { }
public ActionForward execute(
ActionMapping mapping,
LISTATO 3 un semplice JavaBean

50 n.3 - marzo/aprile 2007


JAVA Journal focus

I metodi findSuccess() e findFailure() sono // text.jsp


definiti in BaseAction e facilitano il rintrac-
ciamento dei tipici forward success e failure. <%@ taglib uri=”/tags/struts-html” prefix=”html” %>
Nei forward definiti nell’action mapping, vie-
ne definito cosa fare in caso di successo e cosa <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”
in caso di insuccesso. “http://www.w3.org/TR/html4/loose.dtd”>
In caso di successo, nel nostro esempio, viene
caricata nel browser la “view” /welcome.jsp che <html>
è la pagina che si vede navigando l’URL http:/ <head>
/localhost/struts-mailreader/Welcome.do, che <meta http-equiv=”Content-Type” content=”text/html;
chiude gli elementi del paradigma MVC. charset=UTF-8”>
<title>Form</title>
In definitiva uno dei compiti del controller è </head>
governare il flusso dell’applicazione web at- <body>
traverso file di configurazione scritti in XML. <html:form action=”/SubmitAction”>
Il framework offre anche un altro strumen- Testo: <html:text property=”textproperty” /><br />
to configurabile molto utile: l’ActionForm. <html:submit />
Nel file di configurazione, notiamo che c’è </html:form>
un’azione /Logon.do che fa semplicemente un </body>
forward alla pagina /logon.jsp. </html>

<action path=”/Logon”
LISTATO 4 la form che visualizza il bean
forward=”/logon.jsp”/>

La pagina /logon.jsp, contiene un form costruito con i tag La classe LogonAction conterrà il codice per eseguire l’au-
della libreria HTML di Struts (Listato 1). tenticazione utilizzando username e password forniti dal
form (Listato 2).
Anche nel file di configurazione di Struts esiste una rap-
presentazione di questo form; si trova nella sezione form- Vale anche la pena di osservare che il metodo execute() è
beans: in grado di ritornare alla pagina di logon in caso di errori,
con il metodo mapping.getInputForward() che restitui-
// struts-config.xml sce il forward definito nell’attributo input dell’action-
… mapping.
<form-bean name=”LogonForm”
type=”org.apache.struts.validator.DynaValidatorForm”>
<form-property name=”username”
Uno sguardo alla “blank application”
type=”java.lang.String”/>
<form-property name=”password” La “blank-application” è contenuta nell’archivio struts-
type=”java.lang.String”/> blank.war e contiene lo “scheletro” di un’applicazione web
</form-bean> che funziona con il controller Struts. Ha un web.xml che
… carica l’ActionServlet con la configurazione definita nel file
struts-config.xml, che inizialmente contiene alcuni esempi
Il contenuto del form può essere quindi gestito dal ben commentati.
framework (in questo caso viene addirittura valicato Per iniziare a costruire applicazione web con Struts la
automaticamente dal framework attraverso l’uso del Dy- blank-application fornisce quindi una buona base di par-
naValidatorForm) e rappresentato al suo interno come tenza.
un JavaBean. L’azione /SubmitLogon a cui il form invia le Per interagire con il file di configurazione di Struts, può
informazioni è così definita: essere comodo inizialmente utilizzare uno strumento
di supporto grafico che aiuti a ricordare la struttu-
// struts-config.xml ra del file e il suo utilizzo. Un buono strumento in tal
… senso è la Struts console reperibile all’indirizzo http:
<action path=”/SubmitLogon” //www.jamesholmes.com/struts/console/ di cui in questo
type=”org.apache.struts.webapp.example.Lo esempio è stata usata la versione 4.8.
gonAction” Per iniziare con una nuova applicazione, quindi
name=”LogonForm” estrarremo il file struts-blank.war in qualche directory
scope=”request” nella quale verranno costruiti tutti i percorsi e i file di
input=”logon”> default, quindi usando la console struts e un kit di svi-
... luppo per Java procederemo con lo sviluppo di azioni
</action> e pagine JSP.

n.3 - marzo/aprile 2007 51


focus JAVA Journal

// SubmitAction.java

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionForm;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.PropertyUtils;

public class SubmitAction extends Action {

public ActionForward execute(


ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) throws Exception {

ActionForward retValue;
TextBean tb = new TextBean();
TextManager tm = new TextManager();
tb.setText((String) PropertyUtils.getSimpleProperty(form, “textproperty”));
tm.modifica(tb);
request.setAttribute(“risultato”, tb);
return mapping.findForward(“success”); }
}

LISTATO 5 una action per processare il bean

action l’azione /SubmitAction che andremo a definire suc-


Struts funziona su un cessivamente in struts-config.xml (Listato 4).

Usiamo la struts console per costruire il form e mappare


application server che l’azione. Dal menù file apriamo il file struts-config.xml che
abbiamo estratto in c:\esempi\struts\WEB-INF ed eseguiamo
i seguenti passi:
supporta Servlet e JSP
• Aggiungiamo un form bean di nome textform e di tipo
DynaActionForm ed a questo aggiungiamo una proprie-
tà di nome textproperty di tipo String (Figura 2)
Costruzione di un semplice esempio
• Ora aggiungiamo un’action-mapping con URL /
Proviamo ora a costruire, partendo dalla blank.application, SubmitAction che usi il form bean che abbiamo appena
un’applicazione web che svolga i seguenti compiti: creato; il tipo di mapping deve essere SubmitAction che
è il nome della classe che andremo a creare fra poco per
• Da una pagina /text.jsp venga offerta la possibilità di inse- gestire l’azione (Figura 3)
rire del testo
• All’invio del form tale testo venga trattato da classi di • Aggiungiamo nella configurazione del mapping anche
backend e restituito (Figura 4) un forward che chiameremo success che punti al path
/success.jsp:
Prima di tutto estraiamo con il programma di decompres- • Possiamo salvare lo struts-config.xml, chiudere la struts
sione il file struts-blank.war in una cartella, ad esempio c: console e prosegure con l’editor Java
\esempi\struts. Poi con un editor Java creiamo secondo • Ora dobbiamo costruire la nostra classe SubmitAction
la struttura delle applicazioni web, le classi che rappre- che preso il valore inserito nel form lo manipola con le
sentino il nostro model; costruiamo un JavaBean che classi del model e lo restituisce alla pagina /success.jsp:
rappresenti la nostra informazione ed una classe adatta a (Listato 5). Per rendere il risultato disponibile alla pagi-
trattarlo (Listato 3). na view, una tecnica utilizzata è quella di valorizzare un
Creiamo quindi un semplice form usando la libreria HTML attributo dell’oggetto request, il quale poi verrà letto con
di Struts al posto dei normali tag HTML; il form avrà come la libreria di tag di Struts bean.

52 n.3 - marzo/aprile 2007


JAVA Journal focus

FIGURA 4

// Success.jsp

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

<html>
<head>
<meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8”>
<title>JSP Page</title>
</head>
<body>
Il testo contenuto nel JavaBean processato è <bean:write name=”risultato” property=”text” />
</body>
</html>

LISTATO 6 visualizzare il risultato

• Infine aggiungiamo la pagina success.jsp che deve pre- Struts in effetti è un framework completo e diffuso e offre
sentare all’utente il risultato del processo avvenuto nel anche basi per sviluppare organicamente altre parti delle ap-
backend (Listato 6). plicazioni web, come il supporto all’internazionalizzazione,
alla validazione che in quest’articolo abbiamo solo sfiorato.
Per installare ed eseguire l’esempio è necessario compilare L’avvento di altri validi framework di successo ed il tentativo di
il progetto e copiare tutti i file dell’applicazione web conte- standardizzare lo sviluppo di applicazioni MVC condizionano
nuti nella cartella c:\esempi\struts nel servlet container. lo sviluppo di Struts ed in effetti la divisione tra l’Action Fra-
Una volta copiati i file necessari navighiamo all’URL http: mework e Shale è conseguenza di questo fatto.
//localhost/struts-blank/text.jsp. A questo punto, basterà
Note Biografiche
inserire del testo nella casella di testo, inviare il form … e
avremo ottenuto il risultato atteso. 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-
Conclusioni nologie legate a J2EE, ma anche con Microsoft.NET. Si occupa
anche di formazione; insegna Informatica alla Facoltà di Eco-
Nell’esempio abbiamo toccato i punti essenziali dell’Action nomia dell’Università di Bergamo e in altri corsi più specifici
Framework che di fatto è l’elemento architetturale che con- organizzati da vari enti di formazione. Vive a Seriate in provin-
cia di Bergamo con mia moglie Elena e la sua piccolina, Greta,
sente di scrivere applicazioni web secondo il paradigma MVC. arrivata cinque mesi fa.

n.3 - marzo/aprile 2007 53


focus JAVA Journal

Programmazione
AOP con AspectJ
Dopo anni di programmazione strutturata, si è passati ad anni di programmazione ad oggetti.
Ora si inizia a parlare di POP (Post Object Programming), e delle tecnologie correlate. AOP (Aspect
Oriented Programming), è appunto una di queste tecnologie. Vediamo di cosa si tratta, con esempi
pratici e l’utilizzo di un compilatore gratuito come AspectJ.

>> di Matteo Baccan (matteo.baccan@javajournal.it)

Perché AOP

P
Lo scopo di AOP è quello di isolare un’esigenza oriz-
zontale, racchiuderla all’interno di una regola (as-
rogettare una libreria di funzioni o un pect), ed applicarla solamente nei punti in cui serve,
framework di classi, è sicuramente senza impattare minimamente la classe che ne trarrà
un’operazione lunga e laboriosa. vantaggio.
Occorre capire i problemi che si avran- Questo vuol dire che, le persone che sviluppano una
no, il modo col quale astrarli e genera- classe e quelle che la arricchiscono con un aspect,
lizzarli, ma soprattutto prevedere, nel possono tranquillamente far parte di due team di svi-
modo più completo possibile, le nuove esigenze che luppo diversi, dato che lavorano su due set di classi
si potrebbero avere, per evitare di trovarsi, durante lo differenti, che si fondono per creare un unico byteco-
sviluppo, in problemi architetturali. de, che sarà quello che andrà ad essere utilizzato in
Esistono però delle esigenze orizzontali ad un fra- fase di runtime.
mework, che dovrebbero far parte di tutte le classi, Sorgenti diversi, impatti minimi al cambio delle
ma, per evitare di sporcare tutto il codice, si tende a funzionalità delle classi, possibilità di aggiungere
non integrarle, ad integrarle parzialmente, o a dele- comportamenti senza modificare il framework che
garle al programma chiamante. deve essere arricchito, queste sono le caratteristiche
Esempi classici di queste esigenze sono la gestione principali di AOP.
degli errori, il debug degli oggetti, il controllo formale
dei parametri e così via.
Cosa vuol dire affrontare in modo generalizzato que- AspectJ
ste problematiche?
Sicuramente significa creare dei sorgenti ridondanti, Lo strumento di cui parleremo in questo articolo è
copiare dei frammenti di codice da un metodo all’al- AspectJ, un compilatore gratuito, che si appoggia a
tro, astrarre esigenze in interfacce ed obbligare le javac e permette di integrare, all’interno delle proprie
classi ad implementarle. Fino ad arrivare agli assurdi classi, degli aspect.
delle dipendenze circolari, schemi dai quali diventa Questo compilatore è facilmente scaricabile da: http:
complicato uscire. //www.eclipse.org/aspectj/, e si installa con la clas-
Quando poi l’esigenza orizzontale muta, ne risente sica invocazione da riga comando: java -jar aspectj-
l’intero framework, creando delle destabilizzazioni 1.5.0.jar.
nel codice: se il tutto non è stato progettato più che Una volta installato, viene creata una cartella su
bene, ci si può trovare di fronte alla riscrittura di disco, generalmente c:\aspectj1.5\, che conterrà sia il
varie classi, che non dipendono direttamente dalla compilatore che le librerie per poterlo utilizzare.
modifica della funzionalità orizzontale, ma semplice- Il passo successivo sarà quello di mettere in path la
mente sono impattate in quanto utilizzatrici dirette directory c:\aspectj1.5\bin e in classpath il jar di As-
della funzionalità ormai obsoleta. pectJ: c:\aspectj1.5\lib\aspectjrt.jar.

54 n.3 - marzo/aprile 2007


JAVA Journal focus

Chiaramente, la partenza di tutto è un framework


preventivamente costituito, sul quale vogliamo
aggiungere il controllo d’accesso.
Perché non modificare direttamente il fra-
mework? Le ragioni potrebbero essere molteplici,
come il non disporre dei sorgenti del framework,
oppure il dover applicare tali modifiche solo ad
un progetto che lo utilizza, ma non a tutte le
applicazioni che lo utilizzano, evitando quindi di
aggiungere codice inutile dove non serve.
Se vogliamo analizzare la problematica, dal pun-
to di vista dell’Object Orientation (OO), il primo
approccio che potrebbe venire in mente, in que-
sto caso, è quello di creare una classe di controllo
accessi, modificare il sorgente della classe che
deve aggiungere la funzionalità, inserirvi un me-
todo di controllo e modificare tutti i sottometodi
che devono essere controllati, con la chiamata a
FIGURA 1 Struttura delle classi senza AOP questo metodo.
Questo approccio obbliga, necessariamente, la
Fatte queste due operazioni basilari, siamo pronti per uti- modifica di gran parte del codice della classe,
lizzare AspectJ e creare le prime applicazioni AOP. Inizia- rendendo, di fatto, il controllo d’accesso una funzionalità
mo quindi ad introdurre alcuni concetti di base. obbligatoria, in ogni ambito in cui la classe è utilizzata.
In un’ottica di riutilizzo del framework, si traduce nel
aver introdotto qualcosa che servirà solamente in un certo
Concetti di base caso specifico, ma non nella totalità dei casi in cui verrà
utilizzato il framework stesso. Ne consegue una struttura
Alla base della programmazione AOP c’è il concetto di cros- similare a quella presente in Figura 1.
scutting concern (CC), traducibile in interesse trasversale.
Quando si parla di CC, si fa riferimento ad un requisito Vediamo invece cosa cambia, nel momento in cui decides-
che può essere pensato in modo autonomo, ed applicato in simo di creare un aspect.
più punti, all’interno del progetto che si sta sviluppando, Ciò che viene stravolto totalmente è il modo col quale
senza essere necessariamente legato alla funzionalità che applicare il controllo d’accesso. Non occorre più mo-
si intende sviluppare. dificare le classi o i framework che devono supportare
Il poter astrarre un requisito, per poi applicarlo in modo questo nuovo requisito, ma basta creare singolarmente
orizzontale, ci permette di racchiudere la problematica in il requisito, all’interno di un aspect, definire quando
quello che viene definito aspect. All’interno di un aspect, deve essere applicato e compilarlo insieme al codice del
sono poi presenti le regole che indicano dove applicarlo. framework. Questa modalità permette di aggiungere
Il vantaggio di un aspect è appunto il fatto di essere rac- del codice, ad applicazioni già scritte, senza bisogno di
chiuso all’interno di un proprio sorgente, dove non vi è di- modificarle. Le classi quindi, non devono ereditare da
pendenza diretta rispetto alle classi dove verrà applicato. un qualcosa, ma è quel qualcosa che si inserisce nelle
Per questo motivo, è possibile uno sviluppo parallelo di requi- classi. Ne risulta, quindi, una struttura simile a quella
siti. Sarà poi compito del compilatore, nel nostro caso AspectJ, mostrata nella Figura 2, dove non si parla più di ere-
fondere regole e classi, all’interno dello stesso framework. Pro- ditarietà della classe di controllo degli accessi, ma di
viamo ora ad approfondire questi concetti con degli esempi. utilizzo.

Log degli accessi

Ipotizziamo di dover controlla-


re tutti gli accessi ad una certa
classe. Le ragioni potrebbero
essere svariate: un controllo di
utilizzo, un test di performance
o l’applicazione di un controllo
di accesso.
L’idea è quella di creare un as-
pect, in grado di intercettare tutti
gli accessi ad un certo metodo di
una certa classe, visualizzandoli
a video.
FIGURA 2 Struttura delle classi con AOP

n.3 - marzo/aprile 2007 55


focus JAVA Journal

Classe Demo zializzazione di un oggetto;


public class Demo { • Advice execution: all’ese-
public static void main(String[] args){ cuzione di un Advice.
Demo d = new Demo();
d.go(); Con queste direttive, si
} riescono a coprire tutte le
casistiche di una normale
public Demo(){} struttura ad oggetti.
public String cVar = “”; Vediamo ora le caratteri-
public void go(){ stiche che possono avere i
metodo1( “PAR1” ); singoli costrutti, per meglio
System.out.println( “passo 100 a Metodo2 [“ +metodo2( 100 ) +”]” ); comprendere come e quando
} applicarli
public void metodo1( String cPar ){
System.out.println( “Metodo1 chiamato con parametro stringa [“ +cPar +”]”);
} Applicazione di un Join Point
public String metodo2( int n ){
System.out.println( “Metodo2 chiamato con parametro numerico [“ +n +”]”); Come abbiamo spiegato
return “valore di ritorno*2 (“ +(n*2) +”)”; nel paragrafo precedente,
} un Join Point, può essere
} applicato sia in fase di
esecuzione, sia in fase di ri-
chiamo di un certo metodo.
LISTATO 1 La domanda più spontanea
che può venire in mente è:
perché questa differenza?
Elementi fondamentali della programmazione AOP In effetti, aggiungere del codice in un solo punto, all’in-
terno di un metodo, o aggiungerlo in ogni sua esecuzione,
Chiarita la differenza di approccio rispetto alla program- non cambia il risultato che si vuole ottenere. Cambia però
mazione Object Oriented, vediamo di scendere maggior- a livello di risparmio di codice e cambia soprattutto se non
mente in dettaglio, rispetto a AOP, introducendo un set si può modificare direttamente il sorgente della classe che
minimale di costrutti, con i quali è possibile creare qual- intendiamo controllare.
siasi tipo di aspect e di conseguenza poter sfruttare appieno Partiamo da un caso reale: si vuole condizionare l’utilizzo
questo paradigma di programmazione. di un certo metodo di una certa classe. Ipotizziamo che,
I costrutti che occorre conoscere sono: tale metodo, sia all’interno di una classe di cui disponiamo
il sorgente.
• oin Point: è il punto di esecuzione di un programma: il In questo caso, il punto migliore per poter applicare l’aspect
richiamo di un metodo o l’assegnazione di una variabile è nel momento dell’esecuzione, quindi dentro il metodo
d’istanza; stesso. Se però il metodo non ci è stato dato in chiaro, per-
• Pointcut: è il meccanismo che permette di selezionare su ché contenuto in una classe di cui abbiamo solo la libreria
quali Join Point andrà ad agire un Advice; (.jar), l’unico modo con cui possiamo applicare l’aspect è al
• Advice: è il codice che deve essere eseguito nel Join Point momento del suo utilizzo.
selezionato dal Pointcut; Sicuramente questo secondo modo di utilizzare un aspect è
• Aspect: è l’insieme di Advice e Pointcut. più prolisso, ma è l’unico modo col quale possiamo appli-
carlo in questo contesto.
In base a queste descrizioni, se volessimo definire cos’è un
aspect potremmo dire: è una regola che indica il punto dove
deve essere eseguito del codice. Il concetto di base è molto
semplice, ma allo stesso modo molto potente. Vediamo ora
di capire quali sono i Join Point sui quali possiamo agire: Esistono delle
• Method execution/call: durante l’esecuzione o il richia-
mo di un metodo;
esigenze orizzontali
• Constructor execution/call: durante l’esecuzione o il ri-
chiamo di un costruttore; ad un framework, che
• Class initialization: all’atto dell’inizializzazione di una
classe; dovrebbero far parte di
• Field read/write: alla scrittura o lettura in una variabile
d’istanza; tutte le classi
• Exception handler: quando si verifica un’eccezione;
• Object initialization/pre-initialization: all’atto dell’ini-

56 n.3 - marzo/aprile 2007


JAVA Journal focus

Call / Execution

Proviamo quindi a creare un Aspect, partendo dalla classe


Demo presente nel Listato 1:
L’idea è quella di
La classe d’esempio dispone di due metodi. Il primo non
creare un aspect, in
restituisce alcun risultato, mentre il secondo, restituisce
un risultato String. Quello che dobbiamo creare ora è un
grado di intercettare
aspect, come illustrato di seguito:
tutti gli accessi ad un
Aspect
certo metodo di una
aspect Logging { certa classe
pointcut primo_metodo():
call( void Demo.metodo1(String));
pointcut primo_metodo2():
execution( String Demo.metodo2(int));
Esecuzione
void around(): primo_metodo() {
System.out.println(“Prima”); Prima
proceed(); Metodo1 chiamato con parametro stringa [PAR1]
System.out.println(“Dopo”); Dopo
} Prima2
String around(): primo_metodo2() { Metodo2 chiamato con parametro numerico [100]
System.out.println(„Prima2“); Dopo2
String cRet = proceed(); passo 100 a Metodo2 [valore di ritorno*2 (200)]
System.out.println(“Dopo2”);
return cRet; L’effetto è quello di avere, prima e dopo l’esecuzione dei
} due metodi, la visualizzazione di due messaggi. Chiara-
} mente, se al posto dei messaggi ci fosse stato il controllo
d’accesso, avremmo risolto in modo ottimale la problema-
Un aspect è sintatticamente molto simile ad una classe, di tica, senza impattare la classe Demo.
cui ricorda molto la struttura.
Le differenze sono minime, ma importanti.
Al posto del token class, per indicare un aspect, occorre scri- Staticinitialization
vere “aspect”.
Dopo la definizione del nome, possiamo passare a definire Altro punto interessante, nel quale applicare un aspect, è
i pointcut e soprattutto i punti in cui devono agire: se al ri- l’inizializzazione di un oggetto tramite un costrutto static.
chiamo, call, del metodo o se alla sua esecuzione, execution. L’inizializzazione statica viene applicata tutte le volte in
Una volta decisa la modalità, possiamo indicare quale cui, in una classe, si ha l’esigenza di creare un qualcosa
gruppo di metodi, o singolo metodo, deve essere impatta- di comune a più istanze della classe stessa. Un esempio
to. Nel nostro caso si è deciso di indicare i due metodi della potrebbe essere la lettura di un file di configurazione, o la
classe Demo. creazione dati statici.
Ultimo punto da affrontare, è quello di creare un advice, nel Tale inizializzazione avviene una sola volta sola, in tutto il
quale inserire il codice da eseguire. programma. Potrebbe però essere interessante modificarne
Anche l’advice ha una propria sintassi, data dal ritorno del il comportamento o semplicemente notificarne l’esecuzio-
metodo da arricchire, dalla modalità di utilizzo, nel nostro ne.
caso around, cioè “attorno” al metodo che stiamo modifi- Anche in questo caso c’è un apposito pointcut da definire.
cando, e da un proprio nome. Come si può notare nel prossimo listato, la cosa che cam-
Una volta definito, possiamo creare tutto il codice Java che bia è la direttiva staticinitialization da passare al pointcut.
desideriamo, ricordandoci di utilizzare il metodo proceed() Per quanto riguarda l’advice, la sintassi è la stessa del caso
per attivare il metodo che si stava modificando. precedente. La cosa che varia è la presenza di void come
Per compilare queste righe con AspectJ è sufficiente chia- valore di ritorno, dato che le inizializzazioni non hanno un
mare il compilatore ajc passando, tramite una @, il nome valore di ritorno.
del file contenente l’elenco dei sorgenti da compilare,
come in questo esempio: ajc @files.lst. A questo punto,
invocando l’esecuzione della classe Demo (java demo), Staticinitialization
otterremo l’ouput:
aspect Logging {
pointcut primo_metodo()
: staticinitialization( Demo );

n.3 - marzo/aprile 2007 57


focus JAVA Journal

void around()
This/Target
: primo_metodo() {
proceed(); aspect Logging {
} pointcut primo_metodo()
} : execution( * *.go() )
&& this(Demo2);
void around():
primo_metodo() {
proceed();
Set/Get
}
Così come possiamo controllare l’accesso ad un metodo, è
possibile controllare l’accesso ad una variabile d’istanza, pointcut primo_metodo2()
sia in lettura che in scrittura. Per fare questo è possibile : execution( * *.go() )
utilizzare un pointcut dove indicare quale variabile, di quale && target(Demo);
classe, andare a controllare. Per quanto riguarda l’advice, void around():
rimane tutto invariato, come nel caso del metodo: primo_metodo2() {
proceed();
}
}
Set/Get

aspect Logging {
pointcut primo_metodo()
: set( String Demo.cVal );
pointcut primo_metodo2()

Questa modalità
: get( String Demo.cVal );
void around()
: primo_metodo() {

}
proceed(); permette di aggiungere
String around()
: primo_metodo2() {
del codice, ad
String c;
c = proceed();
applicazioni già scritte,
return c;
} senza bisogno di
}
modificarle
This/Target

Un’altra modalità di attivazione, specificabile all’interno di


un pointcut è data dalla classe di attivazione. Args
Ipotizziamo di avere più classi che hanno un metodo co-
mune chiamato go. Invece di specificare N pointcut, uno per Altro filtraggio possibile sui pointcut è dato dai parametri
ogni metodo di ogni classe, possiamo indicarne uno solo, passati. È infatti possibile utilizzare delle wildcard e paral-
utilizzando la wildcard “*”. Un esempio potrebbe essere lelamente indicare che, i parametri gestiti dal metodo che
“pointcut pc(): execution( * *.go() )”: dato qualsiasi metodo si intende controllare, sono di un certo tipo. In seguito è
go, di qualsiasi classe, con qualsiasi valore di ritorno, gesti- presente un esempio di utilizzo di args() collegato a tutti i
sci il pointcut pc(). metodi che ricevono come argomento un oggetto String.
Chiaramente, tutto funziona correttamente, nel caso in
cui ci siamo poche classi. Quando invece si utilizzano fra-
mework molto grandi, potrebbe essere necessario limitare Args
la capacità di questo pointcut. Per questo sono stati intro-
dotte le estensioni this( classe ) e target( classe ). aspect Logging {
Tramite questi due costrutti è possibile limitare un pointcut pointcut primo_metodo()
all’interno di una certa classe (this) o solamente quando : execution( void *.*(*) )
viene chiamato in una certa classe (target), come esposto && args( String );
in seguito:
void around()
: primo_metodo() {
System.out.println(“Prima”);

58 n.3 - marzo/aprile 2007


JAVA Journal focus

proceed();
System.out.println(“Dopo”); di questo tipo di programmazione, ma solo i concetti
} base, che permettono di capire come iniziare a pro-
} grammare. Come si può notare, il concetto base di
AOP è molto semplice. Servono poche righe di codice
per arricchire in modo concreto, molte classi di nuove
Advice funzionalità.
Piuttosto, il problema di AOP è la sua giovane età. Il
Ora che abbiamo ben compreso come creare dei poin- supporto per questo tipo di programmazione non è an-
tcut, vediamo quali tipo di esecuzione è possibile far cora molto diffuso, anche se inizia a essere presente in
fare ad un advice. alcuni ambienti di sviluppo.
Oltre ad around, osservato negli esempi precedenti, è Inoltre, pensare in AOP, richiede un ulteriore passo in
possibile anche indicare before se vogliamo eseguire del avanti, rispetto alla programmazione Object Oriented,
codice prima del pointcut, o after, se lo vogliamo esegui- passo di cui non si sente ancora l’esigenza diffusa.
re dopo. Come tutte le cose, il tempo ci potrà dare ragione o
Da notare che un advice è di per se molto simile ad un potrà cancellare completamente questo approccio post-
metodo, in quanto, come un metodo: object oriented.

• Segue delle regole di accesso per essere eseguito


• Può generare un’eccezione
• Può fare riferimento all’aspect corrente tramite this

Al contrario di un metodo però:

• Non ha un nome
• Non può essere chiamato direttamente, è il sistema Un aspect è una regola
che lo esegue
• Ha accesso ad alcune variabili valorizzate all’interno che indica il punto dove
di this che possono servire a prendere informazioni
sui join point catturati: thisJoinPoint deve essere eseguito
Altro aspetto interessante degli advice è quello di poter
essere eseguiti dopo il ritorno di un valore da un meto-
del codice
do, oppure nel momento di un’eccezione nel codice.

Advice su eccezione

Ultimi, ma non meno importanti, sono gli Advice su


eccezione. Chiaramente, anche in questo caso, esiste
una sintassi ben precisa, che ricalca molto quella vista Bibliografia
per i metodi.
Si tratta di definire sempre il momento in cui inter- [1] http://www.eclipse.org/aspectj/, AspectJ
cettare l’eccezione (ex: after), indicare che si vogliono [2] http://www.eclipse.org, il progetto Eclipse
gestire le eccezioni: throwing e definire su quali metodi [3] http://www.eclipse.org/aspectj/downloads.php, la
si intende farlo, nel caso del listato seguente sono stati pagina di download di AspectJ
indicati tutti i metodi: “* *.*()”. [4] http://www.baccan.it/index.php?sezione=webbit2
004, dove poter scaricare i sorgenti d’esempio analizza-
ti in questo articolo.
Advice su eccezione

aspect Logging {
after() throwing: call(* *.*()) {
System.out.println(“ERRORE”);
}
}
Note Biografiche
Matteo Baccan è uno specialista di progettazione e svilup-
po C++, JAVA e AOP. È ideatore del portale JobCrawler.it e
Conclusioni speaker in importanti eventi Java (Javaday, JIP Day). Attual-
mente si occupa di analisi presso un importante operatore di
Questo articolo è un’introduzione alla programmazio- telefonia mobile. Può essere contattato tramite il suo sito http:
//www.baccan.it.
ne AOP. Non sono stati toccati i concetti più complessi

n.3 - marzo/aprile 2007 59


IDIOMATICA
FREESPEECH Login Topic

In questa rubrica analizzeremo i più comuni errori di codifica, di progettazione ed i tranelli in


cui è facile cadere. Programmatore avvisato, mezzo salvato!

Falsi Oggetti: oggetti inutili,


anemici, tristi. E pericolosi.
>> di Ugo Landini (ugo.landini@javajournal.it)

nostro codice ci sarà infatti un oggetto che, trami-


La massima di questo mese: te un’astrazione, dovrà essere capace di applicare
delle logiche che ancora non sono state scritte ed
“A worker may be the hammer’s master, but the implementate: in un certo senso, sarà a prova di
hammer still prevails. A tool knows exactly how it futuro. In un linguaggio fortemente tipato come
is meant to be handled, while the user of the tool can Java, senza interfacce e polimorfismo sarebbe
only have an approximate idea” impossibile scrivere codice estensibile. Ma, con-
M.Kundera tinuando nel ragionamento, il polimorfismo im-
plica ovviamente un comportamento da rendere
polimorfo, e non dei semplici metodi accessors (o
getter/setter che dir si voglia). Lungi da me affer-
I Falsi oggetti sono molto comuni se non si ap- mare che gli accessors siano sempre un errore di
plicano correttamente i principi di buon design design: hanno i loro utilizzi. Quel che è certo è
Object Oriented. I falsi oggetti sono spesso asso- invece che un oggetto che non ha un comporta-
ciati con il polimorfismo dei poveri, che ho tratta- mento, un oggetto che non fa nulla, è di solito un
to nel primo numero di questa rubrica, e qualche segno di programmazione strutturata.
volta ne sono addirittura dei generatori.
Ma ripassiamo un momento uno dei cardini della Per cercare nel codice questo problema, seguire i
programmazione Object Oriented: un oggetto è passi:
fatto di comportamento, o behaviour. Questo com-
portamento tipicamente si applicherà su dei dati, 1. L’Oggetto x della classe X non ha comporta-
che altrettanto tipicamente saranno contenuti mento, solo getters/setters.
nell’oggetto stesso. Da qui il vecchio adagio che 2. Una logica, un comportamento da qualche par-
un oggetto è composto da dati + comportamen- te ci sarà pure, oppure il software non avrebbe
to, adagio tanto noto quanto poco applicato nella senso
pratica. 3. Questo comportamento sarà sparso in altre
Se volessimo riassumere in una frase sola cos’è classi, che probabilmente avranno dei nomi si-
che caratterizza un buon design ad oggetti, po- mili a XHandler, XManager, ecc.
tremmo dire – magari semplificando un po’ - che 4. Nel caso peggiore, da qualche parte ci sarà qual-
un buon design è caratterizzato dal poter aggiun- cuno che fa un instanceof, ricadendo addirittu-
gere una feature ad un software semplicemente ra nel Polimorfismo dei poveri (vedi Idiomatica
aggiungendo un nuovo oggetto, senza toccare del numero 1)
tutto il resto. E possibilmente senza dover ricom-
pilare l’esistente. A parte i (pochi) casi in cui un oggetto anemico è
Dovrebbe quindi essere evidente che il polimor- giustificato, la soluzione è decisamente semplice.
fismo è essenziale per raggiungere questo scopo, Il comportamento, sparso qui e la, va spostato nel
addirittura imprescindibile. Da qualche parte nel codice delle classi in cui è più appropriato, tipica-

n.3 marzo/aprile 2007 61


IDIOMATICA
FREESPEECH Login Topic

mente quelle che hanno i dati di cui il compor-


tamento stesso ha bisogno. O, in alternativa, la
classe va fatta sparire del tutto. Dunque Esercizi:

5. Se non ci sono validi motivi per non farlo, • Andare a cercare i falsi oggetti nel vostro codi-
spostare il comportamento dalle classi Handler/ ce
Manager alla classe di dominio • Andare a cercare i falsi oggetti in un software
open source a piacere
• Elencare i casi in un oggetto anemico è giustifi-
cato dal contesto

Conclusioni:

I Falsi oggetti sono molto comuni se non si


applicano correttamente i principi di design.
Stranamente, sono anche molto comuni fra chi
pensa di applicare dei principi di design: tipica-
mente, succede quando si da troppa importanza
agli strati di Service, magari fuorviati da qualche
acronimo di moda di tre lettere

n.3 - marzo/aprile 2007 62

Você também pode gostar