Sei sulla pagina 1di 68

I N V E T R I N A J AVA J O U R N A L 1

Linux for Programmers Scrivi a Linux® Patch Manage-


and Users
di G. Glass e K. Ables
book@infomedia.it ment: Keeping Linux®
Systems Up To Date
specificando di M. Jang
nell’oggetto
Prentice Hall della e-mail:
656 pp, euro 59.80 Prentice Hall
ISBN 0131857487 IN VETRINA 288 pp, euro 39.95
Java Journal n. 1 ISBN 0132366754

OPPURE
inviaci il coupon
Linux - La Guida sottostante Internet Phone Services
(con DVD) Simplified (VoIP)
di J. Davies et al.
al numero di fax di J. Doherty e N.
copertina
non
0587/732232 Anderson

disponibile Potrai acquistare


Mc Graw hill i libri qui riportati con uno Cisco Press
860 pp, euro 51.00 176 pp, euro 21.20
ISBN 8838644543 SCONTO ISBN 1587201623
ECCEZIONALE

An Introduction to XML Extending and


and Web Technologies del 10% anche se Embedding PHP
di A.Moller e M.
Schwartzbach
acquisti solo un libro di S. Golemon

OPPURE
Addison Wesley
del 20% se acquisti Sams
568 pp, euro 60.70
ISBN 0321269667
3 libri 456 pp, euro 45.50
ISBN 067232704X

JAVA JOURNAL 1
www.infomedia.it EDITORIALE

JAVA Journal
Java Journal
BIMESTRALE - ANNO 1 - N.1

DIRETTORE RESPONSABILE

numero 1
MARIALETIZIA MARI
(MMARI@INFOMEDIA.IT)

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

EDITORIAL BOARD Mentre scrivo queste righe ho in mano il numero della rivista Computer Programming
UGO LANDINI, STEFANO SANNA, del 1996 con lo speciale su Java, in cui scrissi due articoli cercando di spiegare cosa
TO N Y M O B I L Y era Java e come si facevano le applet. Era una delle mie primissime esperienze di
autore tecnico, quindi rivivo la cosa con emozione e nostalgia.
COLLABORATORI Java era allora alla versione 1.0; ciò nonostante la sua inclusione nel nuovissimo
Netscape 2.0,(qualcuno si ricorda che era il web browser leader di mercato?), ave-
MATTEO CAMPANELLA va fatto scalpore, creato fermento ed eccitazione, e scatenato un effetto domino di
UGO LANDINI dichiarazioni di supporto della tecnologia. Si erano dichiarati “amici di Java” nomi
ANDREA NASATO come IBM, Oracle e perfino Microsoft.
STEFANO SANNA Sono passati più di dieci anni (non mi sembra vero, ma è così), e tanto è cambiato.
FA B I O S T A R O Per esempio, di applet, la tecnologia allora rivoluzionaria, quasi non si parla più (le
ANDREA ZITO applet sono rimaste una applicazione di Java tutto sommato di nicchia).
Java comunque ha superato i confini del Browser, si è installato stabilmente nei
Server, ed è diventato uno dei linguaggi di programmazione più usati al mondo. Pur
non essendo (ancora) un linguaggio strettamente Open Source (nel senso di licenza
OSI-compatibile), di fatto il suo modello di sviluppo si è sempre avvicinato molto a
quello dell’Open Source. Una enorme quantità di ambienti e strumenti di sviluppo
per Java sono Open Source. Recentemente Java è diventato il linguaggio più usato
nei progetti del repository di SourceForge, il più grande sito che fornisce risorse per
lo sviluppo open. Sul lavoro, vengo consultato come esperto di “Java in ambiente
GRUPPO EDITORIALE INFOMEDIA SRL Open Source”. Quindi, anche se qualche purista potrà storcere il naso, Java viene
V I A V A L D E R A P. 1 1 6 associato comunemente all’Open Source.
5 6 0 3 8 PO N S A C C O ( P I ) I T A L I A Ricordo che Java ha in gran parte sostituito il Pascal nelle università come linguaggio
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 didattico; questo per due motivi: il primo è che è pulito e chiaro come il Pascal, ma
E-MAIL INFO@INFOMEDIA.IT rispetto a quest’ultimo è anche Object Oriented; il secondo è che si tratta di un lin-
S I T O W E B W W W. I N F O M E D I A . I T guaggio effettivamente molto usato in pratica. La maggior parte dei programmatori
quindi, anche se lavora con altri linguaggi, generalmente ha qualche interesse verso
Java, se non altro per completezza professionale.
DIREZIONE Nel frattempo, l’altro grande figlio di Internet, Linux, il sistema operativo vessillo
N A T A L E FI N O (NFINO@INFOMEDIA.IT) dell’Open Source (e del Free Software, per chi è interessato alla differenza) ha an-
ch’esso guadagnato molto terreno. Notare che è anche diventato un fenomeno edi-
CONTATTI toriale qualche anno fa. In Italia sono comparse numerose riviste dedicate a Linux.
Mi aspettavo quindi da un momento all’altro una rivista dedicata a Java. Infatti la
TE C H N I C A L B O O K quantità di programmatori Java, o aspiranti tali, è di tutto rispetto.
(BOOK@INFOMEDIA.IT)
Infatti, nonostante l’uso di Internet per trovare informazioni, la rispettabilità, la pia-
cevolezza e la qualità di una buona rivista non sono mai venute meno rispetto alla
MARKETING & ADVERTISING ricerca sul Web. La storia insegna che un nuovo media non sostituisce mai un altro,
SEGRETERIA: 0587736460 semmai lo affianca.
MARKETING@INFOMEDIA.IT Purtroppo, per anni, in Italia non ho trovato niente. Abbiamo una quantità impres-
sionante di riviste dedicate ai telefonini, ma nessuna rivista dedicata a Java. Eppure
AMMINISTRAZIONE in altri paesi di riviste Java ce ne sono parecchie; conosco moltissimi programmatori
(AMMINISTRAZIONE@INFOMEDIA.IT)
Java regolarmente abbonati alle riviste estere.
SEGRETERIA Così, quando in una chat session con Tony Mobily, mi lamentavo di questa mancan-
(INFO@INFOMEDIA.IT) za, sono rimasto gelato dalla proposta: “perché non la fai tu”? A breve, mi ha messo
in contatto con Marialetizia Mari, direttore responsabile delle riviste del Gruppo
GRAFICA Editoriale Infomedia, che mi ha confermato l’interesse.
(GRAFICA@GRUPPOINFOMEDIA.IT)
Siccome non è corretto lamentarsi di una mancanza per poi tirarsi indietro quando
è il momento di rimediare, mi sono messo al lavoro. Dopo un rapido giro di email...
ho quasi riempito il primo numero! Ho trovato tanto entusiasmo e disponibilità. Non
UFFICIO ABBONAMENTI ci credevo! I commenti praticamente unanimi sono stati: “bella idea”, “ci vuole”,
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 “collaboro anche io”.
ABBONAMENTI@INFOMEDIA.IT Prima di completare il lavoro sono passati mesi, ma eccoci qui: la prima rivista in
W W W. I N F O M E D I A . I T italiano dedicata a Java è appena nata. Spero vi piaccia e sia utile per lavoro o per
studio. Confidiamo nel vostro sostegno concreto, diventando abbonati, ma anche
JAVA E TUTTI I MARCHI DERIVATI proponendo commenti, critiche e facendola conoscere ad amici e colleghi che, come
SONO MARCHI O MARCHI REGISTRATI
voi, cercavano una rivista italiana su Java. Fateci sapere cosa ne pensate scrivendo a
michele.sciabarra@javajournal.it.
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 Michele Sciabarrà
EDITORIALE INFOMEDIA È INDIPEN- Direttore Esecutivo
DENTE DA SUN MICROSYSTEMS, INC. Java Journal

n.1 - novembre/dicembre 2006 7


JAVA Journal numero 1

SOMMARIO Novembre/Dicembre 2006

Speciale JSF
Primi passi con JavaServer Faces
di Michele Sciabarrà 10
Le novità di JSF 1.2
di Andrea Nasato 17
Un Wizard per il Web con JSF e Shale
di Fabio Staro 23

Focus
JavaCard
di Matteo Campanella 30
Gcj: Gnu Compiler for Java
di Andrea Zito 36
Java ME sviluppare applicazioni per cellulari e PDA
di Stefano Sanna 42

Educational
Java 5, le buone nuove e le novità meno buone
di Ugo Landini 49
Fondamenti di Programmazione Java
Prima parte: uno sguardo d’insieme
di Michele Sciabarrà 55

Rubriche
Idiomatica
Codice orribile, antipattern e pratiche discutibili
di Ugo Landini 62

Community
Intervista a Daniela Ruggeri, presidente della
Java Italian Association
di Michele Sciabarrà 64

n.1 - novembre/dicembre 2006


speciale JavaServer Faces JAVA Journal

Primi passi con


JavaServer Faces
Le JavaServer Faces sono da molti considerate il tassello mancante per rendere lo sviluppo di appli-
cazioni Web più semplice. Nella realtà è uno strumento molto potente per realizzare un certo tipo
di applicazioni, ovvero quelle dotate di numerose form per il data-entry. Come tutti gli strumenti
di questo genere, sono abbastanza complesse e richiedono un po’ di tempo e impegno per essere pa-
droneggiate. Prima di entrare nei dettagli della tecnologia con il prossimo articolo, e descrivere il suo
prossimo futuro, mostriamo prima di tutto con un esempio pratico come funzionano.

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

L
e JavaServer Faces sono state proget- JSF sono in realtà delle pagine JSP che contengo-
tate per ridurre il codice da scrivere no dei tag provenienti dalla libreria Faces. Tutta-
quando una applicazione Web ha nu- via, una pagina in JSF deve essere chiamata con
merose form; quasi sempre si tratta di l’estensione.faces (non .jsp) o con il prefisso /faces/;
una interfaccia a dati memorizzati su su disco però vengono memorizzate con la clas-
un database relazionale. In una appli- sica estensione .jsp. Dove è l’inghippo? Semplice:
cazione Web in Java “tradizionale”, quando installiamo le JSF, dobbiamo configurare
ci sono delle JavaServer Pages o delle servlet che nell’applicazione Web una “servlet”, la faces servlet
producono esplicitamente tutto l’html necessario che interpreta le pagine JSF. Questa servlet prepara
per visualizzare le form. Per gestire le form il pro- l’ambiente perché una JSF possa essere eseguita. In
grammatore Web finora doveva fare da solo. Una effetti è un sistema un po’ strano, non ovvio; pur-
applicazione Web infatti richiede una serie di auto- troppo questo “trucco” è necessario perché si possa
matismi che con le sole JSP non possiede: è neces- mantenere la compatibilità con molti application
sario riempire le form con dei dati, mantenere uno server esistenti.
stato, raccogliere e decodificare i dati, spesso codi- Oltre alle pagine JSF avremo delle classi, che sono
ficarli o decodificarli, e infine salvarli in un data- necessarie per usare le JSF. A differenza delle JSP
base. Per quanto riguarda la gestione del database, infatti, le JSF prevedono che molte operazioni delle
questo è compito di librerie ORM (Object Relatio- JSF, vengano svolte in delle classi apposite, dette
nal Mapping), e non verrà considerato nel presen- “Backing Bean”.
te articolo.
Le JavaServer Faces hanno l’obiettivo principale di
aumentare l’automatismo per riempire le form con
i dati, recuperarli quando l’utente li inserisce, e in
generale gestire l’interazione con l’utente. Vedremo
Le
pagine JSF sono
come fare costruendo un esempio pratico passo pas-
so. Si tratterà di un esempio molto semplice, ridotto pagine JSP che conten-
all’osso, che visualizza un elenco dati e permette di
modificarlo. La memorizzazione dei dati verrà gesti- gono tag provenienti
ta con uno “stub”, una classe minimale (da esten-
dere eventualmente) perché altrimenti andremmo dalla libreria Faces
fuori dallo scopo dell’esempio.

Personaggi e Interpreti

Prima di entrare nei dettagli, elenchiamo i compo-


nenti che compongono una applicazione realizzata Da questi Backing Bean le pagine JSF leggono i dati,
con JavaServer Faces. In particolare tratteremo del- li scrivono dopo averli utilizzati, e causano l’esecu-
le JSF versione 1.1. zione di azioni a seguito di “eventi”, che avvengono
Innanzitutto avremo alcune pagine JSF. Le pagine quando l’utente fa delle operazioni sulle maschere

10 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

prodotte. Per collegare Backing Bean a pagine JSF, si


utilizza un file di configurazione, chiamato solitamente commons-logging.jar
faces-config.xml. commons-digester.jar
Questo file innanzitutto contiene la definizione di tutti i commons-beanutils.jar
backing bean. Un altro elemento importante delle JSF è commons-collections.jar
che la navigazione (il passaggio da una pagina all’altra) jstl.jar
viene definita “in astratto”. Ogni volta che serve una standard.jar
navigazione, un backing bean o una jsf non dice espli-
citamente dove vogliono andare, codificando l’url della Copiato tutto nella WEB-INF/lib occorre configurare, ag-
destinazione: invece viene data una risposta generica, giungendo nel web.xml quanto mostrato nel Listato 1.
codificata con una stringa. La navigazione effettiva viene
dichiarata nel faces-config.xml

Installazione di JSF

Prima di andare avanti, vediamo come installare la


versione RI 1.1 delle JSF (la Reference Implementation
fornita da Sun) nella vostra applicazione Web. Notare
che ne esistono altre come le MyFaces, ma la RI sembra
al momento essere la più usata. Si presume in questo ar-
ticolo che abbiate familiarità con le configurazioni delle
WebApp, e in particolare sappiate cosa è e a cosa serve la
directory WEB-INF/lib e il file web.xml. Questo esempio
fa riferimento all’installazione delle JSF versione 1.1 nel-
l’application server Tomcat, in particolare alla sua versio- FIGURA 1 I componenti della Agenda
ne 5.5. Se usate un diverso application server può essere

La configurazione installa una servlet, la Faces Servlet,


<context-param> che viene richiamata per interpretare le JSP che conten-
<param-name>javax.faces.CONFIG_FILES gono tag di tipo Faces. Ancora una volta ricordo il trucco:
</param-name> se avete un file che si chiama pagina.jsp (e dovete avere
<param-value>/WEB-INF/faces-config.xml una pagina di questo tipo), la dovete richiamare con il
</param-value> nome pagina.faces. Se la chiamate con l’estensione jsp,
</context-param> otterrete un errore, perché non vengono eseguite le ini-
<servlet> zializzazioni necessarie per le JSF.
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>
javax.faces.webapp.FacesServlet
</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
L’esempio mostrato
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name> è il prototipo di ogni
<url-pattern>*.faces</url-pattern>
</servlet-mapping> applicazione basata su
LISTATO 1 Le configurazioni nel web.xml delle JSF JSF
necessario variare le operazioni opportunamente.
Per installare JSF occorre scaricare il pacchetto versione
1.1 da java.sun.com/j2ee/javaserverfaces. In prima approssi- L’applicazione Agenda
mazione basta copiare due jar nella directory WEB-INF/lib,
ovvero la jsf-api.jar e jsf-impl.jar. Come è costume, il primo Come esempio scriviamo una applicazione dimostrati-
jar rappresenta la API come definita dalla specifica, mentre va, una semplice agenda che permette di visualizzare
il secondo ne è l’implementazione. Questi due JAR però un elenco di nomi, aggiungerli o toglierli, ed editare un
non sono sufficienti in quanto l’implementazione di Sun dettaglio. Pur nella sua assoluta semplicità questa mini-
usa una serie di librerie esterne, peraltro abbastanza note applicazione è il prototipo di qualunque applicazione
e usate: sono alcuni dei “commons” del progetto Apache. significativa per cui si usano le JSF. Il suo studio fornisce
Infine servono anche le le librerie della Java Standard un buon trampolino di lancio per avventurarsi in appli-
Template Library. Ecco l’elenco di quelle necessarie: cazioni più complesse. In Figura 1 ho schematizzato con

n.1 - novembre/dicembre 2006 11


speciale JavaServer Faces JAVA Journal

AgendaForm.jsp in risposta a una richiesta “form”, e vice-


<managed-bean> versa in risposta a una richiesta “list”.
<managed-bean-name>agenda
</managed-bean-name>
<managed-bean-class>agenda.Agenda
Backing</managed-bean-class>
<managed-bean-scope>session
</managed-bean-scope>
I componenti di una
</managed-bean>
applicazione JSF
<navigation-rule> vengono configurati nel
<from-view-id>/agenda/AgendaList.jsp
</from-view-id> file faces-config.xml
<navigation-case>
<from-outcome>form</from-outcome>
<to-view-id>/agenda/AgendaForm.jsp
</to-view-id>
</navigation-case> Il database
</navigation-rule>
Stiamo costruendo una applicazione che gestisce nei fatti
<navigation-rule> una tabella di dati. Per semplicità, non ci preoccuperemo
<from-view-id>/agenda/AgendaForm.jsp di leggere e scrivere effettivamente i dati sul database,
</from-view-id> ma ci limiteremo a mantenerli in memoria, utilizzando
<navigation-case> consuete strutture dati come liste e mappe. Comunque,
<from-outcome>list</from-outcome> sarà possibile salvare i dati effettivamente su database
<to-view-id>/agenda/AgendaList.jsp semplicemente implementando i metodi appositi di let-
</to-view-id> tura e scrittura, che nel nostro caso si limitano a tenere
</navigation-case> tutto in memoria.
</navigation-rule> Per mantenere un record, utilizziamo un javabean, ovvero
una classe Java i cui campi sono accessibili con getter e
setter; si tratta di Pojo (Plain Old Java Object) nell’acce-
zione corrente. Questo oggetto ha i campi nome, email e
LISTATO 2 La configurazione del faces-config.xml telefono, con relativi getter e setter. Per predisporre il file
nella scrittura sul database, abbiamo anche un campo id
di tipo Long, campo che viene generato automaticamen-
un diagramma, i principali componenti di questa applica- te (usando il noto metodo del timestamp per creare un
zione, e la sua navigazione. identificatore univoco).
Il diagramma non usa nessuna notazione particolare: Un database di bean viene mantenuto in memoria e ge-
semplicemente ho indicato con l’icona dei documenti, le stito tramite metodi statici della classe agenda. Sarebbe
pagine jsf, mentre con un rombo il backing bean. I dati stato forse opportuno separare i metodi statici dalla clas-
vengono letti e scritti in un “database”, che in realtà un se Agenda, ma per semplicità ho messo tutto nella stessa
database vero non è, ma solo una collezione di bean in classe. Per creare un nuovo bean useremo Agenda a = new
memoria. Il meccanismo comunque si estende in manie-
ra naturale verso la memorizzazione in un vero database,
utilizzando un qualsiasi sistema ORM (per esempio Hi-
bernate). In figura abbiamo anche evidenziato lo schema
di navigazione, che è elementare: dalla lista si passa alla
form e viceversa.
Come abbiamo detto, i componenti di una applicazio-
ne JSF vengono esplicitamente configurati nel faces-
config.xml. Di solito il file di configurazione si scrive alla
fine; siccome sappiamo già quali file avremo nella nostra
applicazione, lo scriviamo per primo e ci togliamo d’im-
piccio. Nel file di configurazione ci sono numerose pos-
sibilità, ma ai fini del nostro esempio ci interessano solo
due cose: definire i backing bean, e configurare la navi-
gazione. La configurazione è mostrata nel Listato 2. Il
Backing Bean è uno solo, di classe agenda.AgendaBacking,
che verrà richiamato con il nome agenda. La navigazio-
ne invece va dal file /agenda/AgendaList.jsp al file /agenda/ FIGURA 2 Visualizzazione della lista dei record

12 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

package agenda; // gestione del “database”


// in memoria
// import omissis private static List<Agenda> list =
new LinkedList<Agenda>();
public class Agenda { private static Map<Long, Agenda>
// trucco per generare facilmente map = new HashMap<Long, Agenda>();
// id univoci
static long counter= // ritorna una lista dei bean
System.currentTimeMillis(); public static List<Agenda>
getList(){ return list; }
// campi con getter e setter
Long id = new Long(counter++); // memorizza il bean
public Long getId() { return id; } public static void
public void setId(Long id) { this.id store(Agenda bean) {
= id; } if(map.get(bean.getId())==null)
String nome; list.add(bean);
public String getNome() map.put(bean.getId(), bean);
{ return nome; } }
public void setNome(String nome)
{this.nome = nome;} // recupera il bean
public static Agenda load(Long id) {
String email; return map.get(id);
public String getEmail() }
{ return email; }
public void setEmail(String email) // elimina il bean
{this.email = email; } public static void
remove(Agenda bean) {
String phone; map.remove(bean.getId());
public String getPhone() list.remove(bean);
{ return phone;} }
public void setPhone(String phone)
{this.phone= phone; } // inizializzazione (una tantum)
// del database
// costruttori static {
store(new Agenda(“Michele”,
public Agenda() { this(“”,””,””); } “msciab@ep”,“347”));
store(new Agenda(“Mirella”,
public Agenda(String nome, String “mirella@ep”, “328”));
email,String phone) { store(new Agenda(“Laura”,
super(); “laura@ep”,“736”));
this.email = email; store(new Agenda(“Massimo”,
this.nome = nome; “max@ep”,“922”));
this.phone = phone; }
} }

LISTATO 3 Il “database” dell’agenda

Agenda(“nome”, “email”, “telefono”). Per salvarlo useremo due maschere: una maschera principale che elenca tutti
Agenda.store(a), mentre per recuperarlo (assumendo di i record, e una seconda maschera di dettaglio, che per-
avere già l’id) basterà un Agenda.load(id). Infine, per eli- mette di modificare il singolo record. Entrambe fanno
minarlo possiamo utilizzare Agenda.delete(a). Il codice del riferimento a un unico backing bean, agenda. Iniziamo a
“database” segue in Listato 3. vedere il codice della lista, in Listato 4:
Nel Listato 4 possiamo vedere come si fa a ottenere un
La lista e la form elenco di record del database, come è visualizzato nella
Figura 2. Si può notare che JSF usa dei tag, con prefisso
La nostra applicazione è composta essenzialmente di f: oppure h:, descritti in dettaglio nell’articolo successivo.

n.1 - novembre/dicembre 2006 13


speciale JavaServer Faces JAVA Journal

(si veda l’articolo sulle novità delle


<%@ taglib uri=”http://java.sun.com/jsf/html” JSF 1.2 al riguardo).
prefix=”h”%>
<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%> Notiamo innanzitutto la h:datatable.
<f:view> Questo tag itera i contenuti di una
<h:form> lista. I valori da rappresentare ven-
<h:dataTable var=”data” border=”1” gono forniti dal backing bean, che
binding=”#{agenda.table}” value=”#{agenda.list}”> ne fornisce la lista. Il backing bean
<h:column> viene richiamato con l’espressione
<f:facet name=”header”> #{agenda.list}. Il file di configurazione
<h:outputText value=”Azione” /> faces-config lo definisce, e questo bean
</f:facet> viene creato e viene posto in sessione. A
<h:commandButton questo punto l’output da visualizzare
actionListener=”#{agenda.edit}” viene generato dal metodo getList()
value=”Modifica” action=”form”/> del backing bean. Notare che, come
</h:column> spesso succede, una “proprietà” del
<h:column> backing bean viene chiamata senza
<f:facet name=”header”> usare il prefisso get, ma nel codice
<h:outputText value=”Nome” /> occorre scrivere il metodo getList.
</f:facet> Viene prodotta così una lista di bean,
<h:outputText value=”#{data.nome}” /> che sono di classe Agenda. Ogni bean
</h:column> viene posto nella variabile data e vi-
<h:column> sualizzato.
<f:facet name=”header”> Un’altra caratteristica della datatable
<h:outputText value=”Email” /> è che il contenuto viene prodotto per
</f:facet> colonna, mentre ricordiamo che in
<h:outputText value=”#{data.email}” /> html una tabella viene definita per
</h:column> riga. Non c’è quindi una corrispon-
<h:column> denza diretta tra una datatable JSF e
<f:facet name=”header”> una table HTML.In ogni colonna viene
<h:outputText value=”Telefono” /> visualizzata la riga corrente usando le
</f:facet> outputText che usano #{data.nome},#{
<h:outputText value=”#{data.phone}” /> data.email},#{data.phone} per accedere
</h:column> alle proprietà del bean (che si aspetta
<h:column> di tipo Agenda).
<f:facet name=”header”> Una altra osservazione è il “binding”
<h:outputText value=”Azione” /> della datatable: le JSF costruiscono
</f:facet> per ogni tag JSF un oggetto; nel caso
<h:commandButton della datatable viene creato un og-
actionListener=”#{agenda.delete}” getto UIData; utilizzando il binding,
value=”Elimina” action=”list”/> questo oggetto viene memorizzato
</h:column> direttamente nel backing bean: in
</h:dataTable> questo modo si possono ispezionare
<h:commandButton e ottenere informazioni come per
actionListener=”#{agenda.create}” esempio la riga corrente. Questo uso
value=”Nuovo” action=”form”/> è comunque abbastanza avanzato, ma
</h:form> una volta compreso può essere molto
</f:view> potente. Vedremo come viene sfrutta-
to esaminando il dettaglio del backing
bean nel prossimo paragrafo.
Infine, i comandi. Notiamo che quan-
LISTATO 4 La lista dei record dell’agenda do si clicca un bottone viene invocato
un metodo del bean specificato con ac-
Questi tag definiscono l’interfaccia utente in maniera tionListener. Abbiamo #{agenda.create} per creare un nuo-
astratta. Questa è infatti una delle principali difficoltà vo bean, #{agenda.delete} per cancellarlo e #{agenda.edit}
nell’imparare le JSF: i tag delle JSF sono completamen- per la modifica. Attenzione che in questo caso si tratta
te diversi da quelli dell’HTML. Infatti una pagina JSF proprio dei metodi edit, create e delete, non di una proprietà
genera un output HTML utilizzando un render kit, ma (quindi un metodo con il prefisso get). Tuttavia i meto-
è possibile sostituirlo con un render kit di tipo diverso di specificati come actionListener hanno anche essi degli
per produrre output come WML (per il Wap) o XUL (per obblighi: devono essere di tipo void e prendere un para-
applicazioni GUI basate su Firefox) o usare tecniche Ajax metro di tipo ActionEvent. È assolutamente essenziale ren-

14 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

dersi conto che le JSF hanno un ciclo di vita sottostante,


e che quindi le varie proprietà ed eventi vengono usate in
momenti diversi. Le proprietà vengono lette prima della
visualizzazione della pagina. Le azioni vengono gestite
dopo che l’utente ha premuto un bottone.
Proseguiamo l’analisi dell’esempio vedendo il dettaglio
della form mostrata nel Listato 5, e il cui snapshot può
essere osservato in Figura 3.
Anche in questo caso vengono usati tag astratti: la form

Il ciclo di vita delle

JSF si basa su proprietà FIGURA 3

la lista degli elementi, ma una volta selezionato un ele-


e eventi mento permette di accedere alle singole proprietà. Esami-
nando il dettaglio del backing bean vedremo che abbiamo
creato dei metodi “proxy”: in pratica ogni volta che si chia-
ma il getNome del backing bean (di classe AgendaBacking),
questo chiamerà il getNome della classe Agenda. In questa
usa il panelGrid che permette di disporre i componenti pagina abbiamo non solo outputText ma anche e soprattut-
contenuti in una tabella, senza doversi preoccupare della to inputText, che permettono non solo di leggere ma anche
suddivisione in righe e colonne. Se dichiaro un panelgrid di scrivere. Quindi questa pagina visualizza innanzitutto il
con tre colonne, viene creata una tabella con tre colonne; record selezionato, chiamando i metodi getNome, eccetera.
la prima riga conterrà i primi tre elementi, la seconda riga Quando l’utente ha compilato il modulo e clicca su un bot-
conterrà il quarto, il quinto e il sesto, e così via. Semplice tone, il valore immesso viene riportato nel backing bean
e pratico. chiamando i metodi setNome, setEmail setPhone.
Il nostro backing bean è multifunzionale: non solo fornisce

Il backing bean
<%@ taglib uri=”http://java.sun.com/jsf/html” prefix=”h”%>
<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%> È venuto il momento di chiudere il cerchio, ri-
<f:view> portando il codice del backing bean mostrato nel
<h:form> Listato 6. Potrebbe sembrare strano che il codice
<h:panelGrid columns=”3”> sia così semplice, però è proprio così. Tutti i meto-
<h:outputLabel value=”Nome:” for=”nome” /> di sono di una sola riga, e molti metodi possono
<h:inputText id=”nome” value=”#{agenda.nome}” /> essere scritti in maniera automatica sfruttando
<h:message for=”nome” /> gli automatismi forniti dagli IDE: per esempio per
scrivere i getter/setter o i proxy.
<h:outputLabel value=”Email:” for=”email” /> Per capire come funziona il tutto, vediamo cosa
<h:inputText id=”email” value=”#{agenda.email}” /> succede nei dettagli, avendo il codice sott’occhio e
<h:message for=”email” /> tenendo presente quanto abbiamo visto nei para-
grafi precedenti.
<h:outputLabel value=”Phone:” for=”phone” /> Innanzitutto l’utente chiama la pagina
<h:inputText id=”phone” value=”#{agenda.phone}” /> AgendaList.jsp che abbiamo visto nel Listato 3.
<h:message for=”phone” /> Per visualizzare l’elenco dei metodi la JSF chiama
AgendaBacking.getList(). Il backing bean produce la
</h:panelGrid> lista dei bean prendendoli dal database, con il me-
<h:commandButton value=”Salva” todo statico Agenda.getList(). I vari bean vengono
actionListener=”#{agenda.save}” action=”list”/> posti nella variabile data e i dati correnti vengono
</h:form> visualizzati. I vari #{data.name} chiamano il me-
</f:view> todo getName della classe Agenda. La datatable ac-
cede direttamente ai bean che contengono i dati.
A questo punto un utente decide di modificare
LISTATO 5 Il dettaglio dell’agenda
un bean, e preme il bottone Modifica. La form vie-

n.1 - novembre/dicembre 2006 15


speciale JavaServer Faces JAVA Journal

package agenda; Dopo aver premuto il bottone di mo-


difica, viene eseguito il metodo invo-
// import omissis cato dall’actionListener, che imposta
il bean corrente a quello selezionato,
public class AgendaBacking { e poi si naviga alla form. Notare che
nel command button è specificato
// gestione lista “form” mentre nel faces-config.xml è
public List getList() { return Agenda.getList(); } specificato che da AgendaList.jsp si
deve andare, su questa stringa di
private UIData table; risposta, ad AgendaForm.jsp.
public UIData getTable() { return table; } Siamo quindi arrivati alla form;
public void setTable(UIData table) { notare però che prima di arrivarci,
this.table = table; si è cambiato il bean corrente: in
} questo modo la form può leggere e poi
public void edit(ActionEvent ae) { scrivere direttamente nel bean dati,
bean = (Agenda)table.getRowData(); passando per il backing bean che fa
} da intermediario. Quando l’utente
public void create(ActionEvent ae) { ha modificato i dati e preme salva, si
bean = new Agenda(); esegue lo stesso meccanismo: prima
} viene salvato il bean nel database,
public void delete(ActionEvent ae) { poi si ritorna alla lista dei bean.
Agenda.remove((Agenda)table.getRowData()); Il percorso della creazione di un
} nuovo bean è analogo, solo che il
metodo create non seleziona il bean
// gestione form corrente ma ne crea uno nuovo.
Agenda bean; Infine la delete elimina direttamente
public AgendaBacking() { il bean corrente senza andare alla
bean = new Agenda(); form.
}
public String getEmail() {
return bean.getEmail(); } Conclusioni
public Long getId() {
return bean.getId(); } Con questo esempio, serrato ma suf-
public String getNome() { ficientemente dettagliato, abbiamo
return bean.getNome(); } esplorato abbastanza a fondo come
public void setEmail(String email) { funzionano le JSF: apprendendo
bean.setEmail(email); } bene i concetti qui esposti è possibile
public void setId(Long id) { bean.setId(id); } cominciare a lavorare proficuamen-
public void setNome(String nome) { te. Le JSF comunque sono molto
bean.setNome(nome); } potenti e ricche di funzionalità: i tag
public void setPhone(String phone) { sono ben più numerosi di quelli qui
bean.setPhone(phone); } esposti, e la logica sottostante (so-
public String getPhone() { prattutto i misteri del “ciclo di vita”)
return bean.getPhone(); } possono richiedere un po’ di tempo
public void save(ActionEvent ae) { per essere approfonditi. I vantaggi
Agenda.store(bean); nell’uso della tecnologia comunque
} compensano di gran lunga il tempo
} investito nell’apprendimento.

LISTATO 6 Il dettaglio dell’agenda


ne inviata al server, e viene chiamato il metodo edit del
backing bean. A questo punto si sfrutta il binding: la da- Note Biografiche
tatable sa quale è la riga corrente e la fornisce a richiesta Michele Sciabarrà si occupa di Java fin da quando, nel 93, sca-
con il metodo table.getRowData(). Quindi il bean corrente ricò il sorgente di HotJava e per compilarlo saturò il disco del-
viene impostato come campo del backing bean. la Workstation Sun che amministrava. Da allora ha lavorato in
Java passando dalle applet per Netscape 2 fino alle applicazioni
Notare che mentre il backing bean è uno solo, il bean bancarie di classe enterprise. Dopo aver scritto di Java e averlo
dei dati può variare. Il trucco è usare dei metodi “proxy”: insegnato per dieci anni, è direttore esecutivo di Java Journal.
Quando non cerca di imparare le ultime API o disquisisce della
notare come sono scritti i getNome, getEmail, getPhone: in superiorità del modello Open Source, si diletta a programmare
questo modo si varia il bean corrente e si lascia sempre lo cellulari Symbian in C++ e amministrare sistemi Linux.
stesso backing bean.

16 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

Le novità di
JSF 1.2
La tecnologia JSF (Java Server Faces) continua il suo processo di maturazione. Dopo la versio-
ne 1.1 che mirava a dare stabilità alle specifiche, la nuova versione di JSF diventa una tecnologia
centrale della piattaforma JEE5. Ad agosto del 2005 infatti sono state pubblicate le specifiche per
la versione 1.2, attualmente ancora in stato di “Proposed Final Draft”. In questo articolo vedremo
quali sono le novità e a quali problemi è stato posto rimedio.

>> di Andrea Nasato (andrea.nasato@javajournal.it)


e quindi anche le specifiche JSTL avanzano di una

L
versione: dalla 1.1 alla 1.2.
JSP, a partire dalla versione 2.0, era già dotato di un
a nuova versione delle specifiche expression language, derivato da quello presente nel-
di JSF si pone essenzialmente due le JSTL 1.0. L’EL di JSP ha però due importanti limi-
obiettivi. Il primo è quello di inse- tazioni: la valutazione dell’espressione è immediata
rire in maniera più marcata il fra- ed è in sola lettura.
mework all’interno dell’architettu- La valutazione immediata è quella che avviene nel
ra JEE. Infatti anche altre tecnolo- momento in cui il motore JSP compie il render del-
gie, già presenti in JEE, hanno su- la pagina. L’analisi avviene scandendo il sorgente
bito dei cambiamenti e la loro relazione con JSF partendo dall’alto verso il basso. Quando viene in-
si è fatta più stretta. Inoltre dalla versione JEE5 contrato un token dell’EL, questo viene immediata-
troveremo JSF come componente fondamenta- mente valutato e ne viene fatto il bind con l’oggetto
le: ogni vendor che vuole ottenere la certificazio- referenziato. Questo tipo di espressione (della forma
ne Sun dovrà fornire una implementazione della ${expr}) può essere usata da sola all’interno della
specifica. pagina, oppure come valore di un tag JSP che accetta
Il secondo obiettivo è di porre rimedio ai problemi espressioni valutate a run time.
riscontrati dagli sviluppatori che hanno utilizzato la
tecnologia. Si va dalla semplice correzione di bug,
all’adeguamento delle specifiche a tecnologie ormai
consolidate in internet come AJAX. Nell’articolo ci
concentreremo su entrambi questi aspetti tentando
Novità importante è
di capire quali sono state le motivazioni che hanno
guidato l’expert group. l’introduzione di
Unified Expression Language
Unified Expression
La prima importante novità è l’introduzione dell’Uni- Language (EL)
fied Expression Language (EL). In realtà questa non
è una vera e propria novità di JSF; il fatto nuovo è che
l’EL usato in JSF diverrà comune anche a JSP (Java
Server Pages) e a JSTL (Java Standard Tag Library). Deferred Evaluation
Ciò ha comportato una revisione delle specifiche an- Si pone il seguente problema: in JSP una volta che il
che per queste due tecnologie. bind a una variabile è stato fatto, non è più possibile
L’expression language che caratterizza JSF, a partire modificarlo, ovvero l’EL di JSP non ha il concetto di
dalla versione 2.1 di JSP, viene “spostato” da JSF a fase che invece è proprio di JSF. Inoltre i token dell’EL
JSP. Ciò comporta che tutto il package javax.faces.el.* JSP sono read-only. Dato ad esempio un bean, di que-
di JSF viene deprecato e tutte le sue classi e metodi sto si può solo fare il get delle proprietà e non il set.L’EL
vengono replicati nel package javax.el.* che sarà con- di JSF invece non presenta questi problemi: permette
tenuto in JSP. Anche JSTL si adeguerà al nuovo EL infatti quello che si chiama deferred evaluation.

n.1 - novembre/dicembre 2006 17


speciale JavaServer Faces JAVA Journal

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN”>


<%@ taglib uri=”http://java.sun.com/jsf/core” prefix=”f”%>
<%@ taglib uri=”http://java.sun.com/jsf/html” prefix=”h”%>
<f:view>
<!-- carico il bundle dei messaggi -->
<f:loadBundle basename=”it.jugpadova.loginJsf.LocalizedResources”
var=”bundle” />
<html>
<head>
<title><h:outputText value=”#{bundle.welcome}” /></title>
</head>
<body>
<h:form id=”loginForm”>
<table cellspacing=”0” cellpadding=”0”>
<tr>
<td><h:graphicImage value=”/images/LogoJugPadova.png”
alt=”Benvenuto” title=”Benvenuto” /></td>
<td>
<table cellpadding=”5” cellspacing=”3”>
<tr>
<td colspan=”3”><h:outputText value=”#{bundle.welcome}”
styleClass=”login-heading” /></td>
</tr>
<tr>
<td><h:outputLabel for=”userNameInput”>
<h:outputText value=”#{bundle.insertUserName}” />
</h:outputLabel></td>
<td><h:inputText id=”userNameInput” size=”20” maxlength=”30”
value=”#{user.login}” required=”true”>
<f:validateLength minimum=”5” maximum=”30” />
</h:inputText></td>
<td><h:message for=”userNameInput” styleClass=”errors” /></td>
</tr>
<tr>
<td><h:outputLabel for=”passwordInput”>
<h:outputText value=”#{bundle.insertPassword}” />
</h:outputLabel></td>
<td><h:inputSecret id=”passwordInput” size=”20” maxlength=”20”
value=”#{user.password}” required=”true”>
<f:validateLength minimum=”5” maximum=”15” />
</h:inputSecret></td>
<td><h:message for=”passwordInput” styleClass=”errors” /></td>
</tr>
<tr>
<td/>
<td><h:commandButton action=”#{user.checkUser}”
title=”#{bundle.loginButton}” />
</tr>
</table>
</td>
</tr>
</table>
</h:form>
</body>
</html>
</f:view>

LISTATO 1 Un esempio di deferred evaluation syntax

18 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

FIGURA 1 Il ciclo di vita di JSF

Per deferred evaluation si intende che il JSP engine viene sol- di restore view (attraverso il nuovo metodo isPostBack() di
levato dal compito di valutare l’espressione, compito che ResponseStateManager) si accorge che ora è un evento di
viene invece affidato a fasi successive del ciclo di vita. La postback, e fa procedere il ciclo di vita. In particolare i due
forma (precisamente #{expr}) di un’espressione di questo valori verrano usati in queste fasi:
tipo è quella abituale all’interno dei tag JSF che si riferi-
scono a proprietà e metodi pubblici di un managed bean. • process validation: il framework controlla la correttezza
Vediamo un esempio di funzionamento di questo meccani- formale dei parametri forniti dall’utente;
smo nel Listato 1. • update model values: nel caso in cui la fase di validazione
sia superata con successo, i due valori servono ad aggior-
L’esempio propone una semplice pagina di login, in nare il nostro bean user;
cui sono presenti i classici due campi di input. Sup-
poniamo che un utente apra una sessione del browser
e richieda la pagina. Quando arriva una tale richiesta,
JSF entra nella fase di restore view. Durante questa fase
il framework si accorge che è la prima richiesta della
pagina, quindi cortocircuita il resto delle fasi e passa il
Per deferred evalua-
testimone direttamente alla fase di render response (vedi tion si intende che il JSP
Figura 1). Tale fase valuta l’espressione #{user.login}
proprio come se fosse una valutazione immediata. In
engine viene sollevato
questo caso all’utente viene proposta la pagina con i due dal compito di valutare
campi di input vuoti.
l’eccezione
Quando invece arriva la seconda richiesta (cioè l’utente
ha digitato login e password e ha premuto invia), la fase

<%@ taglib uri=”http://java.sun.com/jsf/


html” prefix=”h”%> Method expression
<%@ taglib uri=”http://java.sun.com/jsf/ Un’altra caratteristica importante dell’EL di JSF, che ver-
core” prefix=”f”%> rà quindi riportata anche nella versione 2.1 di JSP, è la
<%@ taglib uri=”http://java.sun.com/java/ possibilità di inserire espressioni che non si riferiscono a
jstl/core” prefix=”c”%> proprietà di oggetti, ma a metodi veri e propri. JSF infatti
<f:view> fornisce la possibilità di richiamare l’esecuzione di un me-
<ul> todo di un bean. Tornando all’esempio 1, vediamo come
<c:forEach items=”${books}”var=”b”> l’attributo value del tag commandButton prenda come valo-
<li><h:outputText value=”#{b}” /></li> re il ritorno del metodo checkUser del nostro managed bean.
</c:forEach> Questo metodo verrà richiamato durante la fase di invoke
</ul> application per eseguire la logica di business.
</f:view>

LISTATO 2 esempio di tag JSTL

n.1 - novembre/dicembre 2006 19


speciale JavaServer Faces JAVA Journal

<web-app>
JSF fornisce di default il render kit per l’HTML, ma per-
<jsp-property-group>
mette di aggiungere modalità di presentazione anche per
<deferred-syntax-allowed-as-literal>
client che interpretano altri meta linguaggi. È ad esem-
true
pio possibile creare un render kit che genera codice SVG
</deferred-syntax-allowed-as-literal>
</jsp-property-group>
(Scalable Vector Grafix) oppure XUL (Xml User Interface
... Language), usato da Firefox, o addirittura Flex.
</web-app> Questa caratteristica esiste sin dalla prima versione delle
specifiche; ciò che non si poteva fare fino ad ora era uti-
LISTATO 3 deployment descriptor lizzare render kit differenti all’interno della stessa web ap-
plication: ad esempio non si poteva passare da una pagina
in HTML a una in SVG ad una in XUL, mantenendo come
Unified Expression Language e JSTL model e controller JSF. O meglio questo si poteva fare, ma
si doveva definire un ViewHandler custom che fosse in gra-
Lo unified expression language viene esteso anche a JSTL. do di gestire i vari render kit.
Infatti anche i tag JSTL possono contenere delle espres- Adesso è sufficiente definire in pagina quale sia il render
sioni da valutare a run time e come accade nel caso pre- kit da usare, specificandolo nell’attributo renderKitId del
cedente, tali espressioni vengono valutate dal motore JSP tag f:view e avendo l’accortezza di definire nel file faces-
ogniqualvolta la pagina viene interpretata. config.xml il tag render-kit-id con lo stesso valore.
Consideriamo l’esempio del Listato 2, in cui si compie un
ciclo sui valori di un bean attraverso il tag JSTL forEach e
si presenta ogni valore attraverso il tag JSF outputText. A
causa dei diversi momenti in cui le espressioni vengono
valutate, il codice non si comporta come ci aspettiamo.
JSF astrae il mecca-
Con la nuova versione di JSTL che si appoggerà all’ex-
pression language definito in JSP, il codice del Listato nismo di presentazione
3 funzionerà correttamente a patto di cambiare $ con #
nell’attributo items del tag forEach. al client definendo
il render kit
Unified Expression Language – Alcuni problemi di
compatibilità

La modifica delle specifiche JSP comporta alcuni problemi Nuovo Tree Creation e Content Interweaving Model
di compatibilità con il codice scritto fino alla versione 2.0.
Infatti fino a tale versione la coppia di caratteri #{ non Nelle applicazioni con JSF la vista viene spesso realizzata
rappresentava una parola riservata. Era quindi perfet- come una pagina JSP all’interno della quale trovano posto
tamente lecito usare tale combinazione all’interno della i componenti JSF. Fino alla versione 1.1 del framework la
pagina JSP. convivenza tra scriptlet JSP e tag JSF non era gestita al
Supponendo di avere realizzato una web application che meglio.
usava i caratteri #{ all’interno delle pagine e volendo farne Si prenda in considerazione il Listato 4 che rappresenta
un deploy su un container che supporta le specifiche JSP una pagina JSP contenente un tag JSF che raggruppa due
2.1 ,si presentano 3 alternative: elementi, un tag JSF che stampa un messaggio e, di segui-
• procedere all’escape dei caratteri all’interno delle pagine to, uno scriptlet JSP che stampa un secondo messaggio.
JSP, ovvero usare l’espressione \#{; Visualizzando la pagina attraverso un browser ci si attende
• inserire nel deployment descriptor (l’usuale file web.xml) di vedere, in sequenza, “Messaggio 1” e “Messaggio 2”.
il codice di Listato 3;
• usare in pagina la direttiva <%@page … deferredSyntaxAll Ciò che avviene invece è proprio il contrario: viene prima
owedAsLiteral=”true” %> visualizzato “Messaggio 2” e poi “Messaggio 1”.
Utilizzando uno di questi accorgimenti l’applicazione potrà Il motivo di questo comportamento è il seguente. Il mo-
funzionare anche con la nuova specifica.
1:<%@ taglib uri=”http://java.sun.com/jsf/html”
prefix=”h”%>
2:<%@ taglib uri=”http://java.sun.com/jsf/core”
Render Kit
prefix=”f”%>
Un’altra novità importante riguarda i render kit. Come 3:<f:view>
noto JSF è un framework nato per la presentazione di 4: <h:panelGroup>
contenuti sul web, quindi è naturale pensare che l’output 5: <h:outputText value=”Messaggio 1” />
inviato al client sia HTML. In realtà JSF astrae il mecca- 6: Messaggio 2
nismo di presentazione al client definendo il render kit, 7: </h:panelGroup>
che è quell’insieme di classi aventi il compito di definire la 8:</f:view>
modalità di presentazione.
LISTATO 4 il problema del content interweaving

20 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

tore JSP analizza la pagina dall’alto verso il basso fino fasi è l’istanza di UIViewRoot, che viene creato nella prima
ad incontrare il tag h:panelGroup. I figli di questo tag (h: fase (la restore view), che per questo motivo è l’unica nella
outputText in questo caso) demandano il render di sé stessi quale non ci sono eventi.
al padre. Quindi il render di outputText non avviene finché Questo meccanismo risulta comodo nel caso in cui si
non si raggiunge la chiusura del tag panelGroup. A questa vogliano gestire le richieste AJAX. Si supponga infatti di
regola non sono però soggetti gli scriptlet JSP, quindi appe- creare un AjaxPhaseListener il quale avrà il compito di capi-
na trova “Messaggio 2” il motore JSP ne compie il render. re, una volta ricevuta la notifica, se questa è stata generata
Questo errato comportamento è noto come “content inte- da una richiesta AJAX.
rweaving problem”. Se questo è il caso, il listener potrà attivare la logica che
Per ovviare a questo inconveniente sono stati apportati soddisfa la richiesta e cortocircuitare il resto delle fasi chia-
numerosi cambiamenti strutturali. La seguente descrizio- mando il metodo renderResponse() o responseComplete().
ne non è semplice, chi non è interessato può passare al In questo modo la richiesta AJAX, non dovendo passare per
prossimo paragrafo. tutte le fasi del ciclo di vita, viene servita più velocemente.
Sono stati cambiati la specifica di realizzazione del
ViewHandler delle pagine JSP e la classe che rappresenta il LifeCycle diversi all’interno della stessa applicazione
custom tag JSP usata da tutti i componenti JSF. L’enco- Un’altra novità è la possibilità di definire, all’interno del-
ding non viene più fatto mentre la pagina JSP viene ana- la stessa applicazione, più istanze della servlet FacesServlet
lizzata, durante questa fase viene unicamente costruito con URI mapping diversi. Ad ognuna di queste istanze è
l’albero dei componenti e solo quando questo è completo possibile associare un ciclo di vita diverso. Il meccanismo
(l’albero comprende anche i componenti non JSF) si pro- di associazione prevede che nel metodo init della servlet
cede all’encoding. In questo modo l’autore delle pagine avvenga l’acquisizione dei riferimenti alle particolari
non si troverà più a dover fronteggiare strani comporta- istanze di Lifecycle e FacesContextFactory da usare nella web
menti come quello descritto nell’esempio 5. application.
Utilizzando il parametro javax.faces.LIFECYCLE_ID, che
può essere specificato come init-param della servlet oppure
come context-param della web application, si può specifica-

Due
re l’implementazione del ciclo di vita da usare.
nuovo concetti Questo meccanismo permette di creare un ciclo di vita
specifico per soddisfare le richieste AJAX (ad esempio con
un numero minore di fasi) e di associarlo ad una istanza
si prestano bene ad un di servlet dedicata.

suo con AJAX


Annotations JEE5

Se l’applicazione JSF viene eseguita all’interno di un con-


tainer JEE5, nei managed bean è possibile usare il mec-
canismo delle annotation. Le annotation vengono usate per
dichiarare dipendenze da risorse esterne o per definire dei
Gestione richieste AJAX parametri di configurazione senza che queste informazioni
debbano essere riportate in un file di configurazione.
AJAX (Asynchronous Javascript and XML) sta diventando La specifica afferma che deve essere possibile inserire, al-
uno degli standard più diffusi per la realizzazione di rich l’interno dei managed bean le seguenti annotation:
client, permettendo di gestire chiamate asincrone al ser-
ver. Le nuove specifiche di JSF partono da questo dato di • @Resource;
fatto e tentano di migliorare l’interoperabilità tra queste • @EJB;
due tecnologie. Sono stati introdotti pertanto due nuovi
concetti, che pur essendo generali, si prestano bene ad un L’annotation @Resource viene usata per riferirsi ad esempio
uso con AJAX. ad un data source o ad una destinazione JMS. È responsa-
bilità del container impostare il riferimento alla risorsa ed
Phase Listeners eseguire la corretta mappatura attraverso JNDI. In sostan-
Come si vede dalla Figura 2, le fasi di un tipico ciclo di vita za si permette allo sviluppatore di non dover specificare
JSF sono sei. Le nuove specifiche stabiliscono che quando nel deployment descriptor le dichiarazioni di resource-ref,
il framework passa da una fase all’altra deve scatenare message-destination-ref, env-ref e resource-env-ref.
degli eventi (Phase Event), precisamente deve segnalare L’annotation @EJB viene usata per riferirsi, all’interno
quando sta per iniziare e quando è terminata una fase. della web application, ad un EJB 3.0. Questo tipo di an-
Chi volesse registrarsi su questi eventi non deve fare altro notation permette di evitare di inserire nel deployment
che creare una classe che implementi l’interfaccia PhaseLi- descriptor le dichiarazioni ejb-ref o ejb-local-ref.
stener che definisce due metodi: beforePhase(PhaseEvent e) e
afterPhase(PhaseEvent e).
Il componente che scatena questi eventi spostandosi tra le

n.1 - novembre/dicembre 2006 21


speciale JavaServer Faces JAVA Journal

Altre novità Il Java User Group dell’autore


Il Java User Group Padova (www.jugpadova.it) è un
Salvataggio dello stato
gruppo nato per facilitare lo scambio di conoscenze,
In JSF le modalità di salvataggio dello stato tra le request
informazioni ed esperienze tra gli sviluppatori softwa-
sono due: salvataggio sul server e salvataggio sul client. La
re dell’area padovana (e non), interessati al linguaggio
specifica fornisce ampia libertà di scelta riguardo la mo-
Java e alle tecnologie correlate. Il gruppo è indipen-
dalità di tale salvataggio, salvo precisare che ogni imple-
dente, senza scopo di lucro, composto da volontari che
mentazione delle specifiche deve fornire di default il sal-
offrono e condividono le loro conoscenze con gli altri
vataggio tramite la serializzazione della vista, con l’usuale
componenti, in un’ottica di crescita e comune inter-
implementazione dell’interfaccia Serializable.
scambio di informazioni. Anche chi non ha esperienza
Nel caso di salvataggio lato server, la vista viene serializ-
con il linguaggio Java è incoraggiato a partecipare al
zata e messa in sessione. Viene successivamente inviata al
JUG! Le attività del JUG Padova comprendono: ritrovi
client una chiave univoca per il recupero della vista cor-
periodici, organizzazione di corsi, partecipazione alle
retta. In questo modo si possono usare le funzionalità di
manifestazioni del settore.
failover proprie del container.
Nel caso di salvataggio lato client (ad esempio in un campo
hidden), la specifica ora suggerisce la necessità che il con-
tenuto di tale salvataggio sia cifrato e reso difficilmente let container che ci permetta di utilizzare JSF 1.2 e se esista
accessibile in quanto può rimanere all’interno del client una implementazione delle specifiche 1.2. L’unico vendor
per un tempo non trascurabile. che attualmente fornisce un tale strumento è proprio Sun
e lo strumento in questione prende il nome di Glassfish.
Resource Bundle Glassfish è il nuovo applicatio server che Sun sta svilup-
La nuova specifica permette di ricavare i valori dei pando in modo collaborativo su http://java.net . Glassfish
bundle di risorse attraverso il nuovo expression lan- rappresenta il primo application server che realizza le spe-
guage, a patto di aver correttamente definito il bundle cifiche JEE5, all’interno delle quali, come detto, si trova
all’interno del file di configurazione di JSF. In questo anche JSF 1.2.
modo non è più necessario usare nelle pagine il tag f: Attualmente Glassfish è in fase di sviluppo, collegandosi
loadBundle per caricare il bundle specificato nel file di però al sito https://glassfish.dev.java.net/ si può scaricare
configurazione. una versione sufficientemente stabile con la quale provare
JSF 1.2.
Resolver
Dalla versione 1.2 di JSF non sarà più possibile la risolu-
zione di oggetti impliciti (quelli che rappresentano mappe Conclusioni
o liste di attributi), ovvero non sarà più possibile creare un
managed bean con lo stesso nome di un oggetto implicito. Le nuove specifiche di JSF danno una maggiore solidità
Prendiamo ad esempio l’espressione #{param[‘x’]}. In JSF al framework inserendolo appieno all’interno dell’archi-
1.1, attraverso un custom variable resolver si poteva cambia- tettura JEE5. Attualmente non esistono implementazioni
re il significato di param (associandolo ad un managed da usare in produzione, ma è probabile che quando le
bean); dalla versione 1.2 param rappresenterà sempre un specifiche assumeranno uno stato finale, le terze parti
Map di parametri e tale significato non potrà essere so- e la comunità open source (Tomcat e MyFaces ad esem-
vrascritto. pio), inizieranno lo sviluppo. Per chi è curioso e non vuole
Inoltre non è più possibile eseguire i metodi setVariableRe- aspettare può provare Glassfish, contribuendo anche allo
solver() e setPropertyResolver() in qualsiasi punto dell’appli- sviluppo di quest’ultimo.
cazione. Dalla versione 1.2, appena arriva la prima request
all’applicazione, questi metodi non hanno più effetto. Tale
modifica è stata aggiunta per evitare che l’applicazione Bibliografia
possa rimanere in uno stato inconsistente a causa del cam-
biamento dei resolver. Specifiche JSF 1.2 http://www.jcp.org/en/jsr/detail?id=252
Specifiche JSP 2.1 http://www.jcp.org/en/jsr/detail?id=245
Specifiche JSTL 1.2 http://www.jcp.org/en/jsr/detail?id=52
Glassfish Specifiche Servlet 2.5 http://www.jcp.org/en/jsr/
detail?id=154
Abbiamo visto che i prerequisiti per il funzionamento di Glassfish https://glassfish.dev.java.net/
JSF sono abbastanza stringenti: JSP 2.1, JSTL 1.2, (Servlet
2.5 e EJB 3.0 se vogliamo usare le annotation JEE5) e JSE5
come implementazione della virtual machine java. Molte Note Biografiche
delle specifiche che si riferiscono a queste tecnologie sono
state solo di recente poste in uno stato di final draft, stato Andrea Nasato si è laureato in Ingegneria Informatica all’Uni-
versità di Padova e lavora come sviluppatore Java in progetti ri-
che permette alle terze parti di iniziare a realizzare prodotti guardanti la Sanità. I suoi interessi spaziano dai framework web
che poi avranno la certificazione Sun. al real time. È socio fondatore del JUG Padova.
È quindi legittimo chiedersi se esista attualmente un serv-

22 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

Un Wizard per
il Web con
JSF e Shale
Le applicazioni web presentano, in talune circostanze, elaborazioni in stile wizard. Con Java Server
Faces e Shale è possibile realizzare wizard per il web in modo funzionale, chiaro ed elegante.

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

l’inserimento delle esperienze in campo professiona-

L
le ed infine il quarto passo chiede una conferma per
i dati inseriti. Osserviamo come in ciascun passo sia
’uso di wizard, anche noti come crea- possibile tornare indietro e modificare i valori prece-
zioni guidate, è comune in molte atti- dentemente inseriti.
vità svolte davanti al computer: dalla
creazione di documenti alla installa- La realizzazione del semplice wizard proposto si basa
zione di application server o databa- su quattro pagine JSP. La pagina “anagrafica.jsp”
se. Tecnicamente un wizard è una se- raccoglie i dati anagrafici di un utente, la pagina
quenza di schermate atte a raccogliere “istruzione.jsp” i dati relativi alla formazione uni-
le informazioni necessarie nella realizzazione di uno versitaria, la pagina “esperienzeLavorative.jsp” i dati
specifico compito. I wizard rendono l’interazione con relativi alle esperienze lavorative ed infine la pagina
gli utenti maggiormente comprensibile, suddividen- “confermaDati.jsp” chiede conferma all’utente dei
do la richiesta di informazione in blocchi logici, evi- dati inseriti. La navigazione tra le pagine è definita
tando, pertanto, la proposizione di una unica, com- nel file faces-config.xml di cui ne riportiamo uno stral-
plessa ed eccessivamente lunga schermata. cio ed in Figura 2 ne diamo una rappresentazione
In questo articolo realizzeremo un wizard per il web grafica:
con JavaServer Faces (JSF) mostrando come sia van-
taggioso realizzarlo attraverso il supporto alla “gestio- …
ne dei dialoghi” offerto dal framework Shale basato su <navigation-rule>
JSF. L’articolo non è una introduzione a JSF, dandone <from-view-id>/anagrafica.jsp</from-view-id>
per acquisita una conoscenza di base, mentre intro- <navigation-case>
duce Shale e le sue features. <from-outcome>success</from-outcome>
Il framework Shale è uno dei progetti della Apache <to-view-id>/istruzione.jsp</to-view-id>
Foundation, collegato al progetto Struts, che ha come </navigation-case>
obiettivo estendere JSF per fornire nuove funzionali- </navigation-rule>
tà che semplificano lo sviluppo. <navigation-rule>
<from-view-id>/istruzione.jsp</from-view-id>
<navigation-case>
<from-outcome>indietro</from-outcome>
Un semplice wizard
<to-view-id>/anagrafica.jsp</to-view-id>
Il wizard che vogliamo realizzare, volutamente </navigation-case>
semplice al fine di soffermarci sugli aspetti tecnici <navigation-case>
e non funzionali, prevede quattro passi, illustrati <from-outcome>success</from-outcome>
nella Figura 1, per la raccolta delle informazioni <to-view-id>/esperienzeLavorative.jsp
anagrafiche e professionali di un utente: il primo </to-view-id>
passo consente l’inserimento dei dati anagrafici del- </navigation-case>
l’utente, il secondo l’inserimento delle informazioni </navigation-rule>
relative al percorso formativo, il terzo passo permette <navigation-rule>

n.1 - novembre/dicembre 2006 23


speciale JavaServer Faces JAVA Journal

<from-view-id>/esperienzeLavorative.jsp
</from-view-id>
<navigation-case>
<from-outcome>indietro</from-outcome>
<to-view-id>/istruzione.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/confermaDati.jsp
</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/confermaDati.jsp</from-view-id>
<navigation-case>
<from-outcome>indietro</from-outcome>
<to-view-id>/esperienzeLavorative.jsp
FIGURA 2 Rappresentazione grafica, ottenuta
con il tool di sviluppo Oracle JDeveloper 10g, della
</to-view-id>
navigazione tra le quattro pagine JSP del wizard
</navigation-case>
</navigation-rule> conto solo di “cosa succede” piuttosto che domandarsi “dove
… devo andare ora”. Questo concetto è presente nella maggior
parte dei framework web basati sul paradigma Model
Osservando le righe di codice riportate possiamo nota- View Controller (MVC) che adottano il design pattern
re come “nativamente” il framework JavaServer Faces front-controller. Per esempio il framework Struts 1.x, proba-
supporti un meccanismo che permette di definire, in un bilmente il più diffuso framework web, presenta il metodo
file XML di configurazione, le regole di navigazione tra le Action.execute() che ritorna un oggetto di tipo ActionForward
varie pagine costituenti una applicazione. In particolare, il quale descrive il valore logico di “outcome”. Tuttavia
l’algoritmo che definisce la navigazione tra le pagine è per quanto analizzato finora dobbiamo notare come il
definito in JSF dall’implementazione della classe astratta framework JavaServer Faces, analogamente al framework
javax.faces.application.NavigationHandler. L’implementazione Struts 1.x, permetta una elaborazione in stile wizard ma
standard fornita dal framework determina la navigazione al prezzo di legare nel codice e nel file di configurazione
da una pagina ad un’altra in base a a tre dati di input: faces-config.xml i passi del workflow, riducendo di fatto la
possibilità di riutilizzare i singoli passi di cui è composto
• Quale pagina sta correntemente processando il form; il flusso e soprattutto non isolando chiaramente i flussi
• Quale azione, tra quelle potenzialmente possibili, è stata stessi (per esempio il wizard presentato non termina con
invocata; la pagina “confermaDati.jsp” ma con la successiva azione
• Quale è il valore ritornato dall’azione invocata; di business invocata sull’onclick() del pulsante “Avanti”).
In particolare ogni pagina JSP deve sapere esplicitamen-
Il meccanismo di navigazione offerto dal framework JSF, te quale è l’azione da invocare per proseguire nel passo
basato sul valore logico, “logical outcome”, restituito dagli successivo del wizard. Il seguente frammento di codice,
action method presenti nei backing managed bean, riduce estratto dalla pagina JSP anagrafica.jsp, chiarisce quanto
l’accoppiamento tra le pagine poiché quando si realizza un espresso:
action method lo sviluppatore del backing bean deve tener
<h:commandButton value=”Avanti” action=”#{anagrafica.insert
Anagrafica}”/>

L’obiettivo che invece desideriamo ottenere è la possibilità


di trattare una elaborazione in stile wizard come una serie
di mappe che mimano una conversazione o un dialogo con
un utente in cui vi è un preciso e netto disaccoppiamento
fra pagine JSP e le azioni di business. Inoltre un wizard
deve poter essere visto come un componente o più sempli-
cemente come una subroutine richiamabile anche da altri
wizard. Queste features sono possibili attraverso il suppor-
to del framework Shale ed in particolare del suo Dialog
Manager, ossia il gestore dei dialoghi.

Introduzione a Shale
FIGURA 1 I passi del wizard Con il framework Shale estendiamo le JavaServer Faces.

24 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

Infatti il framework JSF versione 1.1 segnala la carenza di identificato. L’implementazione di default in JSF della
alcuni servizi tra i quali: classe VariableResolver ricerca un oggetto, identificato dalla
• un sistema evoluto per la gestione del layout delle pagine chiave specificata, nei diversi “scope” dell’applicazione (re-
web; quest, session o application). Supponiamo ora di estendere il
• un sistema di gestione per la navigazione tra le pagine comportamento standard di JSF in modo tale che sia pos-
web in stile wizard; sibile ricavare attraverso una espressione JSF EL anche il
• una migliore interazione con i managed bean durante valore di variabili definite nel file di deployment descriptor,
le fasi costituenti il ciclo di vita di una richiesta di tipo ossia il web.xml, di una web application (l’esempio è voluto
faces. essendo questa una semplice feature di Shale che tuttavia
• la presenza di validatori client-side; chiarisce il modo di interagire con le classi pluggable). Per
• il supporto per il remoting (AJAX [2]); ottenere questo risultato le classi di default da estendere
sono proprio VariableResolver e PropertyResolver. Decorando
Tuttavia JSF è un framework estremamente flessibile e le implementazioni standard delle due classi ora descritte
facilmente estensibile presentando punti di estensione può essere possibile ricavare il valore della variabile var1
rappresentati da pluggable classes che all’occasione pos- con una espressione JSF EL del tipo:
sono essere sostituite o decorate (cfr. il pattern Decorator
[GoF] e la Figura 3). #{jndi.var1}
Le classi che costituiscono il core di JSF possono essere
divise in due gruppi: le classi di infrastruttura e le classi dove la variabile var1 è, per esempio, così definita nel
file web.xml:

<env-entry>
<description>Variabile di test</description>
<env-entry-name>var1</env-entry-name>
<env-entry-type>java.lang.Boolean</env-entry-type>
<env-entry-value>true</env-entry-value>
</env-entry>

Continuando brevemente la descrizione delle classi plug-


gable, la classe ActionListener gestisce tutti gli eventi di tipo
ActionEvent, la classe NavigationHandler seleziona una pagi-
FIGURA 3 Il pattern Decorator na web in base al valore di outcome restituito da un action
method, la classe ViewHandler crea, recupera e mostra una
pluggable. Le classi di infrastruttura sono: Lifecycle, Ren- view delegando alla classe StateManager il salvataggio ed il
derKit, Application e FacesContext. Sinteticamente: la classe recupero dello stato della view ed infine la classe StateMa-
Lifecycle descrive il ciclo di vita di una richiesta JSF, la nager salva e recupera lo stato di una view. Per quanto det-
classe RenderKit gestisce un insieme di renderer, la classe to finora è intuitivo che se volessimo modificare il modo
Application mantiene le reference verso le classi pluggable standard di navigare tra le pagine di una applicazione
e, infine, la classe FacesContext gestisce tutte le informa- JSF, per esempio attraverso una modalità tipo wizard, do-
zioni legate ad una singola richiesta JSF. Queste classi vremmo estendere, o meglio decorare, l’implementazione
rappresentando il carattere distintivo del framework JSF di default di JSF della classe NavigationHandler mentre se
non sono generalmente modificate dagli sviluppatori o da volessimo fornire a JSF una sorta di integrazione verso un
terzi. Tuttavia l’insieme delle classi pluggable si presta ad sistema per la gestione del layout delle pagine web, per
operazioni di modifica o estensione. Le classi pluggable esempio una integrazione con il noto framework Tiles
sono: VariableResolver, PropertyResolver,ActionListener, Naviga-
tionHandler, ViewHandler, e StateManager. Sono tutte classi
astratte, eccetto Action Listener che è una interfaccia. Il dia-
gramma delle classi della Figura 4 da una vista d’insieme
delle pluggable classes.

La classe VariableResolver ha la responsabilità di valutare


l’elemento più a sinistra di una espressione JSF EL mentre
la classe PropertyResolver valuta gli elementi di una espres-
sione JSF EL dopo il segno “.” o all’interno delle parentesi
quadre. Così se abbiamo la seguente espressione JSF EL:

#{persona.nome}

la classe VariableResolver identifica l’oggetto Java referenzia-


to dalla variabile persona e la classe PropertyResolver ritorna FIGURA 4 le classi pluggable del framework
il valore dell’attributo nome dell’oggetto precedentemente JavaServer Faces

n.1 - novembre/dicembre 2006 25


speciale JavaServer Faces JAVA Journal

[1], dovremmo estendere, sempre attraverso un processo riamo un parametro di contesto con il quale si specifica
di decorazione, l’implementazione standard della classe il nome del file di configurazione per il gestore dei dialoghi
ViewHandler. all’interno del quale sarà specificato come le pagine JSP e
Per quanto detto finora si evidenziano alcuni limiti del fra- le classi Java sono tra loro collegate.
mework JSF, ai quali possiamo aggiungere, per maggiore
completezza, l’assenza in JSF di un supporto verso AJAX <context-param>
[2] e l’assenza di validatori client-side. In questo contesto <param-name>org.apache.shale.dialog.CONFIGURATION</param-
si comprende il perché della necessità di Shale. name>
Apache Shale [3], anche noto come Struts 2, è un fra- <param-value>/WEB-INF/dialogo.xml</param-value>
mework che arricchisce JSF con una serie di servizi i quali </context-param>
si possono usare a piacere, in base alle proprie necessità.
Scopo di questo articolo non è descrivere Shale nella sua Shale presenta una serie di dipendenze verso alcuni noti
interezza non potendo esaurire l’argomento in un solo ar- progetti di Apache (i cosiddetti “commons” [8]) e pertan-
ticolo. La Tabella 1 riporta le principali feaures di Shale. to nella directory lib presente all’interno della directory
WEB-INF della applicazione web devono essere presenti
i seguenti jar di queste librerie (per una descrizione det-
Configurazione di Shale tagliata delle dipendenze di Shale verso librerie esterne si
rimanda a [7]). Di seguito indichiamo l’ambiente di runti-
Una volta eseguito il download del framework Shale, me base che supporta Shale:
rimandando a [3] per i dettagli, la sua configurazione è
estremamente semplice. Nel file web.xml della propria ap- • JRE 1.4 o superiore;
plicazione web è sufficiente aggiungere le seguenti righe • Servlet 2.4 e JSP 2.0
di codice: • JSF 1.1 o superiore;
• JSP Standard Tag Library 1.1
<filter> • Apache Commons Bean Utils 1.7 o superiore;
<description>Filtro per Shale</description> • Apache Commons Chain 1.0 o superiore;
<display-name>shale</display-name> • Apache Commons Digester 1.7 o superiore;
<filter-name>shale</filter-name> • Apache Commons Logging 1.0.4 o superiore;
<filter-class>org.apache.shale.faces.ShaleApplicationFilter< • Apache Commons Validator 1.2.0 o superiore.
/filter-class>
</filter> Osserviamo che Shale può funzionare anche con un ap-
plication server che supporta la precedente specifica delle
<filter-mapping> Servlet e delle JSP, ossia la versione 2.3 per le Servlet e 1.2
<filter-name>shale</filter-name> per le JSP (cfr. [7] per i dettagli).
<url-pattern>/*</url-pattern>
</filter-mapping>
Il gestore di dialoghi
le quali definiscono il filtro che analizza le richieste per il
framework Shale. Inoltre, sempre nel file web.xml, dichia- Il modo più semplice ed efficace per rappresentare un dia-

Features Descrizione
View Controller Meccanismo che estende un backing bean associato ad una pagina JSP fornendo al
bean metodi di callback (init(), preprocess(), prerender() e destroy()) invocati in base
ai precisi eventi che si verificano durante il ciclo di vita di una richiesta JSF.
Validazione Integrazione del componente Apache Commons Validator [4] per la validazione sia
lato client che lato server.
JNDI Accesso semplificato, attraverso espressioni JSF EL, alle proprietà definite nel file di
configurazione web.xml.
Dialog Manager Gestore per la realizzazione di wizard per il web, configurato attraverso un file XML
Application Manager Un controller per le richieste HTTP a livello application.
Remoting Supporto server-side al modello di programmazione AJAX
Clay Modulo per il riuso delle pagine HTML in modo simile a Facelets [5] e Tapestry [6];

TABELLA 1 Le principali features di Shale

26 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

logo, adottando questo termine in sostituzione di wizard


per adeguare la terminologia al framework Shale, è un
diagramma UML degli stati. I diagrammi di stato sono una
tecnica consueta per descrivere il comportamento di un si-
stema. Essi descrivono tutti i possibili stati raggiungibili da
un particolare oggetto e come cambia lo stato dell’oggetto
in conseguenza degli eventi. Il framework Shale definisce
quattro tipi di stato, di seguito descritti:

• Action State: rappresenta l’invocazione di un metodo


pubblico. Questo metodo non prende nessun parametro
di input e restituito una stringa che è trattata come un
valore di “outcome”;
• View State: rappresenta il rendering di una pagina JSP
in attesa del susseguente submit di una form.
• Subdialog State: consente al dialogo principale di
invocare un altro dialogo, visto dal primo come una
subroutine;
• End State: termina il dialogo corrente;

Torniamo ora al semplice dialogo presentato all’inizio del-


l’articolo. La Figura 5 ne da una rappresentazione attra-
verso un diagramma degli stati.

Osservando con attenzione la Figura 5 possiamo notare


che le attività espletate durante l’esecuzione del dialogo
sono:

1. Setup: operazioni di inizializzazione per il dialogo cor-


rente;
2. Anagrafica Form: pagina JSP attraverso la quale l’utente
inserisce le informazioni anagrafiche;
3. Inserisci Anagrafica: azione che permette la gestione dei FIGURA 5 Diagramma degli stati che rappresenta il
dati anagrafici forniti; dialogo Gestore Anagrafica
4. Istruzione Form: pagina JSP attraverso la quale l’utente
inserisce i dati relativi al proprio percorso formativo; estratto dalla pagina JSP anagrafica.jsp, chiarisce quanto
5. Inserisci Istruzione: azione che permette la gestione dei espresso:
dati forniti relativi alla formazione;
6. Esperienze Lavorative Form: pagina JSP attraverso la <h:commandButton value=”Avanti” action=”avanti”/>
quale l’utente inserisce i dati relativi alle proprie espe-
rienze professionali; L’azione “avanti” che deriva dalla pressione del pulsante
7. Inserisci Esperienze Lavorative: azione che permette la fa transitare il sistema dallo stato, di tipo View State, Ana-
gestione dei dati relativi al percorso professionale; grafica Form -> allo stato, di tipo Action State, Inserisci
8. FineConferma Form: pagina JSP attraverso la quale Anagrafica causando di fatto l’invocazione del metodo
l’utente conferma i dati inseriti; anagraficaazioneDialogo.insertAnagrafica(), dove azioneDialogo
9. Conferma Dati: azione che consente al sistema la confer- è un managed bean definito nel file faces-config.xml.
ma dei dati e, per esempio, la loro persistenza. Ovviamente non è necessario che tutte le interazioni nel
framework Shale siano organizzate in dialoghi. È possibi-
Quanto descritto nell’elenco sopra riportato e rappre- le, anzi probabile, avere un misto di processi navigazionali
sentato dalla Figura 5 è di fatto il file di configurazione standard e processi navigazionali descritti da dialoghi.
dialogo.xml. Il Listato 1 lo riporta nella sua interezza e la Tuttavia per iniziare un dialogo è necessario che un action
Figura 6 ne da una rappresentazione grafica. In questo method torni un valore di outcome che inizi con la parola
file sono riportati gli stati che descrivono il sistema e le chiave dialog:xxxxx. Per esempio il dialogo denominato
transizioni tra questi. Osserviamo come ora vi è un reale Gestore Anagrafica, cfr. Listato 1, descritto in questo articolo
disaccoppiamento tra le JSP e le azioni e come il flusso inizia quando il valore di outcome restituito da un action
elaborativo sia pienamente e chiaramente descritto. method è dialog:Gestore Anagrafica. Una volta terminato il
A differenza di quanto avveniva in precedenza con la dialogo riprende il modo, standard al framework JSF, di
gestione “nativa” della navigazione nel framework JSF navigare tra le pagine dell’applicazione.
ora le pagine JSP non presentano dipendenze esplicite In una applicazione web complessa è possibile avere, mi-
con le relative azioni. Il seguente frammento di codice, gliorando di fatto la chiarezza e la manutenibilità dell’ap-

n.1 - novembre/dicembre 2006 27


speciale JavaServer Faces JAVA Journal

plicativo, più file di configurazione per i dialoghi. Questi <param-value>/WEB-INF/file1.xml,


devono essere specificati sempre attraverso il parametro di /WEB-INF/file2.xml </param-value>
contesto org.apache.shale.dialog.CONFIGURATION e separati </context-param>
dalla virgola:
Il Dialog Manager mantiene un oggetto di tipo
<context-param> org.apache.shale.dialog Status memorizzato in sessione con chia-
<param-name>org.apache.shale.dialog.CONFIGURATION ve “dialog” (valore modificabile attraverso un parametro di
</param-name> inizializzazione di contesto). Questo oggetto ha una proprietà
di tipo java.lang.Object chiamata “data” nella
<?xml version=”1.0” encoding=”UTF-8”?> quale l’applicazione può salvare un oggetto
<!DOCTYPE dialogs PUBLIC che rappresentano lo stato del dialogo cor-
“-//Apache Software Foundation//DTD Shale rente. Pertanto è possibile usare espressioni
Dialog Configuration 1.0//EN”
EL del tipo:
“http://struts.apache.org/dtds/shale-dialog-config_1_0.dtd”>
<dialogs>
<dialog name=”Gestore Anagrafica” start=”Setup”> #{dialog.data.nome}

<action method=“#{azioneDialogo.setup}“ name=“Setup“> per referenziare la proprietà nome dello


<transition outcome=“success“ target=“Anagrafica Form“/>
</action>
stato corrente del dialogo. Quando il dia-
logo termina, attraverso una gestione au-
<view name=“Anagrafica Form“ viewId=“/anagrafica.jsp“> tomatica da parte del framework, lo stato
<transition outcome=”avanti” target=”Inserisci Anagrafica”/> corrente del dialogo va in “out of scope”. Di
</view>
seguito uno stralcio del codice della pagina
<action method=”#{azioneDialogo.insertAnagrafica}” confermaDati.jsp:
name=”Inserisci Anagrafica”> …
<transition outcome=”success” target=”Istruzione Form”/> <h:panelGrid columns=”2”>
</action> <h:outputLabel value=”Nome:”/>
<h:outputLabel value=”#{dia
<view name=”Istruzione Form” viewId=”/istruzione.jsp”>
<transition outcome=”avanti” target=”Inserisci Istruzione”/> log.data.nome}”/>
<transition outcome=”indietro” target=”Anagrafica Form”/> <h:outputLabel
</view> value=”Cognome:”/>
<h:outputLabel value=”#{dia
<action method=”#{azioneDialogo.insertIstruzione}”
name=”Inserisci Istruzione”> log.data.cognome}”/>
<transition outcome=”success” <h:outputLabel
target=”Esperienze Lavorative Form”/> value=”Laurea in:”/>
</action> <h:outputLabel value=”#{dia
log.data.laurea}”/>
<view name=”Esperienze Lavorative Form”
viewId=”/esperienzeLavorative.jsp”> <h:outputLabel
<transition outcome=”avanti” value=”Votazione:”/>
target=”Inserisci Esperienze Lavorative”/> <h:outputLabel value=”#{dia
<transition outcome=”indietro” target=”Istruzione Form”/>
log.data.votazione}”/>
</view>
<h:outputLabel
<action method=”#{azioneDialogo.insertEsperienzeLavorative}” value=”Azienda:”/>
name=”Inserisci Esperienze Lavorative”> <h:outputLabel value=”#{dia
<transition outcome=”success” target=”Conferma Form”/> log.data.azienda}”/>
</action>
<h:outputLabel
<view name=”Conferma Form” viewId=”/confermaDati.jsp”> value=”Qualifica:”/>
<transition outcome=”avanti” target=”Conferma Dati”/> <h:outputLabel value=”#{dia
<transition outcome=”indietro” log.data.ruolo}”/>
target=”Esperienze Lavorative Form”/>
</h:panelGrid>
</view>

<action method=”#{azioneDialogo.confermaDati}”
name=”Conferma Dati”>
<transition outcome=”success” target=”fine”/>
</action> Punti di estensione in JSF

<end name=”fine” viewId=”/fine.jsp”/>


Prima di concludere osserviamo che all’in-
terno dell’archivio shale-core.jar è presen-
</dialog> te un file di configurazione faces-config.xml
</dialogs> che presenta le righe di codice che seguono
(in una applicazione JSF possono essere
presenti più file faces-config.xml di configu-
LISTATO 1 razione [JSF]):

28 n.1 - novembre/dicembre 2006


JAVA Journal JavaServer Faces speciale

FIGURA 6 L’editor XML per la definizione dei dialoghi presente nel plug-in Exadel Studio per Eclipse

differenza per esempio di Struts 1.x, la sua “discrezione” e


… poca intrusività presentando una architettura a servizi di
<application> supporto per JSF.
<navigation-handler>
org.apache.shale.dialog.faces.DialogNavigation Attraverso il pattern Decorator è possibile aggiungere fun-
Handler zionalità ad un oggetto senza la necessità di estendere la
</navigation-handler> classe che lo descrive. Il diagramma delle classi che segue
… ne da una rappresentazione.
</application>

Riferimenti
Come osservato in precedenza non è necessario sostituire
completamente l’implementazione di default di una classe
pluggable con una nuova classe. Infatti il più delle volte [1] TILEShttp://struts.apache.org/1.x/struts-tiles/index.html
è possibile ed anzi è preferibile aggiungere nuove fun- [2] http://it.wikipedia.org/wiki/AJAXAJAX
zionalità alla classe originale attraverso un processo di [3] http://struts.apache.org/struts-shale/index.html
decorazione (decorator pattern, cfr. [GoF]). Di seguito [4] http://jakarta.apache.org/commons/validator/
riportiamo la firma del costruttore della classe DialogNa- [5] https://facelets.dev.java.net/
vigationHandler: [6] http://jakarta.apache.org/tapestry/
[7] http://struts.apache.org/struts-shale/struts-shale.pdf
public DialogNavigationHandler(NavigationHandler parent) [8] http://jakarta.apache.org/commons/
{

this.parent = parent;
Bibliografia
}

Possiamo osservare come al costruttore è passato il riferi- [GoF]: Gamma, Erich, Richard Helm, Ralph Johnson, and
mento dell’implementazione originale del NavigationHan- John Vlissides. 1995. Design Patterns:
dler. Pertanto la classe DialogNavigationHandler delega Elements of Reusable Object-Oriented Software. Pubblicato da
alla classe “parent”, implementazione originale della clas- Addison-Wesley.
se NavigationHandler, in pratica la soluzione della naviga- [JSF]: Kito De Mann. 2005. JavaServer Faces In Action. Pub-
zione quando non si è in presenza di un dialogo, mentre blicato da Manning Publications Co.
gestisce direttamente il nuovo processo di navigazione e
transizione tra gli stati in presenza di un dialogo. La classe
DialogNavigationHandler pertanto decora l’implementa-
zione di default del NavigationHandler.

Conclusioni
In questo articolo abbiamo presentato il framework Shale
basato su JSF. Ovviamente non è sufficiente un solo artico- Note Biografiche
lo per descrivere tutte le features di Shale. Tuttavia risulta Fabio Staro, dottore in Fisica e è Responsabile Tecnico per i pro-
evidente come Shale estenda il modello di JSF fornendo getti Java presso la Direzione Ricerca ed Innovazione di Engi-
neering Ingegneria Informatica S.p.A
servizi e componenti di integrazione. Colpisce di Shale, a

n.1 - novembre/dicembre 2006 29


focus JAVA Journal

JavaCard
Uno degli oggetti che negli ultimi anni è diventato di uso comune, quasi senza che ce ne accorgessi-
mo, è la smart card. Probabilmente la prima smart card con cui la maggior parte di noi è venuta
in contatto è stata la SIM utilizzata per la telefonia cellulare, seguita a ruota dalle smart card per
l’accesso ai bouquet della TV satellitare, senza dimenticare le nuove generazioni di carte di credito
e di debito.
>> di Matteo Campanella (matteo.campanella@javajournal.it)

N
egli ultimi tempi la pubblica ammi- per alimentare il nostro piccolo computer, una serve
nistrazione sta introducendo delle per dargli il segnale di clock, e altre due servono come
Carte Servizi che presto potranno linee di comunicazione (ingresso e uscita). Ne conse-
facilmente sostituire buona parte dei gue che il lettore di smart card altro non è che un di-
documenti che di solito trovano po- spositivo che alimenta la carta quando viene inserita,
sto nel nostro portafogli. Se a quanto gli fornisce il clock di lavoro, e gestisce lo scambio di
sopra citato uniamo anche la moltitudine di carte di informazioni fra carta e computer host. Per comple-
fidelizzazione cliente e raccolta punti, ci possiamo tezza bisogna aggiungere che esistono anche delle
fare un’idea concreta di quanto sia diventato vasto smart card che non hanno logica programmabile
questo mondo, e di quanto la smart card faccia or- all’interno, ma sono solo delle memorie.
mai parte integrante della nostra vita. Vale la pena di
ricordare che, sebbene ci possano apparire come un Le Smart Card rispondono ad uno standard ben pre-
fenomeno relativamente recente, la prima smart card ciso, che è l’ISO 7816 – esso ne fissa le dimensioni
è stata creata nel lontano 1974, da Roland Moreno; fisiche, le caratteristiche elettriche e i dettagli del
di contro quest’anno sono state prodotte quasi un protocollo di scambio dati. Sebbene le modalità di in-
miliardo di smart card, con una spiccata supremazia terazione con una smart card rimangono ben identi-
di Europa ed Asia (95%) sugli USA (5%). ficate da questo standard (il che riveste fondamenta-
le importanza per l’interoperabilità), ogni produttore
è libero di implementare i dettami della ISO 7816
nel modo che più gli aggrada, un po’ come succede
con Java per il quale Sun Microsystems detta solo le
specifiche, demandando a chiunque sia interessato lo
sviluppo di una JVM ad esse rispondente.
Una delle principali conseguenze di ciò è che ogni
costruttore è libero di mettere a punto un ambien-
te di sviluppo e un insieme di API, o addirittura un
linguaggio di programmazione, che risponde alle
proprie esigenze e non ad uno standard.

Cosa è una Java Card?


FIGJava Card È in questo contesto che nasce l’idea di Java Card;
la finalità è quella di fornire ai costruttori di smart
card una piattaforma che consenta di far girare delle
Cosa è una smart card? piccole applicazioni Java, chiamate applet, su dispo-
sitivi caratterizzati da una disponibilità di memoria
Ma vediamo cosa è esattamente una smart card. Vo- estremamente limitata, e agli sviluppatori una API
lendo semplificare la questione, si tratta di un com- standard, oltre alla possibilità di scrivere codice Java
puter in miniatura, completamente entrocontenuto per la smart card.
nello spessore della carta, i cui unici collegamenti con
il mondo esterno (e quindi con le apparecchiature che Si identificano tre componenti principali della Speci-
utilizzano la smart card) sono i contatti che affiorano fiche Java Card:
dalla carta. Due di quelle piazzole di rame servono

30 n.1 - novembre/dicembre 2006


JAVA Journal focus

1. Specifiche della Java Virtual Machine; dinamico delle classi, il security manager, i thread e la sin-
2. Specifiche del Java Runtime Environment; cronizzazione non sono supportati, così come alcuni tipi di
3. API per la piattaforma Java Card dato complessi come float, double, e char. Affinché l’instal-
lazione di un’applet possa andare a buon fine, è necessario
Riassumendo, la Java Card è essenzialmente una smart che essa implementi un metodo public static install, che vie-
card in grado di eseguire programmi Java. Le specifiche ne chiamato dal Runtime Environment come ultimo passo
prevedono delle risorse hardware veramente esigue: 16KB della procedura di installazione.
di ROM, 8KB di EEPROM e appena 256 bytes di RAM.
L’esecuzione del bytecode Java è possibile grazie all’im-
plementazione di una Java Virtual Machine direttamente
sullo strato di sistema operativo della smartcard, di cui
nasconde completamente gli aspetti peculiari; chi svilup-
LaJava Card è es-
pa per Java Card non si deve preoccupare di quale sia il
produttore; basta attenersi alle specifiche dell’API e non ci
senzialmente una smart
saranno sorprese. Attenzione però, a volte potrebbe venire
la tentazione di utilizzare delle estensioni alle API stan- card in grado di eseguire
dard fornite dal produttore della card al fine di sfruttare
peculiarità della carta: niente di male, si tratta di un passo programmi Java
in alcuni casi indispensabile, ma di fatto pone fine alla
completa portabilità del codice – non è infatti detto che
un altro fornitore abbia implementato le stesse estensioni
(Figura 1). Tutte le applet registrate su una Java Card sono candidate
a fornire servizio, e di conseguenza è necessario che esista
un meccanismo con cui si possa comunicare alla card quale
Come funziona una Java Card? delle applet installate deve essere mandata in esecuzione.
Le Java Card supportano il protocollo di comunicazione fra
Per poter girare su una Java Card, le applet vi devono la card e il lettore così come da specifiche ISO7816; questo
essere preventivamente installate. Non si pensi di avere protocollo prevede l’uso di pacchetti per la comunicazione,
a disposizione tutta la potenza di Java: il caricamento chiamati APDU (Application Protocol Data Units). La card

FIGURA 1 Architettura di una Java Card

n.1 - novembre/dicembre 2006 31


focus JAVA Journal

6. Le (1 byte) – massimo numero di byte attesi nel campo


dati della risposta al comando

Un APDU di riposta invece si compone di:

1. Dati (Le byte al massimo) – campo dati della risposta


2. SW1 e SW2 (entrambi 1 byte) – stato

Nell’ambito della tecnologia Java Card, esiste un solo


APDU predefinito, ovvero quello di cui abbiamo parlato
sopra, il SELECT APDU; in questo caso i campi di cui sopra
devono essere:

CLA=0x0, INS=0xA4, P1=0x04, P2=0x00, Lc=0x08,


Data=AID, Le=0x0
FIGURA 2 Lettore di Smart Card
Il campo Data, in questo caso formato da 8 byte come in-
dicato dal campo Lc, contiene l’AID dell’applet che si vuole
aspetta che il lettore le invii un APDU di comando, esegue selezionare, che deve ovviamente essere uguale all’AID
quanto richiesto e restituisce un APDU di risposta, metten- utilizzato al momento dell’installazione dell’applet sulla
dosi in attesa di una nuova APDU di comando. card.
Fra le molteplici APDU ne esiste una che si chiama SELECT L’APDU di risposta, in caso di operazione eseguita con
APDU, grazie alla quale il lettore segnala alla card quale successo, deve contenere nei campi SW1 e SW2 il codice di
applet deve essere selezionata. La card a questo punto stato 0x9000; negli altri casi sarà cura dell’applet assegna-
chiama prima il metodo deselect dell’eventuale applet che re un codice di errore a quei campi.
è già in esecuzione, e successivamente chiama il metodo
select dell’applet identificata con l’AID (Applet Identifier) Applet Contatore
passato come parametro della SELECT APDU di cui sopra. Vediamo di seguito come scrivere un’applet che implemen-
Da questo momento in poi tutti i comandi APDU che arri- ta un semplicissimo borsellino elettronico. Questo borselli-
vano alla card vengono passati all’applet selezionata, fino no conterrà una certa somma che verrà decrementata nelle
al prossimo SELECT APDU (Figura 2). operazioni di pagamento e incrementata nelle operazioni
di versamento.

Nella progettazione di un’applet Java Card la prima cosa


Il protocollo ISO7816 da fare è pianificare la comunicazione fra la card e l’appli-
cazione “client”; nel caso del nostro borsellino possiamo
immaginare di accettare i seguenti APDU:
prevede l’uso di
1. APDU Accredito – versa una certa cifra nel borsellino,
pacchetti APDU incrementando la giacenza;
2. APDU Addebito – preleva una certa cifra dal borsellino,
decrementando la giacenza;
3. APDU Giacenza – ritorna la giacenza del borsellino.

Sarebbe opportuno implementare una qualche logica di


Scrivere applet per Java Card sicurezza, come ad esempio fare in modo che ognuna delle
tre operazioni sia vincolata dalla digitazione di un codice
APDU PIN; per semplicità invece si supporrà un borsellino “al
Poiché l’applet comunica con il lettore di card e quindi con portatore”, il cui valore massimo possa essere contenuto
il computer “client” mediante lo scambio di APDU come in due byte; le operazioni di accredito e di addebito inoltre
abbiamo visto sopra, è necessario comprendere appieno saranno limitate ad importi rappresentabili su un solo byte
cosa dice lo standard ISO7816 a proposito. – ciò significa che il borsellino potrà contenere al massimo
Per cominciare, ecco i campi che compongono un APDU 32767 “crediti” e le operazioni di versamento o prelievo
di comando: saranno limitate a 127 “crediti” per volta.

1. CLA (1 byte) – classe del comando Accredito


2. INS (1 byte) – istruzione del comando APDU di comando: CLA=0x60, INS=0x61, P1=0x00,
3. P1 e P2 (entrambi 1 byte) – parametri del comando P2=0x00, Lc=0x01, Data=importo, Le=0x0
4. Lc (1 byte) – numero di byte che compongono il succes- APDU di risposta: Dati=null, SW1-SW2=0x9000 (OK),
sivo campo dati 0x6A00 (KO)
5. Dati (Lc byte) – dati passati al comando

32 n.1 - novembre/dicembre 2006


JAVA Journal focus

package it.mc.jctest; }

import javacard.framework.*; private void accredito(APDU apdu) {

public class Borsellino extends Applet { byte[] buffer=apdu.getBuffer();


byte datalen=buffer[ISO7816.OFFSET_LC];
final static byte BorsellinoCLA=0x60; short readlen=
final static byte AccreditoINS=0x61; apdu.setIncomingAndReceive();
final static byte AddebitoINS=0x62; if (readlen!=datalen)
final static byte GiacenzaINS=0x63; ISOException.throwIt(
final static short KOSW=0x6a00; ISO7816.SW_WRONG_LENGTH);
byte crediti=buffer[ISO7816.OFFSET_CDATA];
short giacenza; if (crediti<0) ISOException.throwIt(KOSW);
if ((32767-giacenza)<crediti)
private Borsellino(byte[] bArray, ISOException.throwIt(KOSW);
short bOffset, byte bLength) { giacenza=(short)(giacenza+crediti);
register(); }
}
private void addebito(APDU apdu) {
public static void install(byte[] bArray,
short bOffset, byte bLength) { byte[] buffer=apdu.getBuffer();
new Borsellino(bArray, bOffset, byte datalen=buffer[ISO7816.OFFSET_LC];
bLength); short readlen=apdu.setIncomingAndReceive();
}
if (readlen!=datalen)
public boolean select() { ISOException.throwIt(
return true; ISO7816.SW_WRONG_LENGTH);
} byte crediti=buffer[ISO7816.OFFSET_CDATA];
if (crediti<0)
public void deselect() { ISOException.throwIt(KOSW);
} if (giacenza<crediti)
ISOException.throwIt(KOSW);
public void process(APDU apdu) { giacenza=(short)(giacenza-crediti);
}
byte[] buffer=apdu.getBuffer();
private void giacenza(APDU apdu) {
if (buffer[ISO7816.OFFSET_CLA]==0x0 &&
buffer[ISO7816.OFFSET_INS]==0xA4) byte[] buffer=apdu.getBuffer();
return; short le=apdu.setOutgoing();
if (buffer[ISO7816.OFFSET_CLA]
!=BorsellinoCLA) if (le!=2)
ISOException.throwIt( ISOException.throwIt(
ISO7816.SW_CLA_NOT_SUPPORTED); ISO7816.SW_WRONG_LENGTH);

switch (buffer[ISO7816.OFFSET_INS]) { apdu.setOutgoingLength(le);


case AccreditoINS: buffer[0]=(byte)(giacenza>>8);
accredito(apdu); buffer[1]=(byte)(giacenza & 0xff);
return;
apdu.sendBytes((byte)0,le);
case AddebitoINS:
}
addebito(apdu);
}
return;
case GiacenzaINS:
giacenza(apdu);
return;
default:
ISOException.throwIt(
ISO7816.SW_INS_NOT_SUPPORTED);
}

LISTATO 2 TalkTimerEngine

L’importo da accreditare è specificato nel campo Data, la L’importo da addebitare è specificato nel campo Data, la
SW dice se l’accredito è andato a buon fine o meno (ad SW dice se l’addebito è andato a buon fine o meno (ad
esempio, il borsellino è troppo pieno). esempio, il borsellino non contiene abbastanza crediti).

Addebito Giacenza
APDU di comando: CLA=0x60, INS=0x62, P1=0x00, APDU di comando: CLA=0x60, INS=0x63, P1=0x00,
P2=0x00, Lc=0x01, Data=importo, Le=0x0 P2=0x00, Lc=0x00,Data=null, Le=0x2
APDU di risposta: Dati=null, SW1-SW2=0x9000 (OK), APDU di risposta: Dati=giacenza, SW1-SW2=0x9000
0x6A00 (KO) (OK)

n.1 - novembre/dicembre 2006 33


focus JAVA Journal

Poiché si tratta di un comando di interrogazione non sono Non ci soffermeremo sul metodo addebito(APDU), poiché
previsti parametri passati in chiamata; ci si aspetta che i esso è del tutto simile al precedente, eccezion fatta per la
due byte rappresentativi della giacenza vengano ritornati logica di aggiornamento della giacenza.
nel pacchetto di risposta (Listato 1).
Vediamo quindi il metodo giacenza(APDU apdu), partico-
La classe Borsellino (che deve estendere la classe javaca larmente interessante in quanto illustra come un metodo
rd.framework.Applet) comincia con la dichiarazione del- possa passare delle informazioni al “client” della carta (in
le variabili corrispondenti ai CLA, agli INS e ai codici di questo caso la giacenza del borsellino). Analogamente a
errore dell’applicazione, così come definiti nel paragrafo quanto visto prima, poiché il campo Dati nell’APDU di
precedente. Il contenuto del borsellino è mantenuto nella riposta è opzionale, è necessario che quest’ultimo venga
variabile a 16 bit giacenza. Segue il costruttore dell’Applet, predisposto mediante il metodo setOutgoing(), che ritorna il
chiamato dal metodo install(), che da specifiche deve numero di byte del campo, uguale al campo Le dell’APDU
preoccuparsi di effettuare tutte le inizializzazioni peculiari di comando. In successione si invocano poi i metodi se-
dell’applicazione e di chiamare il metodo register(). In breve tOutgoingLength() passando come argomento il numero
quindi il JCRE (Java card Runtime Environment) all’atto di byte e sendBytes() passando come argomenti l’offset a
dell’installazione dell’applet Borsellino chiama il metodo cui trovare i dati nel vettore buffer e il numero di byte da
install() che crea una nuova istanza dell’Applet, la quale trasmettere.
nel costruttore deve contenere la chiamata al metodo
register(). Poiché può esistere una sola istanza per applet,
il metodo install() può essere chiamato con successo una
sola volta.

I metodi select() e deselect() vengono invocati dal JCRE


Quando si sviluppa
quando è necessario selezionare o deselezionare la spe- del software per Java
cifica applet. La selezione avviene quando la carta riceve
una SELECT APDU recante l’AID dell’applet in questione. Card, codificare l’applet
Se non si ha la necessità di effettuare delle inizializzazioni,
si può tralasciare l’override di questi metodi. È importante
non basta
tenere conto che il metodo select() torna true o false a secon-
da che l’applet accetti la selezione o meno.

Il cuore dell’applet è senza dubbio il metodo process(APDU Conclusioni


apdu), chiamato durante il ciclo di attività dell’applet
ogni qual volta che JCRE riconosce una APDU valida, che Quando si sviluppa del software per Java Card, codificare
viene passata come parametro. Poiché la ricezione di una l’applet non basta: se infatti la card è assimilabile ad un
SELECT APDU, oltre che causare la selezione dell’applet, server che espone dei servizi mediante ADPU di comando
viene passata al metodo process, è necessario che il codice e di risposta, serve anche un client in grado di invocare tali
preveda questo caso, ritornando semplicemente il control- servizi. Ecco quindi che per il test della nostra applet Bor-
lo al JCRE. Si noti come i vari campi della APDU siano fa- sellino sarà necessario sviluppare un client che generi le
cilmente accessibili mediante costanti definite in ISO7816. APDU di comando e interpreti le APDU di risposta. Il client
A seguire si effettua un controllo sulla CLA della APDU per può essere scritto in qualunque linguaggio supportato dal
essere certi che non si sia stati chiamati con una CLA non fabbricante del lettore di card, che mette a disposizione
supportata dall’applicazione, e si entra in uno switch che una serie di librerie per lo sviluppo di applicazioni per il
chiama, a seconda del campo INS, il giusto metodo di ser- controllo del lettore e l’interazione con le applet residenti
vizio, gestendo come default l’eccezione di INS non servita. sulla carta.

Il metodo accredito(APDU apdu) costituisce un valido Bibliografia


esempio di come si presenta un metodo che riceve dei dati
dall’APDU. Essendo il campo Dati opzionale, questo non http://java.sun.com/products/javacard/index.jsp
viene passato di default all’applet, ed è necessario, dopo http://www.cyberflex.slb.com/
avere estratto il numero di byte che lo compongono dal http://www.cryptoflex.com/
campo Lc, invocare il metodo setIncomingAndReceive(),che http://www.reflexreaders.com/
legge il campo Dati nel buffer; tali dati diventano quindi
accessibili a partire dall’indice APDU.OFFSET_CDATA. La Note Biografiche
parte restante del metodo verifica che non si tratti di un Matteo Campanella. Classe 1967, ingegnere elettronico, libero
numero negativo di crediti e che ci sia ancora “spazio” nel professionista, si occupa di consulenze aziendali nell’ambito di
borsellino. open source changeover e java enterprise computing, con parti-
colare riferimento ai sistemi di content management e alle web
Non vi è la necessità di costruire l’APDU di risposta poiché enterprise applications. Nel campo dell’elettronica si occupa di
ci pensa il JCRE, utilizzando di default la SW 0x9000 se il embedded systems, wireless communications e elaborazione
metodo process() non solleva nessuna eccezione. numerica dei segnali.

34 n.1 - novembre/dicembre 2006


JAVA Journal focus

n.1 - novembre/dicembre 2006 35


focus JAVA Journal

Gcj: Gnu Compiler


for Java
Gcj è il compilatore Java sviluppato dalla Free Software Foundation in seno al progetto Gnu Com-
piler Collection. Nato dall’idea di un dipendente di Cygnus Solutions (acquisita da RedHat nel
2000) adotta un approccio estremamente tradizionale alla compilazione ed esecuzione di codice
Java.

>> di Andrea Zito (andrea.zito@javajournal.it)

S
prattutto se si vogliono introdurre delle ottimizza-
i tratta di un’altra Java Virtual Machi- zioni.
ne? Questa domanda sorge spontanea: Come se non bastasse un JIT efficiente risulta esse-
in effetti tramite i vari tool che accom- re molto complesso e di conseguenza richiede una
pagnano gcj è possibile compilare ed quantità sensibile di memoria, il che può non essere
eseguire del codice Java, esattamente un problema su un desktop od una workstation con
come avviene utilizzando la JVM della Sun. Ma una memoria di svariate centinaia di megabyte, ma
allora dove sta la differenza? è sicuramente un fattore rilevante in un sistema
embedded. Infine Java nella sua implementazione
classica non ha una buona interoperabilità con altri
Funzionamento classico di una JVM linguaggi: le chiamate fra Java e C/C++ sono lente
e non banali.
L’approccio tradizionale a Java è caratterizzato da
due fasi: una fase di traduzione ed una di esecuzione.
Il codice sorgente viene compilato tramite il pro-
gramma javac, che produce una serie di file .class
contenenti la rappresentazione binaria delle infor-
La
tecnica utilizzata
mazioni relative ad una classe. Queste informazioni
sono tradotte in bytecode: il set di istruzioni di una da Gcj prende il nome di
macchina virtuale basata su stack.
La fase di esecuzione viene gestita da una JVM “Ahead of time
(Java Virtual Machine) che ha il compito di leggere
ed interpretare i file .class creati precedentemente. compilation”
Una JVM può essere vista come un emulatore di
una macchina il cui set di istruzioni è il Java byte-
code.

Questo livello di emulazione chiaramente influisce Semplicemente un altro linguaggio di program-


sulle prestazioni in fase di esecuzione. Una solu-
mazione
zione al problema prende il nome di JIT (Just In
Time) compiler. Grazie a questa tecnica il sistema si Questo è l’approccio alla base di gcj. Java viene visto
accorge che un metodo è stato chiamato un nume- e trattato come un qualsiasi altro linguaggio basato
ro sufficientemente cospicuo di volte da renderne sulla compilazione.
giustificabile la compilazione nativa. Tutto questo
avviene a run-time. La tecnica utilizzata prende il nome di “Ahead of
time compilation” e prevede le seguenti modalità:
Un problema di questo meccanismo è l’appesanti-
mento delle fasi di inizializzazione: c’è bisogno di • Compilazione diretta da sorgente ad istruzioni
controllare quante volte un metodo viene invocato macchina
ed inoltre la compilazione richiede del tempo, so- • Compilazione da sorgente a bytecode

36 n.1 - novembre/dicembre 2006


JAVA Journal focus

Abbiamo usato SciMark2 (http: Per maggiore completezza il test Il vantaggio che consegue dalla compilazio-
//math.nist.gov/scimark2) per è stato effettuato in entrambi i ne nativa non è tanto la velocità, quanto un
effettuare un veloce benchmark modi. miglioramento nell’utilizzo della memoria.
che prendesse in esame velocità Gli sforzi profusi nel miglioramento dei JIT
ed utilizzo di memoria di gcj (v. Velocità di esecuzione compiler li ha resi estremamente efficienti,
4.0.2) e Sun JDK 1.5. Modalità normal: tanto che in determinate situazioni possono
• Sun JDK: 27415 ms essere più prestanti rispetto a codice nativo
I test sono stati eseguiti su un • Gcj: 29248 ms poiché effettuano delle ottimizzazioni in
Athlon 1000 equipaggiato con base al contesto attuale. Questo non è fat-
768 Mb di RAM ed è stato uti- Modalità large: tibile con la “ahead of time compilation”
lizzato il pacchetto jar disponi- • Sun JDK: 63188 ms poiché la compilazione avviene in una fase
bile al download sul sito di Sci- • Gcj: 60324 ms precedente a quella dell’esecuzione; di con-
Mark. seguenza il compilatore non ha informazioni
Il tempo di esecuzione è stato Utilizzo di memoria sullo stato attuale della macchina e non può
misurato utilizzando il coman- quindi effettuare ottimizzazioni dipendenti
do time, per l’utilizzo di memo- Modalità normal dal contesto. In generale, comunque, un
ria ci si è invece affidati a ps. eseguibile nativo risulta più veloce in fase di
Imple- VM Size VM RSS inizializzazione (Riquadro 1) .
L’eseguibile nativo è stato com- menta- (kb) (kb)
pilato con queste opzioni: zione
gcj –main=jnt.scimark2. Non soltanto un compilatore
commandline -O3 -o sci- Sun JDK 261436 10472 Gcj non è soltanto un compilatore. È un am-
mark scimark2lib.jar 1.5 biente Java completo, paragonabile al JDK
della Sun. Assieme al compilatore vengono
Le prove sono state effettua- Gcj 4.0.2 30188 12684 forniti un interprete di bytecode ed una serie
te invocando scimark in que- di librerie d’appoggio che completano l’am-
sto modo: Modalità large biente. Il cuore pulsante di gcj risiede nella
• Nativo: ./scimark sua runtime-library: libgcj. Quest’ultima si
• Interpretato: Imple- VM Size VM RSS occupa di gran parte del lavoro, offrendo un
java -cp scimark2lib.jar menta- (kb) (kb) garbage collector, l’interprete di bytecode e
jnt.scimark2.commandline zione un ClassLoader capace di gestire sia librerie
native che file .class.
SciMark2 può essere eseguito Sun JDK 260412 70364
in due modalità: normal e large. 1.5 La Tabella 1 riporta l’equivalente di alcuni
La scelta di una piuttosto che dei tool disponibili nel JDK della Sun.
l’altra determinerà la comples- Gcj 4.0.2 94936 77692
sità computazionale del test.
Prima compilazione
RIQUADRO 1 Un semplice benchmark sulle prestazioni in termini di
velocità di esecuzione ed utilizzo di memoria di gcj e del Sun JDK 1.5 Adesso che abbiamo un idea di cos’è e di
quello che è capace di fare, sporchiamoci le
• Compilazione da bytecode ad istruzioni macchina mani con la prima compilazione nativa tramite gcj. Come
primo esempio ci avvarremo del codice riportato nel Li-
La vera potenza di gcj risiede però nella possibilità di stato 1, che stampa sullo standard output la famosa
utilizzare soluzioni miste: le vostre applicazioni potran- frase: Hello World!
no essere composte da porzioni compilate nativamente Per rendere il tutto più interessante useremo due classi
ed altre interpretate! Questa caratteristica fa di gcj uno interdipendenti.
strumento veramente flessibile, che si adatta facilmente
alla esigenze più disparate. Il processo che porta ad ottenere un eseguibile si divide in
due parti, la compilazione ed il linking. Per chiunque
abbia usato almeno una volta il compilatore gcc la
Sun JDK GNU Gcj prima fase risulterà molto familiare, per quanto ri-
javac gcj -C guarda seconda invece ci sarà qualche novità.
java gij
javadoc gjdoc La prima cosa da fare è istruire gcj su quali file desi-
deriamo vengano convertiti in linguaggio macchina:
javah gcjh
javap jcf-dump gcj -c HelloWorld.java Printer.java

TABELLA 1 Corrispettivi Sun JDK Questo comando farà si che i sorgenti vengano

n.1 - novembre/dicembre 2006 37


focus JAVA Journal

main per il test delle unità (come avviene nel nostro


File HelloWorld.java:
esempio). Questo comportamento confonde il linker che
1 class HelloWorld{
non sa individuare quale fra i diversi main è quello da
2 public static void main(String[] args){
cui il programma deve iniziare. Per questo motivo gcj
3 Printer p = new Printer();
introduce il nuovo switch –main tramite il quale è pos-
4 p.print(“Hello World!”);
sibile specificare il percorso completo della classe da
5 }
cui deve essere iniziata l’esecuzione. Se per esempio la
6 }
calsse HelloWorld si fosse trovata all’interno del package
it.javajournal.gcj, la chiamata corretta sarebbe dovuta
File Printer.java:
essere:
1 class Printer{
2 public void print(String s){
gcj –main=it.javajournal.gcj.HelloWorld
3 System.out.println(s);
-o hello HelloWorld.o Printer.java
4 }
5
A questo punto l’eseguibile è stato creato e linkato alla
6 public static void main(String[] args){
runtime-library di gcj, tutto è pronto per l’esecuzione.
7 System.out.println(“Unit testing: OK”);
8 }
9 }
Il cuore pulsante di
LISTATO 1 Codice sorgente di HelloWorld.java e
Printer.java fornito con gcj 4
gcj risiede nella runtime
tradotti nei file HelloWorld.o e Printer.o che ne sono la
rappresentazione binaria. In questa fase è possibile spe-
cificare tutte le opzioni di ottimizzazione desiderate. A
library: libgcj
questo punto il nostro programma è in un formato com-
prensibile dal computer, ma per funzionare devono essere
agganciate fra loro tutte le componenti e le librerie esterne
di cui necessita, una su tutte la runtime-library di cgj. Per
ottenere questo risultato usiamo il seguente comando: Librerie dinamiche

gcj –main=HelloWorld -o hello HelloWorld.o Printer.o In determinate situazioni risulta conveniente compilare
porzioni di codice in librerie condivise, così da ottimizzare
Come accennato precedentemente, gcj necessita di un l’utilizzo di memoria (sia primaria, che secondaria). Per
parametro aggiuntivo rispetto a quanto accade per gcc. ottenere questo scopo gcj utilizza lo switch -shared, oltre
In C/C++ un programma può essere composto da più ad una serie di opzioni aggiuntive non strettamente ne-
file ma solamente uno di questi può contenere il metodo cessarie che però portano a delle ottimizzazioni a vari
main, di conseguenza il linker è sempre in grado di capire livelli. Per proporre un esempio pratico, compiliamo
da solo quale è la porzione di codice che deve essere ese- Printer.java come libreria dinamica ed agganciamolo a
guita inizialmente. HelloWorld.

In Java invece è pratica comune creare diversi metodi La prima fase ora si svolge in due parti:

1. compilazione di Printer.java
come libreria dinamica
2. compilazione canonica di
HelloWorld.java

Il punto 1 si ottiene invocando gcj nel


seguente modo:

gcj -shared -fPIC -fjni Printer.java -o


libprinter.so

I primi due switch sono parametri


standard della creazione di librerie di-
namiche, -fjni istruisce il compilatore
FIGURA 1 Schermata comparativa delle 3 librerie per sviluppare sul modo in cui trattare i metodi nativi,
applicazioni grafiche. Dall’alto verso il basso: Swing (disponibili da Classpath nello specifico fa in modo che venga
0.20), SwingWT, SWT. usato JNI al posto di CNI (l’implemen-

38 n.1 - novembre/dicembre 2006


JAVA Journal focus

suoi servizi. Perchè la compilazione e la successiva


File App.java esecuzione abbiano esito positivo il sistema deve
package it.javajournal; riuscire a trovare la nostra libreria, questa deve cioè
class App{ trovarsi all’interno del path del linker. Per apportare
public static void main(String[] args)
delle modifiche locali a tale path è sufficiente agire
throws Exception{
sulla variabile d’ambiente LD_LIBRARY_PATH.
Class f =
Class.forName(“it.javajournal.Foo”);
Object foo = f.newInstance();
Un cocktail al gusto di caffè: nativo e bytecode
Class b =
Class.forName(“it.javajournal.Bar”); Adesso che abbiamo scoperto quanto è vantaggioso
Object bar = b.newInstance(); l’utilizzo delle librerie dinamiche, potremmo volerci
} spingere un passo più in là. Considerate lo scenario
} in cui una azienda esterna sviluppa un modulo per
File Foo.java il vostro software, ma non ha l’interesse o le cono-
package it.javajournal; scenze necessarie per fornire una versione nativa
class Foo{
dello stesso per tutte le piattaforme target. Sareste
public Foo(){
disposti a rinunciare al contributo di questa azien-
System.out.println(
“Questo è il modulo Foo”); da? Probabilmente no.
}
} Gcj ci viene in soccorso anche in questo caso, infatti
File Bar.java ci offre la possibilità di creare applicazioni miste,
package it.javajournal; in parte native e in parte interpretate. Il tutto in
class Bar{ modo assolutamente trasparente al programmatore/
public Bar(){ utilizzatore. Nel momento in cui gcj trova un riferi-
System.out.println( mento ad una classe esterna, per prima cosa ne cerca
“Questo è il modulo Bar”); una versione nativa e solamente nel caso questa non
} fosse disponibile tenta la strada dell’interpretazio-
}
ne.

LISTATO 2 Sorgenti della nostra applicazione e Per chiarirci le idee osserviamo il Listato 2, in cui
dei due moduli, Foo e Bar. Il primo verrà compilato in possiamo vedere un’applicazione che carica dinami-
bytecode, l’altro nativamente camente tramite Class.forName due moduli esterni,
dei quali uno verrà compilato nativamente, l’altro
tazione ottimizzata di gcj per l’accesso ai metodi nativi) in bytecode.
che sarebbe altrimenti utilizzato per default. Quest’ulti-
mo parametro non è influen-
te sul nostro esempio poiché
non viene fatto uso di metodi
nativi, ma in presenza di que-
sti è molto probabile che tale
opzione si renda necessaria.
Un eventuale omissione por-
terebbe ad avere diversi errori
in fase di linking.

Il punto 2 ricalca esattamen-


te la procedura seguita nel
primo esempio. Una volta
che entrambi i file sono stati
compilati bisogna eseguire il
linking:

gcj –main=HelloWorld -o
shello HelloWorld.o -lprinter

In questo modo viene creato


l’eseguibile shello, che, nel
momento in cui viene lan-
ciato, si aggancia alla libreria
libprinter.so usufruendo dei FIGURA 2 Eclipse compilato nativamente

n.1 - novembre/dicembre 2006 39


focus JAVA Journal

Avrete sicuramente notato il


fatto che all’atto della compi-
lazione di App non è specificata
nessuna libreria. Infatti dal
momento che ci avvaliamo
dei servizi di Bar mediante
Class.forName non è necessario
specificare al linker dove si tro-
va tale modulo. Nel momento
in cui gcj si trova di fronte al
metodo forName cerca una li-
breria dinamica, contenente la
classe desiderata, che segua il
pattern: lib-<percorso-completo-
del-package>-<NomeClasse>.
Se invece avessimo deciso di
essere più generosi nei dettagli,
avremmo potuto istruire gcj su
quale libreria utilizzare diretta-
mente all’atto della compilazio-
FIGURA 3 Applicazione demo creata con la libreria SwingWT ne, eliminando di conseguenza
il vincolo sul nome:
La compilazione in bytecode del modulo Foo si ottiene
banalmente con: gcj –main=it.javajournal.App
-o app it/javajournal.App.java -lBar
gcj -C it/javajournal/Foo.java
Grazie a questa aggiunta gcj è in grado di accorgersi
Per quanto riguarda Bar invece useremo le nozioni appre- subito che la classe desiderata si trova all’interno della
se poc’anzi per creare una libreria dinamica: libreria libBar.so.

gcj -shared -fPIC -o lib-it-javajournal-Bar.so In entrambi i casi la libreria si deve trovare all’interno
it/javajournal/Bar.java del path del linker, pena il lancio di un’eccezione Clas-
sNotFoundException , nel primo caso, o un errore in fase di
A questo punto passiamo alla compilazione del corpo compilazione nel secondo.
dell’applicazione:
Un compilatore non basta
gcj –main=it.javajournal.App -o app it/javajournal.App.java Gli strumenti necessari per sviluppare ed eseguire un
programma Java sono fondamental-
mente tre:

• un compilatore
• una Virtual Machine/Runtime
library
• le librerie contenti il codice fornito
con J2SE/J2EE

Le prime due componenti sono fornite


dal progetto Gcj, però manca ancora
un tassello... un tassello di enorme im-
portanza. Tutto quello di cui abbiamo
parlato finora si riduce ad un semplice
giochino, per quanto intrigante, se
non possiamo accedere alla vastissima
libreria che il linguaggio ci fornisce.

Gnu Classpath

Purtroppo il codice rilasciato dalla Sun


FIGURA 4 Alcuni widget offerti da SWT
è coperto da una licenza che non ne

40 n.1 - novembre/dicembre 2006


JAVA Journal focus

permette la redistribuzione con Gcj, rendendolo quindi Conclusioni


inadatto.
Gnu gcj è uno strumento flessibile e potente grazie al
Fortunatamente un altro progetto Gnu ha esattamente quale potrete sviluppare applicazioni che non richiedono
questo scopo: sviluppare una versione libera delle libre- una Virtual Machine per essere eseguite e nello stesso
rie che stanno alla base di J2SE. La percentuale delle tempo necessitano di un quantitativo minore di memo-
componenti implementate rispetto al JDK 1.4 può es- ria. Queste caratteristiche lo rendono particolarmente
sere controllato direttamente sul sito di Classpath (http: attraente agli sviluppatori di applicazioni embedded.
//www.gnu.org/software/classpath/); al momento in cui
scrivo questo articolo è circa il 98%. Il supporto agli statement e direttive di Java 1.4 è com-
pleto, mentre è attualmente in corso lo sviluppo per
Una delle mancanze più pesanti all’interno di Classpath è integrare anche le aggiunte fatte con Java 1.5. Questo
sicuramente Swing. Gli sforzi per raggiungere una imple- processo di integrazione si è protratto per lungo tempo
mentazione completamente funzionante sono molti, ma poiché è stato deciso di riscrivere da zero il frontend a
ci vorrà ancora un po’ di tempo prima di poter eseguire gcc in modo da rendere meno dispendiosa l’integrazione
una applicazione Swing complessa, come ad esempio futura di eventuali aggiunte al linguaggio.
NetBeans, tramite gcj+Classpath.
La sua natura libera (Gcj come tutti gli altri progetti della
È possibile comunque sviluppare applicazioni grafiche Gnu sono Free Software) ha anche il significativo vantag-
mediante le librerie SWT, che grazie alla loro natura open gio di avvicinare a Java molti sviluppatori della comunità
source, si prestano ottimamente alla compilazione nativa FOSS che fino ad oggi avevano evitato questo linguaggio,
ed in generale all’utilizzo con implementazioni libere di non per ragioni tecniche, ma di licenza.
Java.

Altre librerie utili

Altre librerie libere che vanno a completare il puzzle


sono:
• GNU ClasspathX: librerie aggiuntive a J2SE (Java-
Mail, JAXP, Activation Framework ecc). Note Biografiche
• Jessie: Java Secure Sockets Extension.
• GNU Crypto: cryptographic primitives. Andrea Zito è studente presso la facoltà di Scienze Informatiche
di Trento. È appassionato di Gnu/Linux e di software libero; da
• SwingWT: implementazione delle API Swing/AWT qualche anno usa Java come linguaggio principale per lavoro e
sopra la libreria SWT. per studio.

Gcj Binary Compatibility ABI Questo tool genera un file .db che mappa una versione
compilata di una classe, alla sua controparte in bytecode.
Alcune applicazioni sono scritte assumendo che verrano Durante la compilazione nativa, quando gcj incontra de-
eseguite solamente all’interno di una Virtual Machine, fineClass(), il bytecode passato viene confrontato (trami-
facendo assunzioni sull’ambiente in cui si trovano. Que- te la mappa contenuta nel file .db) con le librerie dinami-
sta pratica rende molto complicato compilare tali pro- che contenenti le classi native.
grammi nativamente, a meno di pesanti modifiche al co- Perché durante l’esecuzione gcj sappia quale file .db usare
dice sorgente. è necessario specificare tramite la proprietà gnu.gcj.preco
Nello specifico questi programmi contengono il codice per mpiled.db.path il percorso di quest’ultimo.
leggere stream di bytecode e caricarli come classi tramite il Grazie a questo meccanismo, gcj è in grado di utilizzare la
metodo ClassLoader.defineClass(). Un esempio molto cono- versione nativa della classe in questione, al solo costo di
sciuto di tali applicazioni, in cui praticamente tutte le com- mantenere anche la versione in bytecode.
ponenti sono caricate in questo modo, è Eclipse. Il flag -findirect-dispatch attiva l’ABI per la compati-
Il problema che questa pratica comporta a gcj è molto bilità binaria. Quest’ultima oltre ad essere necessaria
semplice: non esiste bytecode per una classe compilata per il funzionamento del meccanismo descritto poc’an-
nativamente e di conseguenza non è possibile creare uno zi, porta benefici a tutte le applicazioni, garantendone
stream da passare al ClassLoader. il funzionamento anche nel momento in cui venissero
Per ovviare a questo problema gcj v.4 ha introdotto una introdotti cambiamenti alla libgcj, senza bisogno di ri-
nuova modalità di compilazione, attivabile tramite lo swith compilare. In futuro diventerà il metodo di compilazio-
-findirect-dispatch ed un nuovo strumeto: gcj-dbtool. ne standard.

RIQUADRO 2 Introduzione all’ABI per la compatibilità binaria fornito con gcj 4

n.1 - novembre/dicembre 2006 41


focus JAVA Journal

Java ME
sviluppare applicazioni
per cellulari e PDA
Java Micro Edition (Java ME) è la piattaforma leader per lo sviluppo di applicazioni multidevi-
ce per telefoni cellulari, palmari e dispositivi embedded. Grazie ad una architettura modulare e ad
una ricca collezione di API opzionali, in soli 5 anni ha conquistato il mercato dei dispositivi mobili
e si appresta alla soglia del miliardo di terminali abilitati già in circolazione. In questo articolo in-
troduciamo questa affascinante tecnologia.
>> di Stefano Sanna (stefano.sanna@javajournal.it)

L
di unità vendute, 150 operatori di telefonia mobile e
più di 350 mila sviluppatori nel mondo supportano
a storia del linguaggio Java inizia nei la piattaforma, mentre mensilmente vengono scari-
primi anni ‘90, grazie ai risultati del cate sui telefonini 23 milioni di applicazioni.
brillante Green Project. L’obiettivo
della semplicità nella scrittura del
codice e di alta portabilità tra diverse Configurazioni e Profili
architetture hardware portarono alla
definizione del linguaggio Oak e alla Rispetto agli ambienti desktop e server, il mondo dei
realizzazione dell’innovativa piattaforma “*7” (la dispositivi mobili è straordinariamente vario. Nume-
prima applicazione di Java) . Inizialmente si mirava rose le combinazioni di sistemi operativi (proprietari
al settore della TV via cavo, ma quanto fino ad al- e non), piattaforme hardware, classi di dispositivi,
lora ottenuto apparve particolarmente efficace per mercati di riferimento: una architettura monolitica
risolvere un problema emergente, complice la ina- non potrebbe abbracciare un’offerta così vasta. Al
spettata e rapida diffusione del web: la possibilità fine di essere adattata al maggior numero di tipi di
di distribuire codice applicativo insieme alle pagine dispositivi, la piattaforma Java ME è organizzata in
web (codice embedded, ancora una volta!) con il livelli componibili e, in certa misura, intercambiabili.
requisito di avere portabilità tra diverse piattaforme In questo modo i produttori dei dispositivi possono
hardware (in teoria qualsiasi PC dotato di un web decidere, in base alle funzionalità supportate dal-
browser, all’epoca Netscape). Nacque Java e le Ap- l’hardware e agli obiettivi di mercato, quali livelli im-
plet: fu l’inizio di una nuova classe di applicazioni. plementare e, dunque, adattare il runtime Java. Tale
Negli anni successivi il linguaggio e la libreria stan- modularità è ottenuta attraverso una organizzazione
dard sono stati arricchiti, portando la tecnologia in Configurazioni, Profili ed API opzionali.
Java in ambiti quali le applicazioni desktop e i servi-
zi enterprise che sembravano appannaggio solo del
software scritto in codice nativo (C/C++). Proprio
in ambito server, invece, con la piattaforma J2EE,
Java ha dimostrato di essere una tecnologia estre-
La piattaforma
mamente potente, flessibile e robusta. Nel 2001 (6
anni dopo il rilascio delle prime specifiche Java)
Java ME è organizzata
vennero rese pubbliche le prime implementazioni di
CLDC e MIDP: nasceva la piattaforma Java2 Micro in livelli componibili e
Edition (J2ME), rinominata lo scorso anno Java
Platform, Micro Edition (Java ME). Il ritorno al intercambibili
settore embedded/consumer è un successo straordi-
nario e i numeri lo confermano: 650 modelli di ter-
minali Java ME compatibili, con più di 700 milioni

42 n.1 - novembre/dicembre 2006


JAVA Journal focus

FIGURA 1 Configurazioni, Profili e API opzionali di Java ME

Configurazioni: CDC e CLDC memorizzazione e connettività limitate, mentre l’alimen-


tazione è verosimilmente fornita da piccoli accumulatori.
La configurazione costituisce l’insieme minimo di fun- Da questa suddivisione scaturiscono le due configurazio-
zionalità esportate da una famiglia di dispositivi caratte- ni attualmente rilasciate: CDC (Connected Device Confi-
rizzati dal medesimo hardware di base. Qualche esempio guration) e CLDC (Connected, Limited Device Configu-
potrà chiarire meglio questa definizione. Si considerino i ration). La prima è destinata a equipaggiare dispositivi
seguenti dispositivi: un telefono cellulare entry-level, un dotati di memoria minima complessiva di 1MB, connet-
computer palmare di fascia alta, un piccolo cercapersone tività elevata e soprattutto hardware sufficientemente
tascabile, un decoder (detto anche set-top box) per la TV potente da poter eseguire una implementazione della
interattiva, un modulo embedded per il controllo remoto Virtual Machine standard. Viceversa, la CLDC destinata a
di un distributore di bibite, un sistema di navigazione dispositivi con memoria totale (ROM + RAM) di 512KB,
satellitare per auto. Ciascuno di questi oggetti svolge connettività limitata su canale a banda stretta, funzio-
una funzione ben precisa; ciononostante è possibile, con namento marcatamente discontinuo e interfaccia grafica
buona approssimazione, aggregarli in due gruppi caratte- ridotta; il runtime environment prevede una virtual ma-
rizzati da prestazioni hardware similari. Un primo gruppo chine dedicata e opportunamente ridotta. La configura-
comprende palmari, set-top box e sistema di navigazione: zione determina la ricchezza della libreria standard, la
questi dispositivi sono caratterizzati da una buona capaci- complessità del modello multithreading, la presenza di
tà di elaborazione, memorizzazione e connettività. Anche supporto per l’aritmetica in virgola mobile o per l’invo-
i requisiti di alimentazione sono abbastanza simili (gli cazione di metodi nativi (dunque la presenza della Java
utilizzatori di PDA sanno che l’autonomia delle batterie è Native Interface, JNI). Nel caso di CLDC, l’intera libreria
ancora un fattore critico). Il secondo gruppo comprende i standard (java.lang, java.io, java.util...) è notevolmente
cellulari (escludendo, dunque, i palmari con funzionalità semplificata (priva di float e double nella versione 1.0).
telefoniche), pager, sistemi embedded: questi dispositivi Questa configurazione ha introdotto il GCF (Generic
sono caratterizzati da modeste capacità di elaborazione, Connection Framework), una infrastruttura estendibile

n.1 - novembre/dicembre 2006 43


focus JAVA Journal

per l’implementazione del supporto alla connettività. Profile) e PP (Personal Profile). Presi nell’ordine, aggiun-
Esso permette di aggiungere il supporto a nuovi sistemi gono funzionalità sempre più complesse alla configura-
di comunicazione (ad esempio, Bluetooth o messaging) zione, a partire dalla GUI elementare di FP fino alla im-
senza che sia necessario modificare la gerarchia standard plementazione completa di AWT fornita da PP. Il Personal
delle classi e garantendo, entro certi limiti, massima com- Profile può essere riconosciuto, da chi (come l’autore) ha
patibilità delle applicazioni (Figura 1). lavorato fin dalle prima implementazioni di Java su PDA,
come il successore del PersonalJava, il primo tentativo
storico di realizzare un Java per dispositivi embedded.

I profili sono la
Panoramica di MIDP 2.0
specializzazione per uno
MIDP è il profilo supportato dalla maggior parte dei
specifico prodotto terminali in circolazione; in particolare, la versione 2.0
equipaggia la totalità dei modelli di nuova commer-
(o insieme di prodotti) cializzazione (di seguito si farà riferimento a questa
versione). MIDP fornisce il supporto alla connettività
via HTTP (requisito minimo), persistenza sulla memo-
ria del dispositivo, interfaccia grafica a componenti,
set minimale di classi per la riproduzione di contenuti
Profili: MIDP e gli altri multimediali, classi accessorie di supporto allo svilup-
po della grafica dei videogiochi (tali classi sono cono-
Mentre le configurazioni stabiliscono le caratteristiche sciute con il nome di Game API). Le classi specifiche
comuni a una certa famiglia di hardware, i profili sono la della piattaforma Java ME sono contenute nei package
specializzazione per uno specifico prodotto (o insieme di javax.microedition.*. La prima particolarità rispetto alla
prodotti). Sulla CLDC sono basati i profili MIDP e IMP. Il piattaforma standard è la gestione del ciclo di vita delle
profilo MIDP (Mobile Information Device Profile) è desti- applicazioni. Queste sono chiamate MIDlet e sono ge-
nato ad equipaggiare telefoni cellulari e computer palma- stite dall’Application Manager del dispositivo, respon-
ri di classe consumer. Il profilo IMP (Information Module sabile della installazione, rimozione, avvio, sospensione
Profile), viceversa, è destinato al mercato dei controllori e interruzione di ciascuna applicazione. L’interfaccia di
embedded avanzati; esso, dunque, è destinato ad essere gestione dell’Application Manager dipende dal disposi-
installato in macchinari e strumenti per i quali siano tivo in uso mentre l’interazione con la MIDlet è gestita
necessarie funzionalità di programmabilità, elaborazione attraverso l’invocazione del costruttore e di tre metodi
di segnali analogici e digitale, controllo di attuattori (ad accessori. Il costruttore della MIDlet viene invocato al
esempio, motori) e soprattutto di connettività su rete IP primo caricamento dell’applicazione, mentre all’avvio
(generalmente attraverso rete telefonica GPRS). Si può vero e proprio l’Application Manager invoca il metodo
pensare a IMP come ad una specializzazione di MIDP, in startApp(). Questo metodo potrebbe essere invocato più
cui è stata eliminata la sezione dedicata all’interfaccia volte durante la vita dell’applicazione: in caso di neces-
grafica (generalmente inutile o comunque sostituita da sità, infatti, l’Application Manager potrebbe richiedere
hardware dedicato) e aggiunta la gestione degli input e all’applicazione di sospendere l’esecuzione (attraverso
output analogici e digitali. Su CDC si basano attualmente l’invocazione del metodo pauseApp()) per poi riprenderla
tre profili: FP (Foundation Profile), PBP (Personal Basis in seguito. Infine, l’invocazione del metodo destroyApp()

FIGURA 2 Il ciclo di vita di una MIDlet

44 n.1 - novembre/dicembre 2006


JAVA Journal focus

segnalerà che l’utente ha richiesto esplicitamente la


package it.javajournal.talktimer;
chiusura dell’applicazione (Figura 2).
import javax.microedition.midlet.*;
L’interfaccia grafica è costituita da una gerarchia di Di-
import javax.microedition.lcdui.*;
splayable, visualizzati alternativamente da un Display, a
cui la MIDlet è associata. Tra i Displayable vi sono i Form,
public class TalkTimer extends MIDlet {
ai quali è possibile aggiungere componenti quali Text-
TalkTimerEngine gui;
Field, radio button, slider; vi sono diversi tipi di liste e la
classe Canvas, che ricorda l’omonima presente in AWT.
public TalkTimer() {
Le classi di MIDP permettono la gestione dei softbutton,
gui = new TalkTimerEngine();
generalmente situati alla base del display del terminale,
gui.display =
attraverso oggetti Command assimilabili ai MenuItem
Display.getDisplay(this);
della piattaforma standard. Un’altra caratteristica pecu-
}
liare di MIDP è relativa al rilascio delle applicazioni, che
possono essere aggregate in Suite, all’interno della quale
public void startApp() {
le MIDlet condividono le classi e le informazioni memo-
Display.getDisplay(this).setCurrent
rizzare sul servizio di persistenza. Il rilascio dell’applica-
(gui);
zione consiste nella coppia di file JAR e JAD. Il file JAR,
}
come consuetudine, contiene le classi dell’applicazione e
delle librerie accessorie, eventuali file di property e altre
public void pauseApp() { }
risorse. Il file JAD (Java Application Descriptor) è un
file di testo contenente informazioni sull’applicazione:
public void destroyApp(
URL e dimensione del file JAR, nome e classe di avvio
boolean unconditional) { }
di ciascuna MIDlet, property per l’avvio dell’applicazione
e soprattutto contiene indicazioni su configurazione e
} profilo minimi necessari per l’esecuzione. L’applicazione
d’esempio di questo articolo ha il JAD file che segue:
LISTATO 1 TalkTimer introduzione

FIGURA 3 Il TalkTimer in esecuzione nel Wireless Toolkit, nella Nokia Developer’s Suite e su Windows Mobile 2003
(attraverso remote display)

n.1 - novembre/dicembre 2006 45


focus JAVA Journal

MIDlet-1: TalkTimer, TalkTimer.png, it.javajournal stione fornito dal produttore del terminale (dunque con
.talktimer.TalkTimer il supporto di un PC), via Bluetooth o Infrarossi (tecni-
MIDlet-Jar-Size: 3528 camente detto OBEX Push, modalità non supportata da
MIDlet-Jar-URL: TalkTimer.jar tutti i terminali).
MIDlet-Name: TalkTimer
MIDlet-Vendor: My Company
MIDlet-Version: 1.0
La prima applicazione Java ME
MicroEdition-Configuration: CLDC-1.0
MicroEdition-Profile: MIDP-2.0 Le classi di MIDP 2.0 permettono di realizzare appli-
cazioni di media complessità, dotate di supporto alla
Attraverso queste informazioni, prima di scaricare il file connettività HTTP, persistenza sul dispositivo e grafica in
JAR, l’Application Manager può determinare la com- movimento. Per prendere confidenza con la piattaforma
patibilità del runtime e segnalare all’utente eventuali Java ME è sufficiente scrivere una MIDlet semplice ma
anomalie. Ad esempio, una applicazione basata su CLDC efficace. Si vuole realizzare un semplice timer (TalkTi-
1.1 (con supporto dell’aritmetica in virgola mobile), non mer), da utilizzarsi, ad esempio, durante un seminario:
verrà eseguita su un dispositivo CLDC 1.0. Il file JAD vie- il relatore, all’inizio della presentazione avvierà l’appli-
ne creato automaticamente dai tool di sviluppo Java ME; cazione, impostando la durata del proprio intervento.
essi provvedono anche a replicare le informazioni del file Durante l’esposizione potrà verificare sul display il tempo
JAD all’interno del file MANIFEST del JAR (con l’esclu- a sua disposizione e al termine di quest’ultimo un segnale
sione dell’URL di quest’ultimo). sonoro lo avviserà. La classe di avvio, TalkTimer, estende
MIDlet e inizializza la classe TalkTimerEngine, responsa-
L’installazione dell’applicazione sul dispositivo può avve- bile della gestione dell’interfaccia grafica e del timer vero
nire con diverse modalità: attraverso download via web/ e proprio (Listato 1)
wap (detto OTA, Over-The-Air, che indica il trasferimento
effettuato su canale radio), per mezzo del software di ge- Nel costruttore viene istanziata la classe responsabile

API Descrizione
Wireless Messaging API 1.1 e 2.0 (WMA, Permette l’invio e la ricezione di brevi messaggi, sia in
JSR 120, 205) formato testo che binario. Probabilmente è l’API opzionale
maggiormente diffusa, anche su modelli entry-level (WMA
2.0 solo su terminali di fascia alta).
Mobile Media API (MMAPI, JSR 135) Fornisce il supporto base per la riproduzione e l’acquisizione
di contenuti multimediali audio e video.
Mobile 3D Graphics (M3G, JSR 184) Implementa una ricca libreria per la grafica 3D. Sono stati
annunciati cellulari con accelerazione hardware per la M3G.
Java APIs for Bluetooth (BTA, JSR 82) Fornisce i meccanismi per il discovery di device e servizi
Bluetooth. OBEX e SPP tra i servizi supportati.
Location API (JSR 179) Permette lo sviluppo di applicazioni basate sulla posizione,
con una interfaccia astratta verso sistemi di localizzazione
mobile e gestione landmark.
FileConnection & PIM API (JSR 75) Si tratta di funzionalità opzionali ereditate dal PDAP
(Pda Profile), che avrebbe dovuto affiancare MIDP nel
supporto Java su palmari e telefoni hi-end. In realtà PDAP
non vide mai la luce e dalla specifica rimasero questi due
importantissimi package, che forniscono supporto ai servizi
di Personal Information Management (PIM) e al file system
del dispositivo.
Scalable 2D Vector Graphics API (JSR 226) Fornisce supporto alla gestione e visualizzazione di file SVG.
Web Service API (WSA, JSR 172) Implementa le funzionalità di parsing XML e invocazione
di metodi remoti su interfaccia Web Service conforme alle
specifiche WS-I Basic Profile 1.0

TABELLA 1

46 n.1 - novembre/dicembre 2006


JAVA Journal focus

package it.javajournal.talktimer; // timer


timer = new Timer();
import javax.microedition.lcdui.*; timerTask = new TimerTask() {
import java.util.Timer; public void run() {
import java.util.TimerTask; counter -= 1;
import javax.microedition.media. timerItem.setText(
Manager; Integer.toString(counter));
if (counter == 0) {
public class TalkTimerEngine alarm();
extends Form this.cancel();
implements CommandListener { }
}
Display display; };
}
private TextField timerField; public void commandAction(
private StringItem timerItem; Command c, Displayable d) {
private Command startCommand; if (c == startCommand) {
private Command stopCommand; delete(0);
private int counter; append(timerItem);
counter = Integer.parseInt(
private Timer timer; timerField.getString());
private TimerTask timerTask; timer.schedule(
timerTask, 1000, 60000);
public TalkTimerEngine() { } else if (c == stopCommand) {
super(“TalkTimer”); timer.cancel();
init(); delete(0);
} append(timerField);
}
private void init() { }
// gui private void alarm() {
startCommand = new Command( try {
“Start!”, Command.SCREEN, 1); Manager.playTone(0x45, 500, 100);
stopCommand = new Command } catch(Exception e) {
(“Stop!”, Command.SCREEN, 2); // non essendo possibile riprodurre
addCommand(startCommand); // un suono, mostriamo un Alert
addCommand(stopCommand); Alert alert = new Alert(
setCommandListener(this); “Attenzione!”, “Tempo scaduto”,
timerField = new TextField( null, AlertType.ALARM);
“Durata (minuti):”, “”, display.setCurrent(alert, this);
2,TextField.NUMERIC); }
timerItem = new StringItem( }
“Time:”, “”);
append(timerField); }

LISTATO 2 TalkTimerEngine

della gestione dell’interfaccia grafica, mentre la visua- con metodi per la sospensione e la ripetizione ciclica
lizzazione avviene all’interno del metodo startApp(). Il temporizzata di blocchi di codice (contenuti all’interno
metodo setCurrent() del display assegnato alla MIDlet del classico metodo run()). Il metodo commandAction(),
permetterà la visualizzazione del Form iniziale. Quest’ul- definito nell’interfaccia CommandListener, è invocato dal
timo è implementato dalla classe TalkTimerEngine (visi- runtime alla pressione di un bottone del cellulare (det-
bile in Listato 2), la quale gestisce gli eventi della gui ed to softbutton) assegnato al Command. La selezione del
è incaricata dell’avvio e arresto del timer. Il metodo init() Command “start” provoca l’assegnazione del TimerTask
provvede a istanziare i componenti e assemblare l’inter- definito nel metodo init() all’interno dello scheduler del
faccia grafica del Form (Listato 2). Timer. Ogni 60 secondi, il Task verificherà se è trascorso il
tempo a disposizione ed eventualmente, attraverso il me-
All’interno dello stesso metodo si definisce un Timer- todo alarm(), notificherà all’utente il timeout attraverso
Task: questo, unito alla classe Timer, costituisce una l’emissione di un breve tono (Figura 3).
specializzazione delle classi Thread e Runnable, arricchiti

n.1 - novembre/dicembre 2006 47


focus JAVA Journal

Le API opzionali sviluppo integrato permette di aumentare la produttivi-


tà attraverso editor avanzati (con evidenziazione della
Quanto descritto finora rappresenta una frazione delle sintassi, autocompletamento dinamico del codice, assi-
potenzialità di Java ME. La grande forza della piatta- stenza alla correzione degli errori più comuni), gestione
forma risiede nelle API opzionali, che arricchiscono il dei progetti e delle librerie, integrazione con il Wireless
runtime Java di funzionalità base e avanzate. Alcune Toolkit e emulatori di terze parti, supporto al deployment
librerie sono da tempo a corredo della maggior parte dei automatico su server remoto e a configurazioni multiple
dispositivi (ad esempio, la gestione degli SMS), altre sono per dispositivi diversi. Netbeans, Eclipse, IDEA, JBuilder,
presenti solo su modelli di fascia alta (ad esempio, il sup- solo per citarne alcuni, offrono apposite estensioni per lo
porto completo a Bluetooth), altre ancora sono appena sviluppo in ambiente Java ME. In ambito CDC/PP è da
state rilasciate e si attende l’imminente apparizione dei segnalare l’ottimo WebSphere Device Developer proposto
modelli di prossima commercializzazione. In tabella sono da IBM, che include anche i runtime environment per
riportate alcune delle API più significative (Tabella 1): Windows Mobile e Linux. In realtà, lo sviluppo di appli-
cazioni CDC/PP è, per diversi aspetti, meno critico ed è
Sul sito del Java Community Process sono attualmente possibile utilizzare strumenti standard (non è necessaria
elencate 79 Java Specification Request, a conferma della la preverifica). Ciononostante, i produttori di dispositivi
vivacità che ruota attorno al mondo Java ME. stanno iniziando a rilasciare documentazione e tool spe-
cifici, che tengano conto delle particolarità che ciascun
modello introduce rispetto alla piattaforma ufficiale.
Strumenti di sviluppo

Per affrontare lo sviluppo di applicazioni per dispositivi

Le
Java ME è necessario utilizzare strumenti dedicati. Ri-
spetto a Java SE, le applicazioni per dispositivi mobili, applicazioni mo-
prima di essere distribuite, passano attraverso un pro-
cesso di preverifica; questo è operato dalla Java Virtual bile, prima di essere di-
Machine standard in fase di esecuzione, mentre in ambi-
to MIDP le ridotte prestazioni dei dispositivi impongono
che parte della verifica del bytecode sia effettuata prima
stribuite, passano per un
del rilascio definitivo. Il runtime Java effettua comunque
dei controlli, anche se meno onerosi e complessi della
processo di preverifica
preverifica. Il passo successivo è l’esecuzione all’interno
di un emulatore, che permette una prima valutazione
dell’applicazione e facilita il debugging. Per CLDC/MIDP
Sun Microsystems fornisce il Java Wireless Toolkit
(WTK), una collezione di tool a linea di comando e una Conclusioni
utility grafica per la compilazione, preverifica e packaging
dell’applicazione. Per realizzare una nuova applicazione è Dal 2001 ad oggi la piattaforma Java ME è cresciuta no-
sufficiente creare un nuovo progetto e indicare il nome tevolmente sia per numero di terminali installati (siamo
(completo di package) della MIDlet. Il WTK associa una prossimi al miliardo di unità!) che per la ricchezza del
directory all’interno del proprio repository, contenuto runtime environment con tutte le API opzionali. Questa
nella directory ROOT_WTK\apps (ROOT_WTK è la car- maturità permette agli sviluppatori di realizzare applica-
tella di installazione del WTK). Il codice sorgente deve zioni a supporto della totale mobilità degli utenti, con
essere salvato nella sottodirectory src, mentre risorse e ricco supporto alla connettività (messagging, Bluetooth,
librerie opzionali troveranno collocazione rispettivamen- IP su rete telefonica e WiFi, web service). Dal 2006 sono
te in res e lib. Attraverso i menù BUILD, RUN e CREATE annunciate nuove API e dispositivi dalle prestazioni ele-
PACKAGE è possibile compilare il codice, eseguirlo all’in- vatissime: l’auspicio è quello di avere una nuova classe di
terno dell’emulatore standard e creare i file JAD e JAR per applicazioni a supporto della mobilità degli utenti consu-
il deployment finale. mer, fortemente connesse e georeferenziate.

All’emulatore fornito con il WTK si affiancano quelli


dedicati forniti dai produttori dei modelli in commercio.
Nokia, Sony-Ericsson, Motorola, Samsung, Benq (che ha
recentemente acquisito la divisione telefonia mobile di Note Biografiche
Siemens) offrono apposite sezioni dedicate agli sviluppa- Stefano Sanna si occupa di sviluppo di applicazioni multime-
tori nei propri siti web, con software, librerie, documen- diali per piattaforma Savaje presso Beeweeb Technologies (http:
//www.beeweeb.com). Ha lavorato per sette anni nel gruppo
tazione e articoli di approfondimento. Network Distributed Applications del CRS4, occupandosi di
mobile computing e applicazioni network-oriented per cellula-
Gli strumenti a linea di comando e gli emulatori sono ri e PDA. Collabora attivamente con JIA, JUG Sardegna e Java
Mobile Developers Forum. Il sito sito web personale e’
il minimo indispensabile per intraprendere lo sviluppo http://www.gerdavax.it
di una applicazione Java ME. Adottare un ambiente di

48 n.1 - novembre/dicembre 2006


JAVA Journal educational

Java 5, le buone
nuove e le novità
meno buone
prima parte
Scrivere nel 2006 un articolo sulle novità di Java5 può sembrare un po’ fuori tempo massimo, poi-
ché Sun ha presentato questa release nel 2004, e Java6 è ormai dietro l’angolo. Ma ci sono da tenere
in considerazione diversi aspetti che giustificano questo argomento.

>> di Ugo Landini (ugo.landini@javajournal.it)

V
fidabilità, mantenendo la compatibilità all’indietro.
ediamo dunque perché trattare le novità Particolare attenzione in questa release è stata posta
di Java5: sull’incremento delle performance: alcuni obiettivi
• le novità introdotte in Java5 non sono iniziali sono invece stati parzialmente rischedulati
state ancora ben digerite da molti svilup- per Java6. L’obiettivo di questo articolo invece è pas-
patori. Per lavoro mi capita di vedere molto codice sare in rassegna le novità, con un accento particolare
Java scritto da altri, ed è comune – molto comune - su quelle che hanno fatto meno clamore.
imbattersi in idiomi ormai resi obsoleti dalle nuove Possiamo raggruppare le novità con l’ausilio della
versioni del linguaggio. Di fatto, spesso non vengo- Tabella 1. Ovviamente la tabella è riduttiva, ci sono
no utilizzate neanche le features di Java 1.4 (per i centinaia di cambiamenti (più o meno piccoli) nelle
non avvezzi alle simpatiche regole del marketing, API e nei tool di supporto [ENHANCEMENTS]. Però
java 1.4 è la release precedente a java5) ce n’è già abbastanza per scrivere un articolo e lascia-
• un cambiamento così grande (mi piacerebbe usare re fuori un sacco di dettagli! Prima di soffermarci sui
l’aggettivo epocale, ma suonerebbe troppo sensa- vari cambiamenti, assicuratevi di usare il compilatore
zionalista) non c’era mai stato e non ci dovrebbe passandogli lo switch per il sorgente 1.5 (-source 5),
mai più essere: il nuovo processo di rilascio delle su alcune “vecchie” versioni di javac il default per
versioni di Java e la relativa tempistica – circa 2 questo switch era ancora 1.4.
anni per major release - rende improbabile cambia-
menti drastici da una release all’altra. Da java 1.4 a Generics
Java5 sono infatti passati ben 4 anni.
• Diversi cambiamenti sono argomento di discus- Sicuramente è la novità apparentemente più impor-
sione giornaliero sui forum. Per molti di essi non tante, e quella sulla quale se ne è scritto di più. È
c’è ancora una chiara posizione della comunità: le anche uno dei costrutti più complessi e meno cono-
Annotations API sono effettivamente utili o peg- sciuti, con molti “angoli bui”
giorano il design? In sostanza, i generics non sono altro che una tecnica
• Java6 non introdurrà nessun cambiamento parti- per ottenere una maggiore type safety in java. In un
colare, ma apporterà solo miglioramenti a diverse linguaggio strongly typed come java, questo non può
API, concentrandosi in particolare sul Desktop. che essere un bene. Usando infatti le nuove tecniche
Java5 ha introdotto nuove keyword nel linguag- si risparmieranno molti cast ed il codice sarà teori-
gio e anche nuove api che rendono praticamente camente più robusto. Uso “teoricamente” perchè
obsolete alcune parole chiave (si pensi alle nuove personalmente non mi è mai capitato un bug dovuto
concurrent api, per esempio) all’inserimento in una collection di un oggetto erra-
Penso di essermi giustificato abbastanza, per cui to, ma diamo atto che un controllo in più fatto dal
passiamo in rassegna le novità. L’obiettivo principale compilatore non può che essere un buon controllo.
del team di Java5 è stato quello di migliorare la leggi- “Making Java easier to type and easier to type”, re-
bilità del codice e aumentarne allo stesso tempo l’af- citava con un simpatico gioco di parole lo slogan di

n.1 - settembre 2006 49


educational JAVA Journal

people.add(“Luca Landini”);
Pizza/GJ [PIZZA], il precursore dei generics in Java5. // ...
È vero infatti che per anni una parte della comunità Java String luca = people.get(2);
ha lamentato l’assenza dei generics (e proprio per questo
qualcuno sentì la necessità di creare Pizza/GJ), mentre Come si vede chiaramente dal codice, non c’è più bisogno
un’altra parte ne ha sempre osteggiato l’inserimento, fa- di fare un cast dopo il get(). È infatti garantito che nella
cendo presente soprattutto la complessità e la macchinosi- collection people ci siano solo delle String, ed un tentativo
tà dei template in C++. James Gosling è sempre stato con- di inserimento di un oggetto del tipo sbagliato sarebbe
trario, ma questa è proprio la dimostrazione che il processo individuato addirittura in fase di compilazione (e non a
che guida l’evoluzione della piattaforma Java (Java Com- runtime).
munity Process, JCP) è abbastanza democratico, oppure è
la dimostrazione che Gosling sta perdendo smalto).
Sia come sia, in Java5 queste feature sono lì e non possono
essere ignorate, soprattutto perchè le API sono state tutte
genericizzate, quindi perlomeno bisogna avere una qualche
Peranni una parte
confidenza con esse. Fra l’altro nell’implementazione che è
stata poi scelta, hanno molto poco a che vedere con quanto della comunità Java ha
a disposizione in C++.
lamentato l’assenza dei
// ...
List people = new ArrayList(); generics
people.add(“Ugo Landini”);
people.add(“Diego Landini”);
people.add(“Luca Landini”);
// ... Poniamo ad esempio che si provi ad inserire uno StringBui-
String diego = (String)people.get(1); lder invece di una Stringa: il compilatore si lamenterebbe
poichè non riuscirebbe a trovare il metodo add(StringBuilder)
Questo codice è ormai legacy, sostituito dal codice seguente all’interno dell’interfaccia List! A questo punto le doman-
de sorgono spontanee... come fa a funzionare? Il metodo
// ... add() di List non accettava Object come parametro? Esi-
List<String> people = new ArrayList<String>(); ste una classe List<String> con un add(String) ed una
people.add(“Ugo Landini”); List<StringBuilder> con un add(StringBuilder)? Come è
people.add(“Diego Landini”); possibile?

Cambiamento Costrutto/Tool Scopo


• Semplificazione della gestione delle Collections
Linguaggio Generics
• Sicurezza del codice
Linguaggio Nuovo ciclo for • Semplificazione della gestione delle Collections
Linguaggio Autoboxing • Semplificazione del codice
• Gestione standardizzata di insiemi di oggetti
Linguaggio Enumeration
• Sicurezza codice
Linguaggio Varargs • Soprattutto semplificazione nel porting di codice C
Linguaggio Static import • Migliorare la leggibilità del codice
Linguaggio Covarianza • Più espressività, migliore modellabilità
API printf • Soprattutto semplificazione nel porting di codice C
API java.util.scanner • Semplificare l’IO
• Maggiore integrazione con XML
API xml bundling
• Supporto web services integrato in Java
• Semplificare la creazione di codice multithreaded
API Concurrent API
• Aumentare le performance del codice multithreaded
• Migliorare lo startup della virtual machine
Sistema Class sharing
• Diminuire il footprint
• Semplificare il troubleshooting di applicazioni java
attraverso l’inserimento nella distribuzione Java di
Sistema Troubleshooting
nuovi tool e/o tool che precedentemente dovevano
essere scaricati separatamente

TABELLA 1

50 n.1 - settembre 2006


JAVA Journal educational

Per padroneggiare questo meccanismo, è necessario ca- può fare con il tipo. Ad esempio, essendoci una sola classe,
pire come si dichiara un tipo parametrico, e come viene i metodi statici – che appartengono alla classe e non alle
compilato di conseguenza il bytecode. Si vedrà che quella istanze - non possono usare il tipo in alcun modo!
complessità che è in qualche modo sparita dal codice che La cosa interessante sull’implementazione di questa fea-
utilizza le collection - il codice client - in qualche modo si è ture è che praticamente il compilatore non fa altro che
spostata nel codice delle classi server. Anzi, a dir la verità, utilizzare Object e fare il cast al posto vostro, mentre la VM
il totale di complessità in qualche modo è aumentato... non sa neanche dell’esistenza dei generics! Questa tecnica
ma andiamo a vedere il sorgente di List per capire un po’ si chiama erasure, poiché il compilatore cancella tutte le
meglio: informazioni di tipo dalle classi genericizzate, cosicché
List<String> di fatto diventa List, <E> diventa Object, e
public interface List<E> extends Collection<E> { così via. Infarcendo il bytecode con un po’ di cast, il gioco
// ... è fatto.
boolean add(E o); Questa scelta implementativa, che è stata necessaria per
E get(int index); non stravolgere le VM esistenti, porta con sé però diversi
// ... problemi, e ci sono molte situazioni in cui capire esatta-
} mente cosa succede, non è per nulla semplice, anche per
i più esperti.
La prima cosa che salta all’occhio è che List ora è diventato
List<E>, leggasi una lista di E. E rappresenta il tipo di ele-
mento che può essere gestito da List, ed è un tipo generico. Type Variable Significato
E si chiama Type Parameter o Type Variable, ed è l’iniziale
E Element
di Element, ed anche se si può usare qualsiasi lettera al
suo posto è una scelta piuttosto comune. Si dirà: ma non K Key
bastava Object? Cosa è cambiato? V Value
È cambiato che per costruire un oggetto List ora si può dire T Type
al compilatore quale tipo deve sostituire al posto di E, e da
quel momento in poi l’oggetto sarà una lista di String, come TABELLA 2
nell’esempio di prima, e non più una lista qualsiasi. Nota: è
ovviamente possibile e perfettamente legale istanziare una
List non parametrizzata, altrimenti tutto il codice pre Java5 L’argomento è molto vasto (troppo?) e non si esaurisce
diventerebbe di colpo illegale! certo in queste poche righe: argomenti come i bounded
Per capire meglio, immaginate che il tipo sia un parametro type, i generic nested types, gli wildcard, il subtyping ed
da passare ad un metodo,: altri hanno bisogno di un certo sforzo di apprendimento e
di un po’ di pratica per essere padroneggiati, senza contare
• List<E> è una dichiarazione generica di tipo, equivalen- gli angoli oscuri a cui abbiamo appena accennato. Quello
te al nome di un metodo che abbiamo visto è l’assoluto minimo che bisogna sapere
• E è il parametro di tipo, equivalente al tipo del parametro sui generics per non cadere dalle nuvole di fronte a del
di un metodo codice Java5!
• List<String> fornisce un argomento al tipo, in questo
caso String, equivalente all’effettivo valore del parametro Nuovo ciclo for (enhanced for)
nella chiamata di un metodo
Questo nuovo costrutto, insieme ai generics, è quello sicu-
La prima lezione da imparare sui tipi generici è quindi che ramente più invasivo: volente o nolente, prima o poi con
List<String> e List<StringBuilder> non sono due differenti Java5 vi troverete ad usare la nuova sintassi e ad apprez-
classi, ma semplicemente due diverse istanze della stessa zarne le qualità. Niente di trascendentale, ma sicuramente
classe a cui è stato passato un diverso tipo come parame- una maggiore sinteticità e leggibilità, soprattutto quando
tro. combinato con i generics.
Questo può apparire contro intuitivo perché siamo abituati Dal punto di vista teorico, esistono due tipi di iteratori,
a considerare tutto ciò che è a sinistra dell’identificatore esterni ed interni (Booch li definisce attivi e passivi, rispet-
in una dichiarazione come il suo tipo: la difficoltà è che to al ruolo che ha il client). Un iteratore è chiamato esterno
bisogna imparare a leggere le parentesi angolari come se quando è il client che ha il controllo del suo avanzamento
fossero le parentesi tonde di un metodo, e ricordarsi che (attivo), mentre uno interno (passivo) controlla da sé l’ite-
con Java5 è possibile parametrizzare una classe passando- razione. Gli iteratori “classici” di Java sono esterni: tipica-
gli dei valori. In questo modo la classe sarà più specifica, e mente un iteratore esterno offre una maggior flessibilità
funzionerà solo con quel determinato tipo che gli è stato di uno interno poiché si ha un controllo più fine sull’itera-
passato in fase di dichiarazione: l’oggetto people dell’esem- zione, ed in effetti ci sono dei problemi difficili da risolvere
pio è una Collection che accetta solamente Stringhe e non solamente con iteratori interni: basti pensare al confronto
più oggetti qualsiasi. degli elementi di due liste per rendersene conto.
Questa lezione è di fondamentale importanza: c’è una sola È però vero che l’iteratore interno è molto più conciso ed
classe, indipendentemente dal numero di parametri di elegante nella stragrande maggioranza dei casi! E basta un
tipo, e questo limita fortemente cosa si può e cosa non si esempio per rendersene conto.

n.1 - settembre 2006 51


educational JAVA Journal

utilizzando le Collection e confrontando il nuovo codice


// ... con il vecchio ne possiamo apprezzare l’utilità
List people = ...
for (String person: people) { //...
System.out.string(name); List numeri = new ArrayList();
} numeri.add(new Integer(1));
numeri.add(new Integer(2));
I due punti vanno letti come “in”, dunque qualcosa di si- numeri.add(new Integer(3));
mile a “per ogni person in people”, che è ovviamente molto //...
più leggibile e conciso dell’equivalente con iteratore ester- int due = ((Integer)numeri.get(2)).intValue();
no. diventa infatti molto più semplice e leggibile
Come nell’esempio precedente, il nuovo for da il mas- //...
simo di sé quando unito ai generics, ma è comunque List numeri = new ArrayList();
molto flessibile e permette anche di iterare su semplici numeri.add(1);
array: numeri.add(2);
numeri.add(3);
// ... //...
String[] names = {“Ugo”, “Diego”, “Luca”}; int due = numeri.get(2);
for (String name: names) {
System.out.println(name); Tutto qui, l’autoboxing/unboxing rende di fatto intercam-
} biabili i tipi base e i corrispettivi wrapper. Ma attenzione!
La cosa da ricordare è che la distinzione fra i tipi base e gli
A voler essere pignoli, sarebbe stato bello fare il passo com- oggetti è ancora lì, solo che ora è nascosta: si badi bene
pleto ed avere anche la possibilità di definire dei blocchi, dunque a non usare un Integer come indice in un lungo
ossia delle porzioni di codice da “passare” al ciclo e che po- ciclo, magari nidificato. Il fatto che compili e che funzioni
tessero essere eseguite sui singoli elementi, ma non si può non implica che sia la migliore soluzione. Da questo punto
avere tutto e per ora ci accontentiamo del nuovo for e della di vista, il boxing e l’autoboxing sono decisamente perico-
possibilità di scegliere fra iteratori esterni ed interni. losi! Basta osservare questo piccolo esempio per renderse-
ne conto:
Autoboxing/unboxing
// ...
Questa nuova feature aggiunge un po’ di zucchero sintat- long before = System.currentTimeMillis();
tico a Java. All’osso, rende il seguente codice compilabile e int x = 0;
perfettamente funzionante: for (int i=0; i<10000000; i++) {
x = x + i;
}
System.out.println(System.currentTimeMillis() - before);

L’autoboxing/ before = System.currentTimeMillis();


x = 0;
unboxing rende di fatto for (Integer i=0; i<10000000; i++) {
x = x + i;
intercambibili i tipi base }
System.out.println(System.currentTimeMillis() - before);

e i corrispettivi wrapper Il secondo ciclo è circa 20 volte più lento, questo per via
di tutte le conversioni automatiche (sia boxing che unbo-
xing) che vengono eseguite ad ogni iterazione.
Ovviamente non ci si limita ai tipi numerici, ed ora potrete
anche scrivere:
Integer i = 0;
Boolean vero = true;
Dietro le quinte, il compilatore si occupa delle necessa- Boolean expression = exp1 && exp2 || exp3
rie conversioni fra tipo base ed oggetto, che da sempre
tormentano i programmatori Java. Questa conversione Un ultimo dettaglio: il boxing/unboxing non avviene per la
da tipo primitivo ad oggetto wrapper è chiamata boxing risoluzione di metodi in overload, ma continuano a valere
e, visto che succede in automatico, la feature è chiamata le regole pre-Java 1.5. Questo per non variare il compor-
autoboxing, mentre l’operazione opposta - da oggetto tamento di programmi compilati per versioni precedenti.
wrapper a tipo primitivo - è chiamata unboxing (senza Considerate infatti cosa accadrebbe se il boxing fosse ap-
auto, chissà perché). plicato in una situazione simile:
Ovviamente questo semplice esempio non rende l’idea, ma

52 n.1 - settembre 2006


JAVA Journal educational

// ...
public void doSomething(double num); sere un sottotipo o un supertipo. Per un linguaggio object
public void doSomething(Integer num); oriented, se sia meglio avere tipi covarianti o controvarian-
ti è una scelta di design che è ancora argomento teorico di
//... dibattito: noi ce ne terremo lontani (Tabella 3).
int x = 1; Possiamo avere invarianza, covarianza o controvarianza
doSomething(1); per i tipi di ritorno di un metodo, per i suoi parametri, o
per le eccezioni che lancia.
Per Java 1.4, verrebbe invocato il primo metodo, mentre
per Java 1.5 verrebbe invocato il secondo per via
dell’autoboxing!
Tipo Relazione con il
supertipo
Static import Invarianza Non cambia
Covarianza Può essere un sottotipo
Lo static import è fortunatamente una delle novità più
semplici da imparare.
TABELLA 3
Questa novità permette semplicemente di “importare”
variabili e metodi statici, in modo da poterli eseguire
direttamente senza il nome della classe. Anche questa Un esempio di covarianza pre-Java5 sono le eccezioni:
quindi è una feature più di forma che di sostanza, e serve l’override di un metodo che lanci eccezioni è tenuto
per risparmiare qualche carattere e scrivere codice più a lanciare eccezioni in maniera covariante: le stesse,
leggibile: o dei sottotipi, A voler essere precisi può anche non
lanciarne nessuna (ma così mi si rovina l’esempio): co-
import static java.lang.System.out; munque, se il metodo lancia eccezioni, queste devono
// ... essere covarianti.
out.println(“Hello, world!”); Discorso diverso invece per i parametri di un metodo, che
sono invarianti: scrivere questo codice
ma anche
public class Base {
import static java.lang.Math.*; public void uno(CharSequence sequence) {
import static java.lang.System.out; System.out.println(“Base.print “ + sequence);
// ... }
out.println(PI); }

oppure public class Derived extends Base {


public void print(String string) {
import static Collection.copy; System.out.println(“Derived.print “ + string);
// ... }
copy(from, to); public static void main(String[] args) {
Base b = new Derived();
Non ne fate un abuso, è molto semplice farsi prendere la b.uno(“ciao”);
mano e scrivere codice molto poco leggibile, ossia l’esatto }
opposto del beneficio atteso! }

Covarianza (sul tipo di ritorno) porta in realtà ad un overload e non certo ad un override.
Per accertarsene, basta verificare l’output del main: viene
La covarianza sul tipo di ritorno è un altro aspetto di Java5 eseguito il metodo della classe base e non della classe de-
passato un po’ in sordina. In realtà il suo inserimento in rivata
Java5 è stato accessorio all’inserimento di altre feature, ma Ritornando alle novità di Java5, è ora possibile avere il
è comunque una caratteristica in più ed utile di per sé, so- tipo di ritorno covariante e dunque scrivere codice come
prattutto perché può semplificare il design in diversi casi. questo (mi si perdoni il dominio dell’esempio, che è pa-
Qui c’è sicuramente bisogno di un appoggio teorico, anche tetico):
per chiarire alcuni aspetti che spesso non vengono chiariti
abbastanza. Troppo spesso si legge che Java5 supporta la public abstract class Erbivoro {
covarianza, in realtà con Java5 ora c’è il supporto della co- public abstract Erba mangia();
varianza sul tipo di ritorno, poichè alcune caratteristiche del }
linguaggio erano già covarianti da tempo immemore. public abstract class Cavallo extends Erbivoro {
Ma vediamo le definizioni: public abstract Fieno mangia();
Un tipo, relativamente al suo supertipo, può essere inva- }
riante, covariante o controvariante. Invariante vuol dire
evidentemente che deve essere lo stesso. Covariante e Dove Fieno estende Erba, permettendo dunque ad una
controvariante vogliono dire, rispettivamente, che può es- sottoclasse di specificare meglio il comportamento rispetto

n.1 - settembre 2006 53


educational JAVA Journal

sistemi unix e jre/bin/client/classes.jsa per i sistemi win-


Tipo Varianza in Java dows. Sul mio sistema linux è un file di circa 13Mb, il che
Tipo di ritorno Covariante (invariante ad occhio e croce vuol dire che ad ogni esecuzione la Vir-
fino a JDK 1.4.x) tual Machine avrà un footprint molto più leggero e rispar-
mierà pure un bel po’ di tempo per lo startup.
Parametro Invariante
Sarà interessante vedere come si evolverà il class sharing
Eccezione Covariante in Java6, anche in virtù della probabile introduzione in
questa release delle nuove “Isolation API”, descritte nel
JSR 121 [ISOLATION], che invece si pongono un proble-
TABELLA 4
ma più ampio: come isolare oggetti e contemporaneamen-
te condividere risorse fra diverse applicazioni java. Queste
alla sua superclasse. Api dovevano originariamente essere inserite in Java5,
La covarianza sul tipo di ritorno è dunque un arma in più quindi ce le aspettiamo tutti in Mustang!
nel nostro bagaglio di designer, e permette di modellare L’altra novità sistemistica di rilievo è l’inserimento
in maniera decisamente più efficace e parsimoniosa alcu- nella distribuzione standard di moltissimi tool per il
ni problemi, contribuendo ad evitare l’abuso della classe troubleshooting/monitoring delle applicazioni. Sostanzial-
Object, in linea con le altre feature di Java5. mente è possibile ora monitorare e diagnosticare problemi
In tabella riassumiamo per comodità lo stato della cova- in applicazioni Java senza utilizzare costosi sistemi di
rianza in Java. (Tabella 4) profiling (ovviamente questi sistemi sono molto più user-
friendly delle utility java5) con tool come jstat, jinfo, jmap,
Class sharing e troubleshooting jps e jconsole. L’argomento è molto vasto e richiederebbe
sicuramente un articolo specialistico di approfondimento,
Il class sharing [SHARING] è una novità “sistemistica” di nel frattempo potete però cominciare a sfogliare le oltre
Java5. Questa tecnica è stata in realtà inventata da Apple 100 pagine di pdf [TROUBLESHOOTING] della guida Sun
per il JDK 1.4 di OsX, e successivamente condivisa con il al troubleshooting!
resto della comunità Java ed inserita nella release 5.0.
Sostanzialmente il class sharing permette di diminuire il Conclusioni
tempo di avvio (startup) della virtual machine e lo spazio
occupato in memoria (footprint). Lo startup della Virtual Con questa breve rassegna delle novità di Java5 spero
Machine infatti, se troppo elevato, è un ostacolo alla dif- di avere incuriosito coloro che, per vari motivi di tempo/
fusione di Java in compiti diversi da quelli di middleware: lavoro, sono rimasti legati alle “vecchie” release di Java.
dal desktop allo scripting, riavviare ogni volta la macchina Per gli approfondimenti, vi rimando alla bibliografia. Il
virtuale è sicuramente uno spreco di risorse. riferimento insuperato ed ufficiale è sicuramente il [GO-
Il class sharing, nella sua forma attuale, consiste nel man- SLING], che espone anche i dettagli del linguaggio in uno
tenere i riferimenti ad una serie di classi java di sistema stile asciutto ma comprensibilissimo. Nella seconda parte
(alcune classi incluse in rt.jar) in modo che diverse esecu- di questo articolo tratteremo le concurrent API, i typesafe
zioni della virtual machine si trovino già un po’ di lavoro enums, i varargs e le annotations API. E vedremo cosa bol-
preparato. Tecnicamente, questo avviene utilizzando il le in pentola per Java6.
memory mapping: queste classi “condivise”, serializzate
in un formato particolare, sono a disposizione di tutti in Riferimenti e bibliografia
un file, lo shared archive. Questo file, essendo “memory
mapped”, permette così alle diverse istanze delle VM di [GOF94] Iterator pattern
condividere queste classi di sistema e di risparmiare il tem- [BLOCH] Effective Java
po del loro caricamento, di fatto diminuendo lo startup ed [ENHANCEMENTS] http://java.sun.com/j2se/1.5.0/docs/
il footprint. relnotes/features.html
Sotto OsX per PowerPC è noto come, pur non essendo [FLANAGAN] Java 1.5 Tiger, a developer’s notebook
la VM particolarmente performante, il JDK 1.4 aveva un [GOSLING] The Java Programming Language, 4th edition
tempo di startup molto basso e le performance “percepite” [ISOLATION] http://www.jcp.org/en/jsr/detail?id=121
sembravano così molto elevate. Con Java5 anche gli altri [PIZZA] http://www.cis.unisa.edu.au/~pizza/
sistemi (x86, Sparc) possono ora beneficiare di questa in- [SHARING] http://java.sun.com/j2se/1.5.0/docs/guide/vm/
teressante ottimizzazione. class-data-sharing.html
Da notare che attualmente ci sono diverse limitazioni, per [TROUBLESHOOTING] http://java.sun.com/j2se/1.5/pdf/
cui lo sharing delle classi funziona solo se la virtual ma- jdk50_ts_guide.pdf
chine è eseguita in modalità Hot Spot client (d’altronde
sul server ha meno senso), e non con tutti i possibili tipi di
Note Biografiche
Garbage Collection. Se volete giocare un po’ con l’archivio
shared, con il seguente comando forzate la costruzione del Ugo Landini ha più di 10 anni di esperienza nel mondo Object
Oriented, e segue Java dalla nascita. Si ostina ancora a voler pro-
file classes.jsa (Java Shared Archive): grammare e ha velleità di centravanti, con scarsi risultati in en-
trambe le attività. È CTO in Pronetics, dove si è occupa preva-
java -Xshare:dump lentemente di architetture distribuite e di tutto ciò che riguarda
il mondo Java, XML e in generale l’integrazione. È stato Senior
Java Architect in Sun Microsystems.
Il file si trova sotto jre/lib/[arch]/client/classes.jsa per i

54 n.1 - settembre 2006


JAVA Journal educational

Fondamenti di Programmazione Java

Prima parte: uno


sguardo d’insieme
Java è il protagonista della nostra rivista; la rivista ovviamente non si rivolge solo a chi lo conosce
già, ma anche a chi Java lo vuole imparare. Un corso istituzionale sui fondamenti di Java inagura
la sezione educativa di Java Journal. Questo corso comunque è per chi è già un programmatore: si
presume che abbiate già le basi di programmazione, ovvero sappiate programmare in almeno un
altro linguaggio.

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

I
di programmazione, nato oramai più di 10 anni fa.
Ai tempi della sua gestazione, uno dei linguaggi di
niziamo il nostro corso spiegando alcuni con- programmazione più usati era il linguaggio C, mentre
cetti base. Il nome “Java” è un nome che rac- il suo designato successore era il linguaggio C++. Il
chiude in sé le diverse tecnologie che com- C++ è una estensione del linguaggio C che mantie-
pongono la “piattaforma” Java. In particola- ne la compatibilità all’indietro: cioè ogni programma
re, Java è innanzitutto un (bel) linguaggio di scritto in C è, a meno di marginali modifiche, utiliz-
programmazione, ed è quello che la maggior zabile come programma C++.
parte dei neo-programmatori Java desidera
imparare. Java però è anche il nome della “virtual Raccontano le cronache che James Gosling, il prin-
machine”, ovvero l’ambiente di l’esecuzione di pro- cipale autore del linguaggio Java, aveva tentato di
grammi, nota più propriamente con l’acronimo JVM usare il C++ per realizzare un editor per l’SGML
(ovvero Java Virtual Machine). La JVM è il più usato (il precursore dell’attuale XML), ma si era scontrato
(ma non l’unico) ambiente di esecuzione per i pro- con la sua grande complessità. Notoriamente il C++
grammi scritti in linguaggio Java. presenta non poche difficoltà: queste sono indotte
anche dal fatto che è un linguaggio sostanzialmente
Infine, sotto il nome di Java ricadono anche le ampie di basso livello; si tratta di una caratteristica eredita-
e complesse librerie standard della “piattaforma” ta dal fatto che è volutamente compatibile con il C.
Java; queste librerie fanno sì che essa sia qualcosa Questo fatto, aggiunto alla grande quantità di “featu-
di più di un linguaggio di programmazione: ovvero re” (funzionalità) disponibili, lo rende un linguaggio
Java è un completo ambiente di esecuzione di pro- molto difficile, che richiede grande accortezza nella
grammi che isola dal sistema operativo sottostante. stesura dei programmi, e presenta tanti trabocchetti
Per questo motivo si parla di piattaforma: non si per i programmatori.
tratta di un vero e proprio sistema operativo (non
arriva a mettere le radici nell’hardware, fornendo Quando Gosling si trovò a dover scegliere (o pro-
device driver e cose del genere), ma è completamen- gettare) un linguaggio di programmazione per una
te autosufficiente per quanto riguarda lo sviluppo nuova applicazione, pensò di partire dal C++ proprio
di software. Una volta scritto un programma in perché veniva considerato “il linguaggio del futuro”.
Java, per eseguirlo basta il cosiddetto Java RunTime Sun stava infatti sviluppando un sistema di nuova
Environment, che esiste per numerosi sistemi ope- concezione (quello che poi, dopo varie peripezie, sa-
rativi: Windows, Linux, Solaris, MacOSX, AS/400 e rebbe diventata la piattaforma Java), e Gosling creò
così via. un linguaggio chiamato Oak (in inglese ‘quercia’, che
richiama l’idea della solidità e robustezza). L’idea di
Il linguaggio Java fondo era quella di riprendere la sintassi e le migliori
idee del C++, ma, al prezzo di “rompere con il passato”
Esaminiamo le caratteristiche specifiche del linguag- (ovvero la compatibilità con il C), creare un derivato
gio Java e la sua genesi. Si tratta di un linguaggio con una sintassi e una semantica simile, ma molto

n.1 - settembre 2006 55


educational JAVA Journal

più semplice, lineare, coerente, facile da imparare e che white-paper di molti anni fa su Java 1.0 in cui si ripeteva il
presentasse meno trappole per i programmatori. mantra: less is more (meno è di più).

In effetti, chi conosce il C++ e Java si rende conto che Praticamente sono state rimosse tutte le caratteristiche
molti concetti sono gli stessi: si ha la stessa sintassi di base, che rendevano difficile la lettura del codice (come l’opera-
ereditata dal C; il modo di definire classi e oggetti in Java è tor overloading, che permette di dare agli operatori come
abbastanza simile a quella del C++ (anche se decisamente il “+” significati diversi, ma costringe il programmatore a
meno potente). Infatti esaminando in dettaglio si scopre fare molta attenzione al tipo di una variabile). Sono state
che molte caratteristiche del C++ sono state rimosse. È come se anche rimosse alcune parti che complicavano parecchio
qualcuno avesse voluto usare un sottoinsieme del C++ in- l’implementazione (per esempio l’ereditarietà multipla).
serendo solo quello che era strettamente utile. Ricordo un Altre caratteristiche del C++ sono rimaste a lungo fuori
dal linguaggio Java ma sono state poi reintrodotte solo di
recente (come la programmazione generica). In definitiva
Java vuole essere un C++ più semplice e lineare. Ma non
si è trattato solo di pulire la sintassi: Java ha anche intro-
dotto nuove funzionalità, come l’esecuzione su una virtual
machine e la “garbage collection”.

Chi conosce
C++ e Java si rende
conto che molti concetti
sono analoghi

La Garbage Collection

Una delle più importanti estensione rispetto al C++ è


che Java gestisce la memoria in maniera automatica. Questo
concetto è abbastanza delicato ed importante: per cui ne
parliamo subito per approfondirlo poi. In linguaggi come il
C o il C++, quando si ha bisogno di memoria, viene chie-
sta al sistema (si dice che “viene allocata”). Occorre però
ricordarsi, quando la memoria non serve più, di restituirla
esplicitamente al sistema.

In un programma, l’uso di memoria è continuo: ogni og-


getto che si crea (e Java fa tutto usando oggetti) richiede
memoria. Notoriamente, la gestione della memoria occupa
molto tempo nella programmazione, sia C che C++, ed è
soggetta ad errori. Questo avviene soprattutto quando si
costruiscono strutture dati complesse, in cui parti sono
condivise: in questo modo non è affatto ovvio né semplice
determinare quando un blocco di memoria deve essere
liberato, perché potrebbe essere in uso da altre parti del
programma.

Java permette di richiedere la memoria al sistema, e di


recuperarla in maniera automatica. Java infatti rileva
automaticamente che un blocco di memoria non serve
più al programma. Questa apparente “magia” viene fatta
considerando la memoria che in un momento il program-
ma sta utilizzando, a partire dalle variabili che sono in uso.
Tutta la memoria che il programma non può più utilizzare
(semplicemente perché le variabili in uso non consentono
FIGURA 1 la garbage collection

56 n.1 - settembre 2006


JAVA Journal educational

cati” blocchi di memoria che in Java corrispondono


public class Hello { agli oggetti. Alcuni oggetti possono a loro volta fare
public static void main(String[] args) { riferimento ad altri oggetti.
System.out.println(“Hello, world”);
} È possibile determinare quale memoria è attualmen-
} te in uso in questo modo: si considerano tutte le va-
riabili del programma (guardando lo stack), e da lì si
LISTATO 2 Il nostro primo listato risale agli oggetti che usano; eventualmente alcuni
oggetti possono fare riferimento ad altri oggetti, che
di raggiungerla) viene recuperata, tramite un meccanismo sono in uso anche questi (sia pur indirettamente). La gar-
denominato “raccolta di spazzatura” (appunto garbage bage collection (raccolta di spazzatura) funziona proprio
collection). così: con il processo appena descritto, si “marcano” tutti
gli oggetti che sono in uso. Tutti quelli rimasti, non essen-
Programmatori esperti in C o Pascal inorridiscono all’idea do utilizzabili, vengono considerati spazzatura, e vengono
di “sprecare” tanta memoria, e dubitano fortemente che difatti riutilizzati, recuperando la memoria.
un meccanismo del genere possa funzionare. Eppure, che
ci si creda o no, la garbage collection può essere molto
efficiente, e (sui grandi numeri) addirittura più effi-
ciente della gestione manuale. Il rovescio della medaglia La memoria usata
comunque è che il Java standard necessita di parecchia
memoria, nell’ordine dei megabyte. Il Java Micro Edition dal programma è acces-
è ottimizzato per l’uso in ambienti con limitate risorse,
e pur mantenendo la garbage collection, richiede me- sibile solo attraverso
moria nell’ordine dei kilobyte. Ciò non toglie che Java
è un linguaggio con alti requisiti di memoria anche per le variabili in uso
programmi semplici, anche se oggi giorno la memoria
è diventata una risorsa relativamente economica ed è
disponibile in quantità anche in ambienti limitati come
i telefoni cellulari. La Java Virtual Machine

Per capire come funziona la garbage collection possiamo I programmi scritti in Java possono essere eseguiti in vari
fare riferimento alla Figura 1: ho rappresentato schema- modi. Se pensate al C, sapete che i programmi vengono
ticamente una situazione tipica di un programma Java in compilati in codice nativo, per poi essere eseguiti diret-
esecuzione. Il programma utilizza la memoria a partire tamente dal processore (il C e il C++ è solitamente un
dalle sue variabili. Tutte le variabili attualmente in uso si compilatore puro). Se pensate al Basic (o al JavaScript
trovano in un posto noto, chiamato “stack”. Tutta la me- per considerare un altro caso più recente), sapete che i
moria usata dal programma è accessibile solo attraverso le programmi possono venire eseguiti così come sono, senza
variabili in uso, che fanno riferimento all’area di memoria nessun passo intermedio. Si tratta della tradizionale di-
di uso dinamico chiamata “heap”. Nello heap sono “allo- stinzione tra interprete e compilatore (che nel caso di Java
non vale del tutto).
Compiled from “Hello.java”
Va subito detto che per Java esistono
public class Hello extends java.lang.Object{
sia compilatori puri che interpreti puri.
public Hello();
Esiste per esempio il compilatore GCJ,
Code:
che trasforma un programma Java in
0: aload_0
codice nativo, eseguito direttamente dal
//Method java/lang/Object.”<init>”:()V
processore. Esistono anche interpreti puri
1: invokespecial #1;
(come la BeanShell), in grado di esegui-
4: return
re programmi Java direttamente, così
come sono, senza alcuna trasformazione
public static void main(java.lang.String[]);
intermedia. Nella maggior parte dei casi
Code:
tuttavia, Java viene utilizzato seguendo
//Field java/lang/System.out:Ljava/io/PrintStream;
l’approccio originale: ovvero viene prima
0: getstatic #2;
compilato in un codice intermedio, detto
3: ldc #3; //String Hello, world
bytecode, e poi eseguito da un interprete,
//Method java/io/PrintStream.println:(Ljava/lang/String;)V
detto Java Virtual Machine. Questo fa
5: invokevirtual #4;
di Java un linguaggio essenzialmente
8: return
interpretato; tuttavia quello che viene
interpretato non è il codice Java così come
}
è, ma un suo codice intermedio, risultante
da compilazione esplicita, detto bytecode.
LISTATO 3 II bytecode di Hello

n.1 - settembre 2006 57


educational JAVA Journal

Siete alle prime armi e non sapete da dove scaricare Java? Allora prima di cominciare a leggere l’articolo leggete
queste istruzioni.
Java viene fornito con due diversi download: il Java Runtime Environment (JRE), e il Java Development Kit (JDK).
Il primo (JRE) serve per eseguire programmi in Java, mentre il secondo (JDK) serve per SVILUPPARE programmi in
Java. Poiché vogliamo programmare, è necessario procurarci il JDK. Consigliamo di usare l’ultima versione, la 5.0.
Potete scaricare il JDK dal sito http://java.sun.com. Fare attenzione che sito http://www.java.com fornisce il JRE, non
il JDK. La posizione del JDK è, al momento in cui scrivo, questa (ma può ovviamente variare in quanto i rilasci di
nuove versioni si susseguono con un ritmo frenetico):

http://java.sun.com/j2se/1.5.0/download.jsp

Consiglio per il momento di scaricare solamente il JDK, e non il bundle che comprende anche l’ambiente di program-
mazione NetBeans: può essere abbastanza complicato orientarsi con un ambiente di sviluppo tuttofare finché non si
conoscono i fondamenti. Gli esempi del nostro corso possono essere provati per il momento con un semplice editor di
testo (ad esempio, Notepad su Windows).
Ricordatevi comunque, dopo aver installato il JDK, di aggiungere al PATH gli strumenti di sviluppo. Se state usando
Windows, dovete andare nel pannello di controllo, scegliere Sistema, Avanzate e poi Variabili di Ambiente, e infine
impostare la variabile PATH e aggiungere all’inizio “C:\Programmi\Java\jdk1.5.xxx\bin;” (cambiare xxx con l’effettiva
versione che avete nel vostro computer). A questo punto, da una finestra terminale, digitate “java -version”. Se leg-
gete la versione di Java siete pronti per lavorare.

RIQUADRO 1 Installare il Java Development Kit

Proviamo adesso a toccare con mano queste caratteri- ni. Ma se utilizziamo il comando javap -c Hello possiamo
stiche, partendo dal nostro primo listato, mostrato nel decodificare il bytecode ottenendo quello che vediamo nel
Listato 2. Sfortunatamente, in Java anche il classico Listato 3.
programma che stampa al terminale “Hello World”, usa
molti concetti che non sono ovvi: occorre necessaria- Cosa scopriamo pertanto? Che il bytecode assomiglia mol-
mente creare una classe, citare concetti avanzati come to ad un vero assemby. In effetti la JVM assomiglia molto
gli array, imporre la visibilità pubblica, chiamare un meto- ad un vero processore, solo che non è realizzato in silicio
do e un campo statico. Tutti concetti che approfondiremo ma direttamente in software. C’è da dire comunque che
strada facendo. Per il momento non consideriamo perché la JVM non è esattamente progettata come un processore
il listato è scritto così, ci concentriamo su come fare ad fisico, e presenta alcuni concetti “evoluti” come l’invoca-
eseguire il nostro primo programma, con lo scopo di zione di metodi virtuali e altre caratteristiche che rendono
esplorare il meccanismo di esecuzione e la Java Virtual particolarmente semplice compilare per essa un linguaggio
Machine. di alto livello (come Java).

Supponiamo di aver creato il listato in figura e di averlo


memorizzato in un file chiamato Hello.java. La scelta non
è casuale: se un programma contiene una classe pubbli-
ca che si chiama Hello allora deve trovarsi in un file con il
nome indicato. Se è così, andiamo alla riga di comando del
La JVM assomiglia
DOS (o di Linux), cambiamo alla directory dove si trova
il sorgente e proviamo a compilare il primo programma,
eseguendo javac Hello.java. Se non avete commesso errori di
ad un vero processore
sintassi, non dovreste avere alcun messaggio. (Ricordatevi
prima di installare il Java Development Kit, per i dettagli si
veda il Riquadro 1). realizzato via software
Il risultato della compilazione è la comparsa, nella di-
rectory corrente, del file Hello.class, che contiene il byte-
code. È questo il vero codice eseguibile di Java. Senza un Le prestazioni
“.class”, anche se abbiamo un “.java”, il programma non
può andare in esecuzione. Se abbiamo creato il “.class”, Quando si scopre che Java è sostanzialmente interpre-
possiamo scrivere java Hello e otterremo il fatidico messag- tato, molti programmatori associano immediatamente
gio Hello, world. questo fatto con una lentezza di esecuzione. In realtà
le cose non stanno proprio così. La maggior parte degli
Approfittiamo della disponibilità del file Hello.class per interpreti Java in realtà sono dei “compilatori Just-In-
dare un’occhiata a come è fatto il bytecode. Purtroppo se Time”: questo significa che trasformano il byte code “al
proviamo ad aprire ll suddetto file con un editor di testo volo”, immediatamente prima di eseguirlo, in codice
rimarremo delusi: il file è binario e illeggibile dagli uma- macchina e poi lo eseguono a velocità nativa. Questo

58 n.1 - settembre 2006


JAVA Journal educational

non significa che non ci sia un degrado di prestazioni “write once run anywhere”. In realtà il raggiungimento
rispetto al codice macchina puro; significa che il degra- effettivo di questo obiettivo ha richiesto considerevoli
do di prestazioni è molto inferiore a quello che normal- sforzi, ma si può dire che, dopo anni di sviluppo, sia stato
mente si pensa. In alcuni casi, la velocità di esecuzione raggiunto, e non solo in teoria ma anche in pratica.
di un interprete Java può essere addirittura superiore
a quella di codice equivalente scritto in C/C++, perché La libreria di Java, inizialmente piccola e semplice (con la
il compilatore Just-In-Time è in grado di ottimizzare versione 1.0 di Java) si è nel tempo ingrandita in maniera
il codice durante l’esecuzione, in base ai risultati delle considerevole. In effetti il “nocciolo” della piattaforma
esecuzioni precedenti! Java, la sua portabilità, è legata al fatto che è possibile fare
moltissime cose utilizzando solamente la libreria standard
In verità, Java viene usato spesso per compiti abbastanza di Java. In questo modo un programma dipende solo da
complessi: viene utilizzato spesso per realizzare appli- essa; a sua volta la libreria Java è stata adattata a gran
cazioni di tipo Web, che operano su complessi database parte dei sistemi operativi moderni attualmente in uso
relazionali. In questi casi, il tempo che viene impiegato per (Windows, MacOSX, Linux, Solaris, AS/400 eccetera);
la trasmissione in rete delle pagine Web o per accedere al in questo modo un programma “in Java” può funzionare
database occupa una porzione di tempo molto significativa praticamente dovunque senza modifiche.
(in certi casi superiore al 99%) rispetto al puro tempo di
esecuzione del codice Java. In questi ambiti la pura veloci-
tà di esecuzione del linguaggio conta molto poco rispetto
al contesto. Infatti vengono comunemente utilizzati per
questo tipo di applicazioni anche linguaggi di scripting,
che sono, nei fatti, molto più lenti di Java, e raramente
La libreria Java è
si considera la loro “pura” velocità di esecuzione come un
fattore determinante.
indipendente dal
Ma Java viene anche utilizzato anche per costruire i cosid-
sistema operativo
detti “Application Server”, ovvero complesse infrastrutture
per l’esecuzione di programmi, dei veri e propri “sistemi sottostante
operativi” per lo sviluppo di applicazioni Web. Siccome
Java è nei fatti piuttosto efficiente e veloce, è possibile
realizzarli interamente in Java.
In realtà, un programma scritto male può dipendere da
La libreria di Java comportamenti del sistema operativo sottostante, e quindi
comportarsi diversamente su sistemi operativi differenti.
Abbiamo dunque visto che abbiamo a che fare con un buon Nel corso degli anni però questo problema si è via via at-
linguaggio di programmazione, e un buon supporto a tempo tenuato, anche se ricorrendo a dei compromessi, a volte
di esecuzione dello stesso, la JVM. Ma tutto questo non fa eccessivi. La libreria di Java si è da un lato ingrandita (ver-
(ancora) di Java una piattaforma. I linguaggi di program- so l’impresa), dall’altro ridotta (verso i dispositivi mobili).
mazione tradizionali, come il C, il Pascal o lo stesso C++, Per questo motivo la “piattaforma Java” è stata divisa in
prevedono nello standard le sole librerie standard minime tre edizioni: Standard, Micro ed Enterprise. Di fatto la
per fare input/output a riga di comando. Il C++ va un po’ differenza tra queste edizioni consiste, oltre a una virtual
avanti perché fornisce anche, nelle sue versioni più recenti, machine diversa per la Micro Edition, in un diverso corre-
strutture dati e algoritmi standard. Ma linguaggi più recenti do di librerie fornite.
come Visual Basic o Delphi, forniscono anche tutto il ne-
cessario per sviluppare applicazioni a interfaccia grafica con La Standard Edition è quella che abbiamo quando scari-
connessioni a database: ovvero forniscono allo sviluppatore chiamo Java dal sito http://java.sun.com. Per essere cor-
professionista il necessario per sviluppare applicazioni senza retti, sul sito Sun sono disponibili due diversi pacchetti: il
dover ricorrere a ulteriori componenti di terze parti. Runtime Environment e il Development Kit. Il primo serve
per l’esecuzione di programmi in java; è il minimo assoluto
Il Java standard fornisce, insieme al linguaggio di pro- necessario per poter usare programmi in Java sul proprio
grammazione e alla virtual machine, anche una cospicua computer. Il secondo invece comprende degli strumenti
libreria che permette di fare tutte le principali attività per lo sviluppo, in particolare il compilatore e altre utilità
necessarie per lo sviluppo di programmi di tipo Desktop: per la programmazione.
creazione di interfacce grafiche, accesso a database, ma
anche librerie per la manipolazione di strutture dati, di La Micro Edition è Java adattato per funzionare su pal-
immagini, per processare l’XML, accedere al web e molto mari, cellulari e in generale su dispositivi meno potenti di
molto altro. Il bello della libreria Java è che, come la virtual un Desktop Computer. In un certo senso, si tratta di una
machine, è totalmente indipendente dal sistema operativo versione ridotta della Standard Edition; comprende anche
sottostante. Questo fa sì che un programma scritto in Java librerie specifiche per funzionalità dei dispositivi mobili
sotto Windows possa funzionare senza modifiche anche che non sono presenti nella Standard Edition.
sotto Linux e il Mac. Questa è la grande promessa di Java: Di solito, troviamo Java già pronto per eseguire applica-

n.1 - settembre 2006 59


educational JAVA Journal

zioni in molti dispositivi mobili, come i telefoni cellulari Gli elementi base di un programma in Java sono costanti
Nokia, Motorola o SonyEriccson (per citare solo i casi più e variabili. Una costante è per esempio il numero uno (1),
noti). Esistono anche versioni che si scaricano e si instal- un carattere ‘a’, o una stringa “hello”. Ci sono dei dettagli
lano, come la J9 di IBM disponibile per dispositivi PalmOS che vedremo più avanti. Una variabile è invece una se-
e PocketPC. La Micro Edition tuttavia è meno incapsulata quenza alfanumerica di lettere o numeri: per esempio a
della Standard Edition, anzi è piuttosto modulare (molti è una variabile. Per la verità anche _1 o a$ sono variabili
dicono troppo): esistono infatti diversi profili e configura- valide in Java: la regola per gli “identificatori” è che siano
zioni. Per i dettagli rimandiamo all’articolo sull’argomento sequenze alfanumeriche di lettere, numeri, il carattere “_”
su questo stesso numero. o il carattere “$”, e non possono cominciare con un nume-
ro. In realtà Java permette anche di usare caratteri come le
La Enterprise Edition invece è la Standard Edition estesa lettere accentate come lettere. Usando variabili, costanti e
con una serie di funzioni che sono utili per la realizzazio- operatori (+,-,* eccetera) si creano delle espressioni. Quindi
ne di applicazioni complesse per le imprese, di solito con nel caso più semplice avremo:
interfaccia Web, ma che comprendono una serie di compo-
nenti distribuiti che si parlano tra di loro. Di solito per ave- a+1
re la Enterprise Edition occorre procurarsi un applicativo
che la implementa, comunemente noto come Application Notare che in Java (come in C o in JavaScript) l’assegna-
Server. Per esempio sono application server generalmente mento (=) è un operatore. Si possono anche usare le paren-
conformi a una versione di Java Enterprise Edition prodot- tesi, quindi la seguente è una espressione:
ti commerciali come BEA WebLogic o IBM WebSphere, o
prodotti Open Source come JBoss o Apache Geronimo. Ma b = a + (c-1)
approfondiremo l’argomento in dettaglio in queste pagine
prossimamente. Fin qui abbiamo considerato il mattone fondamentale di
Java; ma un programma in Java non è solo un calcolo, ma
una sequenza di calcoli. Chiameremo comando un singolo

Per utilizzare la Enter-


passo di esecuzione (che può comprendere un calcolo): i
comandi infatti generalmente contengono delle espressio-
ni. Un comando semplice è una espressione seguita da un
prise Edition occorre punto e virgola. Per esempio:

un applicativo che la b = a + 1 ;

implementi,comunemente I comandi possono essere posti in sequenza:

noto come Application a = 1;


b = a + 1 ;

Server Oltre ai comandi semplici, abbiamo anche i comandi com-


posti, che possono contenere dei sotto-comandi semplici.
Consideriamo questo caso:
Struttura di un programma in Java
a = 1;
Riprendiamo l’obiettivo principale di questo corso, if(b>2)
l’apprendimento del linguaggio Java (nonché di alcu- a = 2;
ne funzioni della libreria di base). Vediamo dunque la
struttura dei programmi. Come abbiamo già detto nel Il comando composto if contiene una espressione b>2 e
nostro primo esempio, sfortunatamente (dal punto di un sotto-comando (a=2;); a sua volta esso contiene una
vista didattico) non è possibile scrivere un programma espressione. Per il momento non ci soffermiamo oltre, lo
Java che sia semplice come, per esempio, in BASIC. In scopo di questa introduzione alla sintassi è avere un’idea
questo caso, PRINT “HELLO” costituisce un programma di come si presenta un programma Java. Affronteremo i
valido. Il più piccolo programma valido in Java è forse dettagli strada facendo.
class Hello { }, ma purtroppo questo programa non fa
assolutamente nulla. Un altro elemento importante presente nei programmi in
Java, che non sono comandi ma che possono contenere
Per scrivere un programma che scriva “Hello” occorre espressioni, è la dichiarazione. Ecco un esempio:
digitare tutto questo mostrato nel primo listato. In breve
occorre creare una classe, definire un metodo, ivi chiama- int b
re un altro metodo (println) di un’altra classe (System)
che stampa la nostra costante. Non è ancora il momento In questo caso int significa intero, ed è il nome di un tipo,
di capire come funziona. Vediamo invece innanzitutto la mentre b è il nome di una variabile. Questa è una dichiarazio-
sintassi dei programmi in Java. ne di variabile. In generale prima di usare una variabile oc-

60 n.1 - settembre 2006


JAVA Journal educational

int doubler(int x) {
corre sempre dichiararla, ovvero specificare il suo tipo. Una int res = x*two;
dichiarazione può anche essere seguita da una espressione return res;
di inizializzazione (e conclusa da un punto e virgola) }
}
int a = 1;
L’esempio non vuole essere codice da usare in programmi
Una dichiarazione può essere usata (senza inizializzazio- reali. È scritto in questo modo per evidenziare due cose: le
ne) quando viene dichiarato un metodo, come nel seguente diverse posizioni in cui è possibile collocare una dichiara-
caso: zione di variabile, e le cosiddette variabili libere. Ma andia-
mo con ordine.
int sum(int a, int b) {
return a+b;
} Per prima cosa notiamo la dichiarazione di variabile: oltre
ad essere presente nel parametro del metodo (int x), è pre-
I metodi in Java assomigliano alle funzioni o alle proce- sente anche dentro il metodo (int res = x * two) e fuori dal
dure di altri linguaggi di programmazione. Questa strut- metodo ma dentro la classe (int two=2). Nel primo caso,
tura già diventa più complicata. Abbiamo l’intestazione la variabile viene comunemente chiamata variabile locale.
int sum(int a, int b). In gergo si dice che è la “firma” di Il motivo è che queste variabili vengono create quando
un metodo. Indica cosa viene fornito in ingresso e cosa si entra nel metodo, ma scompaiono quando si esce dal
viene ritornato quando viene chiamato. Un metodo in un metodo. Nel secondo caso (int two=2) queste variabili ven-
certo senso assomiglia ad una funzione matematica, ma in gono chiamate campi, e sono persistenti. Per essere esatti
realtà è qualcosa in più. La firma dichiara i parametri che (ma è un concetto che dovremo riesaminare più avanti in
prende e il valore che ritorna: il metodo add dunque pren- maggior dettaglio) i campi esistono fin tanto che esiste
de due parametri a e b di tipo intero, e ritorna un risultato l’oggetto che le contiene.
intero. Dopo la firma abbiamo il corpo del metodo, ovvero
una sequenza di comandi racchiusi tra parentesi graffe. Infine introduciamo il concetto di “variabile libera”. Se
In alcuni casi ci serve solo la firma, e non il corpo: in osserviamo in dettaglio il corpo del metodo doubler no-
questi casi al posto del corpo c’è semplicemente un punto teremo a un certo punto l’espressione res = x*two. Ora,
e virgola. res è una variabile locale, mentre x è un parametro, ma
two non è nessuna delle due. Guardando il solo corpo
Un elemento importante è che i metodi non possono es- del metodo non si riesce a trovare dove questa variabile
sere dichiarati da soli. In altri linguaggi è possibile avere è dichiarata: per questo motivo viene detta variabile li-
una funzione sum, ed è un componente non collegato ad bera. Ma in Java le variabili libere di un metodo possono
altro in un programma. Non così in Java: non abbiamo solo fare riferimento alle variabili della classe, ovvero ai
un concetto di funzione a sé stante, ma solo di metodo, e campi.
come tale deve trovarsi sempre dentro la dichiarazione di
una classe. È abbastanza importante sviluppare occhio per le variabili
libere in un metodo: questo ci permette di localizzare fa-
Come abbiamo detto, una classe è la minima entità auto- cilmente i campi; è dove vengono memorizzate le informa-
noma in java: zioni che devono persistere al di fuori del metodo corrente.
In un certo senso, le variabili libere mettono in comunica-
class Hello { zione il metodo con la classe che le contiene.
}

Conclusioni
è un programma valido che può essere compilato da solo.
Ma non fa assolutamente nulla. Dentro la classe possiamo Se Java lo conoscevate solo per sentito dire, adesso ab-
inserire la dichiarazione di un metodo: biamo mosso i primi passi. Abbiamo parlato di virtual
machine e di byte code, e abbiamo spiegato le varie edi-
class Sum { zioni di Java. Nel prossimo numero vedremo in dettaglio il
int sum(int a, int b) { linguaggio, esaminando come sono implementati in Java i
return a+b; classici costrutti di programmazione.
}
}
Note Biografiche
Anche questa è una classe valida, e contiene anche un me- Michele Sciabarrà si occupa di Java fin da quando, nel 93, sca-
todo di somma. Per completare il discorso, ci serve capire ricò il sorgente di HotJava e per compilarlo saturò il disco del-
la Workstation Sun che amministrava. Da allora ha lavorato in
che relazione abbiamo tra un metodo e una classe. Consi- Java passando dalle applet per Netscape 2 fino alle applicazioni
deriamo questo esempio: bancarie di classe enterprise. Dopo aver scritto di Java e averlo
insegnato per dieci anni, è direttore esecutivo di Java Journal.
Quando non cerca di imparare le ultime API o disquisisce della
class Doubler { superiorità del modello Open Source, si diletta a programmare
int two =2; cellulari Symbian in C++ e a amministrare sistemi Linux.

n.1 - settembre 2006 61


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!

Codice orribile, antipattern e


pratiche discutibili
>> di Ugo Landini (ugo.landini@javajournal.it)

if (a instanceof b) {
La massima di questo mese: “My guess is that // fai qualcosa
} else if (a instanceof c) {
object-oriented programming will be in the 1980s // fai qualche altra cosa
what structured programming was in the 1970s. }
Everyone will be in favor of it. Every manufacturer
Ora, già l’uso di instanceof è di per sé criticabile:
will promote his products as supporting it. Every
instanceof in un linguaggio ad oggetti non dovreb-
manager will pay lip service to it. Every program- be mai essere usato, se non in un caso particolare
mer will practice it (differently). And no one will che lascio come simpatico esercizio agli amici let-
know just what it is.” tori.
T. Rentsch
Ma usare instanceof per fare eseguire logiche di-
verse ad un oggetto a seconda del suo tipo, è vera-
mente abominevole: a cosa serve il polimorfismo
– che fa esattamente la stessa cosa - se poi devo
ricostruirmelo malamente da solo? Notare che il
#1: Il polimorfismo dei poveri fatto che l’operazione sia eseguita sullo lo stesso
oggetto su cui si è operata la condizione o su un
Voglio cominciare questa rubrica con una “worst altro è irrilevante: in quest’ultimo caso è solo se-
practice” fra le più orribili, il polimorfismo dei gno di un cattivo assegnamento di responsabilità
poveri. Non che non abbia materiale a disposizio- e della necessità di spostare l’eventuale metodo al
ne per decine e decine di rubriche, e centinaia di posto giusto.
esempi di come non si dovrebbe scrivere del codice
in Java... ma questa particolare pratica, oltre a es- a.faiQualcosa()
sere veramente brutta, ha delle caratteristiche che
secondo me la rendono unica. E per questo deve È evidente come il vero polimorfismo sia infinita-
avere l’onore del primo numero di questa rubrica mente superiore alla sua brutta copia: l’”if ” viene
dedicata alle brutture nel design. fatto dal runtime automaticamente, e voi non
dovete fare nulla di particolare se non usare degli
• È assolutamente non necessaria, e l’alternativa è oggetti in maniera polimorfa. Il polimorfismo dei
nell’abc della programmazione ad oggetti poveri invece va invece mantenuto, ogni volta che
• Non offre nessun vantaggio particolare rispetto si introducono nuovi tipi e nuove logiche: di solito
all’alternativa corretta, ma solo svantaggi. Altre fra l’altro questo tipo di strutture condizionali si
brutture perlomeno hanno una qualche giustifi- trovano ripetute in diversi punti del codice, poi-
cazione più o meno fondata, questa no. chè è molto comune che esistano diverse logiche
• È incredibilmente diffusa da eseguire, rendendo l’introduzione di bug così
probabile da essere quasi scontata. Il vero poli-
Il polimorfismo dei poveri è caratterizzato da codi- morfismo invece vi permette semplicemente di
ce simile a questo: aggiungere nuovi metodi per ogni nuova logica,
concentrando così in unico punto tutto ciò che ha

62 n.1 - novembre/dicembre 2006


IDIOMATICA
FREESPEECH Login Topic

gli stessi motivi per cambiare. Esercizi:

Eseguite per curiosità un bel Eliminare il polimorfismo dei poveri da uno qual-
siasi degli esempi Swing del jdk. Come dite? Eh no,
grep -R instanceof . così bisogna rivedere le gerarchie... e poi inserire
nuove interfacce. E poi bisogna eliminare quelle
nella directory demo del vostro JDK, e troverete istanziazioni di oggetti concreti... bene, quella si
molti esempi di poliformismo dei poveri. Sembra chiama programmazione ad oggetti.
che Swing sia un portatore (sano?) di polimorfi- Ora salutate con la manina quella brutta e vecchia
smo dei poveri! programmazione strutturata, e cercate di lasciar-
vela per sempre alle spalle!

Permettetemi di riformulare il concetto in maniera


più immediata: se trovate del codice che usa “il po- Conclusioni:
limorfismo dei poveri”, è codice strutturato e non
codice ad oggetti. Che sia nelle librerie di java, che Il polimorfismo dei poveri è una delle peggiori
l’autore sia considerato un guru, che sia uno dei pratiche che si possa adottare per avere codice dif-
software open più blasonati, che l’abbiate trovato ficilmente manutenibile, inutilmente complicato e
su un libro (di solito di API, non certo di design), soggetto a bug. Il polimorfismo dei poveri indica
o che l’abbiate scritto voi stessi in quello che con- inoltre che non state sfruttando la potenza degli
siderate il vostro capolavoro di programmazione oggetti. Se siete pagati per linee di codice, o per
ad oggetti, non cambia la sostanza: non sarà che bug risolti, usatelo pure liberamente! Ma se poi
in 20 anni questa benedetta programmazione ad vi trovate nei guai, non dite che nessuno vi aveva
oggetti a molti non è ancora entrata in testa? avvertito...

n.1 - novembre/dicembre 2006 63


COMMUNITY
FREESPEECH Login Topic

Intervista a Daniela Ruggeri,


presidente della
Java Italian Association
Inaguriamo lo spazio community intervistando il
Ü di di Michele Sciabarrà
presidente di una delle più “antiche” associazioni di (michele.sciabarra@javajournal.it)
sviluppatori Java, il JIA (Java Italian Association).

JJ: Ciao Daniela, ci racconti che cosa è il JIA e da JJ: Dalla tua posizione di osservatore privilegia-
quando tempo esiste? to, come ti sembra sia cambiato il mondo Java in
questi anni?
DR: la Java Italian Association è nata l’11/12/1997 da-
vanti ad un notaio di Roma grazie alla volontà di un DR: Moltissimo. Ho assistito a cambiamenti radicali su
gruppo di amanti della tecnologia java. Questa associa- questa tecnologia e visto nascere il mondo opensource
zione senza scopo di lucro, costituita da 66 soci fondato- che ben si integra con esso.Ho visto la proliferazione di
ri, è un punto di riferimento sia per il mondo del lavoro un gran numero di prodotti di ogni genere e qualità, di
che per quello della scuola. Tramite JIA è possibile per i framework che permettono di risparmiare tempo: sono
soci anche ottenere una visibilità maggiore, promoven- basati su scheletri gestiti da elementi descrittivi spesso
do la loro professionalità attraverso la docenza in corsi o di tipo xml, a partire dei quali è possibile generare codi-
seminari java, o nella scrittura di articoli o in altre occu- ce e costruire per esempio interi portali.
pazioni sociali e culturali utili alla comunità Java. Nello Tuttavia non sono completamente favorevole ai fra-
statuto sono descritte in dettaglio tutte le attività di cui mework perché se da una parte permettono di generare
ci JIA si può occupare. un prodotto con meno errori perché si deve intervenire
meno nel codice, spesso per imparare ad usarli occor-
re un tempo superiore alla vita del framework stesso.
JJ: Quali sono le attività più interessanti che ri- Inoltre sono spesso invasivi nel codice e, a causa del
cordi del JIA in questi anni? livello più alto di astrazione, non sono facili da gestire
se qualcosa non funziona, o se si devono effettuare delle
DR: Ne abbiamo fatte veramente tante: la produzione personalizzazioni pesanti.
di CD, la partecipazione a seminari a conferenze im-
portanti, la traduzione di corsi java dall’inglese... Direi JJ: Come sono i rapporti con i vari Java User
che il progetto più interessante è stato il progetto scuola Group?
diretto a docenti e studenti di scuola media e realizzato
assieme alla società Sun Microsystems e al Ministero DR: C’è stata un po’ di diffidenza iniziale e qualche
dell’Istruzione, Università e Ricerca nel 2003. Adesso, incomprensione. Ma confido in un futuro denso di col-
nel 2006, siamo in partenza con la seconda release. laborazioni anche perché abbiamo un obiettivo comune
Nel 2003 Il progetto comprendeva tre corsi web in che è la divulgazione di Java e non avrebbe molto senso
lingua inglese fornito dalla società Sun Microsytems fare una guerra tra “fratelli” perché sarebbe contropro-
mentre JIA forniva i tutor di supporto ai docenti sui ducente per tutti. Inoltre non vedo JIA in contrapposi-
corsi java. Il progetto ha previsto anche la realizzazione zione con i JUG. JIA non è un JUG perché porta avanti
di un mini-portale, che è partito il 15 Gennaio con la temi sociali che siano utili a tutti, anche verso le cate-
pre-registrazione degli studenti e degli insegnanti dopo gorie meno esperte e disagiate. I JUG invece possono
un incontro con la stampa avvenuto a Milano in data occuparsi di tematiche più avanzate e all’avanguardia.
10/1/2003. La sua durata è stata di circa un anno. Nel Oggi esistono più JUG a livello locale, questo sicura-
2006 invece il progetto riguarda la possibilità di par- mente facilita gli incontri dal vivo e in questo modo si
tecipare ai corsi del programma SAI (Sun Accademic possono creare collaborazioni inter-jug. Questa cosa nel
Initiative della Sun Microsystems). Anche questa volta JIA non si può fare perché essendo una realtà nazionale
JIA fornisce i tutor di supporto ai docenti sui corsi java. ha maggiori difficoltà ad organizzare incontri dal vivo.

64 n.1 - novembre/dicembre 2006


COMMUNITY
FREESPEECH Login Topic

RIQUADRO 1 La Java Italian Association caso che sia molto difficile impararla e applicarla nella
maniera adeguata...

La Java Italian Association (http://www.jia.it) è JJ: Cosa vorresti che succedesse nel mondo Java
un’associazione senza scopo di lucro, costituita da 66 nei prossimi anni?
soci fondatori nel 1997 ed è un punto di riferimen- DR: Il futuro dei prossimi anni è del mobile e del voip.
to sia per il mondo del lavoro che per quello della Java è fatto apposta per questi mondi.
scuola. I suoi obiettivi riguardano la divulgazione Ma se nei prossimi anni esplodesse la robotica e la demo-
del linguaggio java e delle tecnologie emergenti con tica sarebbe il massimo poter applicare java anche qui.
ogni mezzo come seminari, articoli e progetti. Tra
le attività più importanti ci sono il progetto “Java JJ: E che cosa temi di più?
a Scuola” organizzato in collaborazione con Sun
Microsystems e con il Ministero dell’Istruzione per la DR: Non esistono linguaggi che un programmatore
formazione java di studenti e docenti di scuola media può temere ma la precarietà del mercato si. Soprattutto
superiore (http://www.jia.it/modules.php?name=C quando in particolare l’Italia ha la concorrenza di paesi
ontent&pa=showpage&pid=93) e “Tecknos” (http: come Cina, Romania, India ecc. dove esistono università
//www.tecknos.it) la conferenza sull’Innovazione anche migliori delle nostre che permettono di preparare
Tecnologica organizzata con la società Apai (http: programmatori molto validi disposti a lavorare a costi
//www.apai.biz) a Sarzana (La Spezia) con lo scopo bassissimi.
di far aumentare il contributo tecnologico italiano in
JJ: Mi racconti un aneddoto divertente che ti è ca-
Europa.
pitato in questi anni come presidente del JIA?

DR: Non ricordo molti aneddoti divertenti, gestire


JJ: Perché esiste un Linux Day organizzato dalla
un’associazione, soprattutto virtuale, è un’attività
Italian Linux Society e non esiste un Java Day (al
faticosa e densa di problemi. In tutti questi anni ho
di là dell’annuale conferenza annuale di Sun) ?
avuto gioie derivanti da una crescita professionale che
un’associazione di questo genere ha l’opportunità di
DR: Java non è come Linux: essendo un sistema ope- dare, mediante l’incontro con persone di alto livello
rativo può coinvolgere un maggior numero di persone tecnico e derivanti dal fatto di essere veramente utili
anche non tecniche e quindi ottenere un pubblico nu- nel divulgare una tecnologia interessante come Java.
meroso in tali conferenze. Java finora ha interessato Ma ho avuto anche dolori derivanti da critiche e scontri
soprattutto tecnici e quindi un numero nazionale di che in ogni caso però vedo sempre positive perché riten-
persone piuttosto ristretto. Tuttavia il coinvolgimen- go che le esperienze negative (forse maggiormente di
to delle scuole e la diffusione di questa tecnologia quelle positive) contribuiscono a far maturare e a non
con i cellulari, ha fatto si che anche persone meno far ripetere determinati errori commessi per leggerezza.
esperte venissero a conoscenza di java. Proprio in La cosa che comunque giudico molto divertente è quan-
questi giorni si sta tentando di organizzare un java- do finalmente ci si incontra tra noi soci in qualche riu-
day e stiamo decidendo le date e le città dove tenerlo. nione o conferenza per raccontare le nostre esperienze,
presiedere uno stand o tenere un seminario. Ma penso
JJ: Come vedi la “concorrenza” a Java di linguaggi che questa sia una sensazione comune di tutte le comu-
come C# dal versante Microsoft? nità in genere.
DR: Non la vedo proprio. Prima di tutto i programma-
tori che amavano Java hanno continuato ad amarlo an-
che dopo; Java è sicuramente più famoso e più presente
nella mente dei clienti. Anche Microsoft ha deciso di
occuparsi di nuovo del linguaggio Java perché proba-
bilmente si è resa conto che abbracciava un ramo del
mercato troppo esteso per ignorarlo.... Note Biografiche

Daniela Ruggeri è laureata in Matematica presso l’Universi-


JJ: E come vedi PHP/Python/Perl/Ruby dal mondo
tà di Studi di Roma. Si occupa di Informatica dal 1982 e di
Open Source? Java dal 1995. È socio fondatore e Presidente della Java Ita-
DR: Questa è una domanda interessante perché sembra lian Association ed uno dei fondatori di Mokabyte la prima
che le nuove leve (ragazzini di 16-18 anni) amino molto rivista online dedicata a Java, per la quale ha scritto 17 arti-
questi linguaggi perché più immediati. Però non dimen- coli. È autrice di vari articoli e ha tenuto diversi seminari per
tichiamoci che con questi linguaggi si costruiscono ar- diverse manifestazioni come Inforscuola, Webbit e Infome-
chitetture non molto robuste. Java non è un linguaggio dia. Ricopre attualmente la figura professionale di quadro
come senior consultant presso la società Aubay SPA (http:
ma una tecnologia insegnata all’Università. Non è un //www.aubay.it)

n.1 - novembre/dicembre 2006 65

Potrebbero piacerti anche