Professional Documents
Culture Documents
it EDITORIALE
JAVA Journal
BIMESTRALE - ANNO 1 - N.2
DIRETTORE RESPONSABILE
Java Journal
MARIALETIZIA MARI
(MMARI@INFOMEDIA.IT)
DIRETTORE ESECUTIVO
in presa
diretta
MICHELE SCABARRÀ
(MICHELE.SCIABARRA@JAVAJOURNAL.IT)
EDITORIAL BOARD
UGO LANDINI, STEFANO SANNA,
TO N Y M O B I L Y
COLLABORATORI
M I C H E L E FE R R E T T I
UGO LANDINI
STEFANO SANNA In occasione del secondo numero di una rivista, Java Journal compresa, non è cer-
EDOARDO SCHEPIS to tempo di bilanci; però un resoconto su come sono andate le cose dopo il primo
FA B I O S T A R O numero si può dire. Innanzitutto, la rivista sta riscuotendo interesse. A riprova
MATTEO ZINATO di ciò abbiamo ottenuto un primo riscontro anche dalla casa madre di Java, Sun
Microsystems, dalla quale siamo completamente indipendenti, ma con cui siamo
onorati, quando vi è occasione, di poter collaborare. E in effetti una prima forma di
collaborazione si è concretizzata in occasione dell’evento più importante nel mondo
Java, non solo degli ultimi mesi.
Tra l’uscita del primo numero e la preparazione del secondo, è avvenuta una delle più
importanti transizioni per Java: l’annuncio del rilascio dei sorgenti Java in licenza
GPL. Dopo tanti anni, Java diventa, finalmente e definitivamente, un prodotto sia
GRUPPO EDITORIALE INFOMEDIA SRL
Open Source sia Free Software. In questo modo, Java soddisfa anche i palati più
V I A V A L D E R A P. 1 1 6 esigenti in fatto di “apertura” e di “libertà” della piattaforma.
5 6 0 3 8 PO N S A C C O ( P I ) I T A L I A In seguito a questo importante avvenimento, abbiamo avuto occasione di poter
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 intervistare, su invito di Sun, il principale artefice di questa trasformazione: Simon
E-MAIL INFO@INFOMEDIA.IT Phipps. Simon, per chi non è addentro agli organigrammi di Sun, è il direttore delle
S I T O W E B W W W. I N F O M E D I A . I T iniziative Open Source di Sun. Prima di lavorare in Sun è stato un importante pro-
tagonista della adozione di Java, XML e dell’Open Source in IBM. Un personaggio
DIREZIONE chiave, quindi, di indiscussa rilevanza.
N A T A L E FI N O (NFINO@INFOMEDIA.IT) E il sottoscritto, vostro umile (ma fiero) direttore della neonata Java Journal, ha avu-
to l’onore di intervistarlo nel corso di una sua visita in Italia, a Milano. Nonostante
CONTATTI l’apprensione del dover sostenere, e in inglese, la prima intervista “ufficiale” per
Java Journal con un personaggio di tale spessore, sono sopravvissuto indenne. E gra-
TE C H N I C A L B O O K zie agli anni di analisi delle problematiche dell’Open Source, gli ho posto un numero
(BOOK@INFOMEDIA.IT) di domande, abbastanza dettagliate. Troverete in questo stesso numero l’intervista
a Phipps, ovviamente … tradotta in italiano (un buon motivo in più per sostenere le
MARKETING & ADVERTISING iniziative di Java Journal).
SEGRETERIA: 0587736460
MARKETING@INFOMEDIA.IT
Detto questo, passiamo alle “comunicazioni di servizio”. Innanzitutto, abbiamo de-
ciso di utilizzare meglio lo spazio cartaceo, e di eliminare il corso base di Java, che
AMMINISTRAZIONE abbiamo invece sostituito con un videocorso. Il videocorso era nato in altri contesti,
(AMMINISTRAZIONE@INFOMEDIA.IT)
ma ho avuto la possibilità di portarlo in dote alla rivista Java Journal. Questo video-
SEGRETERIA corso lo abbiamo anche offerto gratuitamente a tutti coloro che si sono abbonati fino
(INFO@INFOMEDIA.IT) al 31 gennaio 2007.
Inoltre, da questo numero Stefano Sanna inaugura la rubrica “Community Watch”,
GRAFICA in cui ci parla di delle varie iniziative in corso nella comunità Java, di cui è, da sem-
STEFANO BELLANI pre, un membro attivissimo.
(GRAFICA@GRUPPOINFOMEDIA.IT)
Lo speciale di questo numero riguarda la Java Micro Edition (Java ME), che riscuote
sempre più interesse. E non è un caso che il primo codice di Java disponibile come
UFFICIO ABBONAMENTI Open Source sia proprio una implementazione di Java ME. Detto questo, non mi
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 resta che passare la mano ai collaboratori di questo secondo numero: gli argomenti
ABBONAMENTI@INFOMEDIA.IT presentati sono tutti molto interessanti e gli articoli, come potrete apprezzare, sono
W W W. I N F O M E D I A . I T stati redatti da professionisti di ampia e consolidata esperienza.
JAVA E TUTTI I MARCHI DERIVATI
SONO MARCHI O MARCHI REGISTRATI
DI SUN MICROSYSTEMS, INC. NEGLI Michele Sciabarrà
U S A E I N A L T R I PA E S I . I L G R U P P O Direttore Esecutivo
EDITORIALE INFOMEDIA È INDIPEN- Java Journal
DENTE DA SUN MICROSYSTEMS, INC.
Educational
Apache Ant
di Michele Ferretti 31
Java 5, le buone nuove e le novità meno buone
Seconda parte
di Ugo Landini 38
Focus
Resource Management con JMX
di Fabio Staro 49
Accedere a file di Excel in Java
di Luigi Zanderighi 63
Rubriche
Community
Intervista a Simon Phipps
Chief Open Source Officer di Sun Microsystems
di Michele Sciabarrà 46
Community Watch
di Stefano Sanna 60
Idiomatica
Codice orribile, antipattern e pratiche discutibili
di Ugo Landini 61
JAVA JOURNAL 2
speciale Java Micro Edition JAVA Journal
I package
opzionali della
Java Micro Edition
In questo articolo prendiamo in considerazione le principali librerie della Java Micro Edition,
orientate allo sviluppo di applicazioni per dispostivi mobili, tra cui cellulari, smartphone, PDA e
palmari
D
Dal lavoro del JCP vengono fuori tutte le JSR sulle
quali si basano le applicazioni Java attualmente
opo una breve panoramica sulla realizzate nel mondo, negli ambiti Java Standard,
tecnologia e sulle principali im- Enterprise e Micro Edition.
plementazioni oggi presenti sul Per un breve elenco delle principali JSR relative alla
mercato, sposteremo l’attenzione diverse Edition della piattaforma Java rimandiamo al
su quali novità ci riserva il futuro. Riquadro 1. Nel seguito ci occuperemo più in detta-
Sfruttando le API ancora in fase glio di quelle legate alla Micro Edition.
di studio vedremo come sarà pos-
sibile ben presto gestire direttamente da una nostra Le origini della Java Micro Edition
applicazione:
Al momento della sua nascita (parliamo dell’anno
• una conversazione telefonica, 1999) la Java Micro Edition costituiva più che altro il
• i micropagamenti, tentativo di portare Java là dove esisteva solo tecno-
• ed anche una trasmissione interattiva del digitale logia embedded proprietaria. Nessun altro operatore
terrestre. tecnologico nel campo del software aveva investito
abbastanza in quell’area, lasciando così che ciascun
Per capire quanto sia articolato e vario il mondo delle produttore di hardware si occupasse dello sviluppo
specifiche Java in campo Micro Edition dobbiamo in- del software secondo modalità e specifiche del tutto
nanzitutto fare qualche premessa riguardante il pro- chiuse e proprietarie.
cesso relativo alla loro stesura e implementazione.
Il primo tentativo di rompere con questo approccio
Il Java Community Process fu fatto con l’obiettivo di permettere agli svilup-
patori Java di creare proprie applicazioni anche
Tutto nasce, e direi cresce, nell’ambito del Java su quei dispositivi che fino ad allora erano rimasti
Community Process (JCP): una organizzazione com- accessibili solo nei laboratori delle aziende produt-
posta da membri attivi, aperta a tutti (chiunque può trici.
prendervi parte), che si occupa della stesura e dello Si partì con un approccio a dir poco analitico: biso-
sviluppo delle specifiche tecniche nel mondo Java: le gnava innanzitutto classificare il vasto mondo della
cosiddette Java Specification Requests (JSR). tecnologia “micro”; e non era certo semplice. In que-
st’area rientravano infatti le smart card, i dispositivi
Il JCP ha come compito principale quello di defini- mobili con cui oggi abbiamo maggiore confidenza
re ed alimentare l’evoluzione della tecnologia Java, (cellulari e PDA), ma anche i navigatori satellitari
assicurandone un elevato livello di stabilità e di delle nostre automobili e i decoder del digitale ter-
interoperabilità proprio grazie alla partecipazione al restre tanto in voga oggi. Si iniziò così a parlare di
processo di tutti i suoi membri. configuration e profile.
RIQUADRO 1 Elenco delle principali JSR presenti nella Java Enterprise e nella Standard Edition
Elenco delle principali JSR presenti nella Java Enterprise e nella Standard Edition
Nella tabella di seguito sono riportate le principali JSR definite per le piattaforma Java Enterprise, Standard e Micro
Edition.
È possibile approfondire lo studio di ciascuna di esse collegandosi al sito “http://www.jcp.org/en/jsr/detail?id=” se-
guito dal numero della JSR di interesse.
Nel sito è possibile trovare un documento contenente le specifiche e una reference implementation da utilizzare per lo
sviluppo software.
è rivelato dannoso per la complessità e la poca chiarezza l’evoluzione della tecnologia rischia di essere un freno. Nel
delle specifiche e delle interfacce a disposizione dei pro- prossimo paragrafo vedremo come il JCP ha perciò iniziato
grammatori). a rilasciare numerose JSR che vengono definite opzionali
in quanto non rientrano nella categoria di configuration o
È così che il JCP decide di risolvere questa esigenza gesten- profile e che il costruttore di hardware può decidere di in-
do l’evoluzione della tecnologia Java ME con l’approccio a cluderle o meno nei propri prodotti.
package. Nulla di nuovo sotto il sole, si tratta di quanto vie-
ne normalmente fatto in area Enterprise e Standard, ma in Alcuni di questi optional package sono ormai degli standard
area Micro c’è un problema da non sottovalutare. de-facto, perché presenti sulla maggior parte dei dispositi-
Se infatti nelle altre Edition rilasciare una nuova libreria vi; altri sono delle vere e proprie chimere … al cui insegui-
significa rilasciare una JSR con relativa reference imple- mento si gettano gli sviluppatori più smaliziati.
mentation e permettere così allo sviluppatore di utilizzarla
includendola nel suo ambiente Java Runtime, in ambito
Micro non è altrettanto immediato.
In Java ME, infatti, si ha a che fare con il firmware! Ossia
le API di una certa JSR vivono all’interno dell’ambiente
di esecuzione, inglobate nel dispositivo. In altre parole
una nuova versione di MIDP o una nuova libreria potrà Sull’emulatore fun-
vedere la luce solo su un nuovo cellulare; mentre i prodotti
rilasciati fino ad allora non avranno alcuna possibilità di
ziona tutto… ma non sui
evoluzione. dispositivi!
Non si tratta né di una scelta del JCP né dei costruttori del-
l’hardware, ma di una esigenza imprescindibile del settore
tecnologico di riferimento. Infatti, in questo settore ogni
libreria ha una sua implementazione solo se è strettamente
agganciata all’hardware sul quale risiede.
Tanto per fare un esempio: le librerie per la gestione del di- Optional package: lo stato dell’arte
splay incluse in MIDP permettono la visualizzazione di im-
magini ad una risoluzione che verrà scelta e implementata Si potrebbe proseguire nella panoramica delle JSR in area
da ciascun costruttore di cellulari in modo proprietario. Java ME passo dopo passo, ma dopo la “relazione intro-
Se da una parte lo sviluppatore ha a disposizione una API duttiva” sulla teoria, penso sia proprio ora di passare ai
(interfacce) standard, dall’altra il costruttore ha il compito risvolti pratici di quanto si è detto. Perciò, affronteremo in
(non banale) di tradurre l’astrazione in implementazione dettaglio i presupposti dello sviluppo di applicazioni basa-
effettiva. E ciò, se per gli sviluppatori può essere sicura- te sulle tecnologie CLDC e MIDP, perché di maggior uso e
mente visto come un vantaggio, dal punto di vista del- diffusione sul mercato: infatti, il numero di cellulari sui
quali è possibile trovare una implementazione Java ME è Nel mondo Java ME ciò continua a valere, a patto che nes-
in frenetica crescita! suno dimentichi cosa offre il mercato e le specificità delle
In Figura 2 è possibile vedere il trend positivo del 2005: implementazioni: la qual cosa è valida anche nelle altre
tanto per fornire qualche numero, siamo di fronte a 635 edition, ma di fatto è esasperata in questo settore.
diversi modelli di cellulari, pari a più di 700 milioni di uni- Rischiando di somigliare un po’ troppo a Monsieur de la
tà installate. In altre parole, più di 7 cellulari su 10 hanno Palice (il più illustre “lapalissiano”), potrei dire:
una Java Virtual Machine a bordo!
• non basta una JVM, ma serve una JVM più le librerie
necessarie all’esecuzione dell’applicazione.
Abbiamo visto che CLDC e MIDP coprono le aree principali In pratica, se volessimo implementare in Java un’applica-
per lo sviluppo di applicazioni per cellulari. E allora di co- zione “a caso” per il nostro cellulare, che permetta di ac-
s’altro si avrebbe bisogno? quistare dalla rete dei brani musicali, salvarli sul cellulare,
Se da una parte CLDC e MIDP rappresentano un supporto ascoltarli e scambiarli con gli amici attraverso messaggi e/o
essenziale per lo sviluppo di applicazioni (fornendo i mat- via Bluetooth avremmo bisogno che il suddetto cellulare
toni base e le API per l’accesso alla grafica di alto e basso supporti, oltre a CLDC e MIDP, anche le sopra citate cinque
livello e alla rete), dall’altra parte gli sviluppatori hanno API opzionali.
sin dall’inizio notato alcune carenze.
Alcune aree, infatti, furono demandate in apposite JSR, Siamo al punto di svolta. Da un mercato pervaso di di-
che iniziarono a popolare i cosiddetti optional package. spositivi Java-based ci spostiamo verso un sottoinsieme:
La gestione della messaggistica (CBS, ossia Cell Broadcast significativo, ma pur sempre un sottoinsieme. Non tutti
System, SMS, ossia Short Messaging System, e MMS, ossia i cellulari hanno infatti a bordo queste librerie e quindi
Multimedia Messaging System), delle connessioni via Blue- la nostra applicazione potrà funzionare solo in tale sot-
tooth, dell’audio, della grafica avanzata e del file system toinsieme.
del cellulare, sono funzionalità lasciate al di fuori del
MIDP e di competenza di alcune librerie opzionali. Lo stato dell’arte delle implementazioni Java ME in
Ecco allora che viene alla luce il vero significato di optional quest’area ci permette di dire che ad oggi i cellulari con
packages: questi package a bordo (non più da considerarsi opzionali
a nostro avviso) sono la maggior parte, e comunque sono
• un costruttore di cellulari per fregiarsi del marchio Java quelli di riferimento per il mercato. Il che assicura una
On Board deve implementare CLDC e MIDP, poi ha la grande diffusione, almeno potenziale, della nostra appli-
facoltà di includere quanti e quali package opzionali de- cazione.
sidera.
Ma c’è dell’altro. Non paghi di questo scenario i nostri svi-
Gli sviluppatori, quindi, sono costretti a fare i conti con luppatori, sempre alla ricerca della sottile linea di confine
questa frammentazione, affidandosi ad una nuova acce- “tra la scienza e la fantascienza”, hanno “sollevato altre
zione del motto vincente di Java “Write Once, Run Anywhere” eccezioni” e sono alla ricerca di un giusto “catch”: mi pia-
(ossia, una volta scritta, la mia applicazione sarà eseguita cerebbe gestire il segnale GPS per localizzare l’utente; e se volessi
dappertutto, basta che sia installata una Java Virtual Ma- interagire con i Webc service? E se volessi creare un’applicazione di
chine). segreteria telefonica per il mio cellulare?
Da qui in poi entriamo in un campo minato; e ci entriamo delle applicazioni perfettamente integrato (il Sun
bendati! Ci avventuriamo, cioè, in un settore che sa poco di Wireless Toolkit) che li supporta in tutte le fasi del
implementazione e ancora troppo di specifiche. ciclo di vita del software.
Molte delle JSR sono ancora poco diffuse sui cellulari, ma
è già possibile utilizzarle nell’emulatore. Più precisamente
si tratta delle:
Un profile sono le
•
•
Security and Trust Services API (JSR 177);
SIP API (JSR 180);
API che forniscono il • J2ME Web Services Specification (JSR 172).
tion Framework (GCF) L’implementazione del GCF residente sul cellulare inter-
pretando l’URL capirà di dover creare una HttpConnection
verso l’host specificato e così via per altri casi.
SocketConnection socketConn =
(SocketConnection)Connector.open(“socket://myhost.com:8081”);
Il Generic Connection Framework
Crediamo di non fare torto a nessuno dicendo che la più Per accedere ad una risorsa presente nel filesystem del
grande spinta per la diffusione dello sviluppo in Java ME, cellulare:
e che permette allo sviluppatore di creare in pochissimo
tempo una applicazione completa, sia stato il Generic Con- FileConnection fileConn =
nection Framework (GCF). Si tratta di un meccanismo per (FileConnection) Connector.open(“file:///myMusic.mp3”);
la creazione di connessioni che consente di astrarsi dallo
specifico dell’implementazione sottostante. Il vantaggio Per creare una connessione utile all’invio di un SMS:
dell’approccio per astrazioni qui raddoppia: infatti, oltre
ad avere a che fare con una macchina virtuale, in Java ME MessageConnection msgConn =
si ha il notevole vantaggio di poter creare connessioni di (MessageConnection) Connector.open(“sms://+12345689:5000”);
diverso tipo verso l’esterno, utilizzando la stessa gerarchia
di classi descritta nella Figura 3.
Approfondimenti sul GCF
Il GCF nasce dal bisogno di avere un sostituto nella Micro
Edition delle librerie java.net e java.io ivi mancanti o ridot- Per tutte le altre sfaccettature relative al GCF, che tra l’altro
te. Si tratta, infatti, di una gerarchia di classi che fornisce può essere utilizzato anche in ambito Java Standard Edi-
proprio un approccio generico alla connettività. Grazie ad tion, si rimanda a http://www.jcp.org/en/jsr/detail?id=197
una gerarchia estendibile di interfacce, ad una factory di e alle risorse reperibili sul sito http://developers.sun.com/
connessioni e all’utilizzo delle specifiche standard degli techtopics/mobility/.
Uniform Resource Locator (URL), lo sviluppatore ha un unico
punto di ingresso verso le connessioni: la classe Connector e
l’interfaccia Connection. Il GCF supporta molte connessioni
e permette di delegare all’implementazione sottostante i Note Biografiche
dettagli per la loro costruzione e tutto passa attraverso lo Edoardo Schepis è Java ME Tech Lead presso Funambol. È stato
schema degli URL. Java Architect in Sun Microsystems e ha fatto parte del grup-
po di lavoro che ha prodotto la certificazione Sun Certified
Il formato generico di un URL è definito nelle RFC 1738 e Mobile Application Developer (SCMAD). Edoardo è il fonda-
2396 ed è il seguente: tore e responsabile del Java Mobile Developers Forum (http:
//www.jmdf.org), community italiana dedicata al mondo Java e
alle tecnologie wireless.
J2ME
Best Practice
La diffusione di J2ME è ormai un dato di fatto
D
quello che sarà l’utilizzatore finale della nostra ap-
plicazione.
Se qualche anno fa c’era grande
scetticismo sulla possibile diffu-
sione di J2ME, oggi si può affer-
mare che la tecnologia Java per la
programmazione dei cellulari si è
ritagliata una discreta porzione di
mercato, forse non grande quan- U n’ a p p l i c a z i o n e
to ci si aspettava, ma sicuramente incoraggiante. Gli
applicativi scritti in C++ sviluppati per Symbian deve essere robusta,
hanno avuto una partenza bruciante e sembravano
dover superare e affossare J2ME; ma relativamente efficiente, chiara da
pochi cellulari si basano su Symbian e la percentua-
le di diffusione del sistema operativo, anche se de-
stinata a crescere, difficilmente andrà a coprire tutto
comprendere, facile da
il mercato dei cellulari. A tutto ciò si aggiunge una
sempre maggiore necessità di sviluppare applicati- modificare ed estendere
vi che siano utilizzabili anche da dispositivi mobili e
sempre più spesso si vedono cellulari inseriti nei dise- nelle funzionalità
gni di architetture di applicazioni enterprise.
Una delle prime cose di cui occuparsi in un’applicazione, public void displayUserForm(){
anche di piccole dimensioni, è l’organizzazione delle classi userForm.clearForm();
e la suddivisione in package. È vero che con i moderni IDE display.setCurrent(userForm);
per lo sviluppo Java il refactoring delle classi e la riorga- }
nizzazione in package è molto semplice, ma è sempre
bene partire organizzando il lavoro nel giusto modo. La public void displayUserForm(
scelta delle funzionalità che una classe deve compiere (in Contact user){
altre parole i metodi che deve avere) non è soltanto una userForm.loadForm(user);
questione di pulizia o di stile del codice, ma va anche ad display.setCurrent(userForm);
influire sulle prestazioni dell’applicativo. Infatti le classi di }
una midlet vengono caricate in memoria solo al momento
dell’utilizzo, per cui, dovremmo riuscire a raggruppare le public void displayUserList(){
funzionalità nelle giuste classi, in modo che se l’utente uti- userList.loadUserList(“”, “”);
lizza solo una determinata funzionalità dell’applicativo, il display.setCurrent(userList);
sistema non vada a caricare anche classi che non vengono }
utilizzate, se non per un metodo.
Facciamo un esempio: se scriviamo in una classe tutti i public void displaySearchUserList(
metodi per l’accesso al database locale (RMS) e in un’altra String name, String surname){
classe tutti i metodi per l’accesso ai dati in remoto sul server userList.loadUserList(name, surname);
(con connessioni http) e l’utente utilizza l’applicativo solo display.setCurrent(userList);
nelle funzionalità di salvataggio in locale, tutte le altre classi }
non verranno caricate, con un risparmio nel tempo di esecu-
zione e soprattutto nella memoria occupata a runtime. public void displayUserSearch(){
Invece, per quanto riguarda l’organizzazione delle classi display.setCurrent(userSearchForm);
in package la strategia non influisce sulle prestazioni e }
sull’efficienza dell’applicativo, ma soprattutto sull’ordine
delle classi all’interno del progetto (e non è poco…).
LISTATO 1 Alcuni metodi della classe UIController
UIController uiController = null; serie di immagini, disegna delle forme geometriche e scri-
ve del testo. In casi come questo si deve valutare l’utilizzo
protected void startApp() throws della lazy initialization delle classi (“lazy” letteralmente
MIDletStateChangeException { significa “pigro”, e in questo caso assume il significato di
“solo quando serve”). Questa tecnica consiste nel caricare
// ... l’istanza di una classe solo quando si è sicuri che verrà
uiController = new UIController(this); utilizzata e cioè un attimo prima di caricarla sullo schermo
} (Listato 3 e Listato 4).
di testo che caratterizza- • Informare sempre l’utente su quello che sta facendo l’applica-
zione durante le operazioni che richiedono qualche secondo.
no le interfacce grafiche
Ciò, banalmente, per evitare che l’utente pensi che l’ap-
in un’unica classe plicazione si sia bloccata. In questo caso è sufficiente pre-
disporre un oggetto di tipo Gauge che viene aggiornato al
momento della creazione delle singole istanze delle classi
della nostra applicazione (Listato 5).
loadingForm.updateProgress();
col l’ausilio dei thread userForm = new ContactForm(this);
loadingForm.updateProgress();
userList = new ContactList(this);
loadingForm.updateProgress();
Internazionalizzazione delle applicazioni userSearchForm =
new ContactSearchForm(this);
Al di là del fatto che l’applicazione che dobbiamo svilup-
pare debba essere tradotta o meno in altre lingue, è buona loadingForm.updateProgress();
norma raggruppare tutte le stringhe di testo che caratteriz- connectionSaveForm =
zano le interfacce grafiche in un’unica classe. La classe in new ConnectionSaveForm(this);
questione sarà simile a quella mostrata nel Listato 6.
In questo modo, la traduzione e la distribuzione del- loadingForm.updateProgress();
l’applicazione in altre lingue si ridurrebbe al semplice connectionGetForm =
lavoro di modifica delle etichette contenute nel file new ConnectionGetForm(this);
LanguageLabel.java, evitando di dover spulciare i singoli file
Java alla ricerca del testo da tradurre. displayMenu();
Programmare ad oggetti }
• “ogni azione associata ad un comando dell’utente deve ritornare FIGURA 5 Menu di opzioni della midlet di
subito il controllo dell’applicazione per non rischiare deadlock”. collegamento con il server
Nel momento in cui l’utente preme il pulsante per inviare permettergli di fermare eventuali operazioni che l’applica-
dei dati al server, l’applicazione non farà altro che far par- zione sta svolgendo (quando queste non sono immediate).
tire un Thread separato, che effettua la connessione e in- Per cui, tornando alla comunicazione delle midlet con il
forma l’utente dello stato di avanzamento delle operazioni; server, è molto importante mantenere informato l’utente
mentre il Thread principale dell’applicazione non subisce e dargli la possibilità di fermare il collegamento se i tempi
nessun tipo di blocco di attesa per lo svolgimento delle si rivelano troppo lunghi (cosa più che normale per le con-
operazioni di comunicazione col server. nessioni GPRS). Vediamo come realizzare in pratica quello
che si è descritto finora (Figura 5).
Visualizzare un’indicazione di avanzamento
Siamo nel caso in cui un utente debba inviare ad un server
Come abbiamo detto nella prima parte dell’articolo, “best una serie di informazioni residenti nella midlet. Dal menù
practice” non vuol dire solamente soluzione tecniche, ma dell’applicazione, l’utente sceglie la voce che corrisponde
anche soluzioni che vadano a favore dell’usabilità dell’ap- all’azione di invio dei dati al server; verrà visualizzata sul
plicazione da parte degli utenti. In questa logica, un fat- display un’istanza di una classe di tipo Form (all’interno
tore molto importante è tenere sempre informato l’utente del package view) che contiene al suo interno un oggetto
di quello che l’applicazione sta facendo, e soprattutto di tipo Gauge, che, a sua volta, visualizzerà l’avanzamento
FIGURA 6 Risultato dell’esecuzione del codice FIGURA 7 Grafico di occupazione della memoria
della classe view prima dell’invocazione della GC
/**
* popola l’oggetto ContactBean partendo /**
* da uno DataInputStream * popola l’oggetto UserBean partendo
* @param DataInputStream * da un array di byte
* @throws IOException * @param data
*/ * @throws IOException
public void deserialize( */
DataInputStream reader ) public void fromByteArray(
throws IOException { byte[] data )
throws IOException {
name = reader.readUTF();
surname = reader.readUTF(); ByteArrayInputStream stream =
long dataLong = reader.readLong(); new ByteArrayInputStream( data );
if (dataLong != 0)
borndate = new Date(dataLong); DataInputStream reader =
telephone = reader.readUTF(); new DataInputStream( stream );
email = reader.readUTF();
} deserialize( reader );
stream.close();
/** }
* restituisce un DataOutputStream
* dei dati dell’utente /**
* @param DataOutputStream * Restituisce una array di byte
* @throws IOException * dell’oggetto utente
*/ * @return
public void serialize( * @throws IOException
DataOutputStream writer ) */
throws IOException { public byte[] toByteArray()
throws IOException {
writer.writeUTF( name );
writer.writeUTF( surname ); ByteArrayOutputStream stream =
if (borndate != null){ new ByteArrayOutputStream();
writer.writeLong(
borndate.getTime()); DataOutputStream writer =
} else { new DataOutputStream(stream);
writer.writeLong(0);
} serialize( writer );
writer.writeUTF(telephone); writer.close();
writer.writeUTF(email);
} return stream.toByteArray();
}
della connessione e del trasferimento dei dati al server. guita in modo indipendente dal resto dell’applicazione. La
Tutta la parte che gestisce la connessione sarà inserita in classe RemoteModel è una classe dell’applicazione che con-
un’apposita classe, a sua volta inserita nel package model tiene al suo interno tutti i metodi alla base di una connes-
in modo da tenere separato il codice di view dal codice di sione HTTP e verrà estesa da tutte le classi che dovranno
model. La classe di view conterrà un codice del tipo riportato eseguire collegamenti col server (Listato 13).
nel Listato 10, il cui risultato è visibile nella Figura 6.
La cosa importante da tenere presente è che il metodo Torniamo ora alla classe RemoteContactSaveList.java con-
performConnection() deve essere esplicitamente invocato centrandoci sul codice contenuto nel metodo run() che,
dall’esterno; per cui, al momento della selezione dell’ope- ricordiamo, viene invocato quando il Thread viene lanciato
razione di invio dei dati al server dovrà essere eseguito il con start(). A parte gli aggiornamenti alla progress bar che
codice riportato nel Listato 11. l’utente vede a video, dopo aver aperto la connessione, ed
aver aperto un outputStream per l’invio dei dati al server
Vediamo ora come è costruita la classe di model per la con- (utilizzando i metodi della superclasse RemoteModel) la
nessione http (Listato 12). La prima cosa che si nota è prima cosa che viene fatta è quella di scrivere nello stream
che la classe estende RemoteModel ed implementa Runnable. in uscita un byte. Il valore di questo byte è quello della
L’implementazione dell’interfaccia Runnable è indispensa- costante MessageConstants.OPERATION_SAVE_USER_LIST.
bile per avere una classe di tipo Thread che può essere ese- Un’operazione di questo tipo viene fatta perché in questo
LISTATO 8 I metodi inseriti nella classe Contact per il salvataggio, l’aggiornamento e la cancellazione
Ai metodi che possono essere eseguiti vengono passati i appende gli eventuali dati di risposta che dal server devono
riferimenti ad un DataInputStream per la lettura di tutti i passare al client.
dati allegati alla richiesta, e un DataOutputStream per la Questo metodo di gestione delle richieste al server è molto
scrittura di tutti i dati di risposta. semplice da realizzare e soprattutto molto facile da man-
Dopo aver terminato l’esecuzione del metodo richiesto, tenere visto che tutte le richieste entrano nell’applicativo
il metodo perform scrive come prima cosa un byte in cui server da un’unica porta di accesso e la logica applicativa
indica che l’esito dell’operazione è positivo e subito dopo di ogni singola richiesta può essere gestita nel modo che
stringItemStatus = /**
new StringItem(“”, “”); * Viene invocato dal Thread
gauge = new Gauge(“”, * Notifica alla classe di view il
false, GAUGE_MAX, 0); * termine delle operazioni.
* Rimuove il tasto di cancel e mette
cmdDone = new Command( * quell di ok.
LanguageLabel.CONFIRM, */
Command.OK, public void notifyFinish() {
0); removeCommand(cmdStop);
addCommand(cmdDone);
cmdStop = new Command( }
LanguageLabel.UNDO,
Command.BACK, public void commandAction(Command c,
0); Displayable d) {
addCommand(cmdStop); if (c == cmdStop){
remote.stop();
append(stringItemStatus); uiController.displayMenu();
append(gauge); }
if (c == cmdDone){
setCommandListener( this ); uiController.displayMenu();
} }
}
/**
* viene creata un’istanza della }
LISTATO 13
Apache Ant
Il progetto Apache mette a disposizione una notevole quantità di software open source, in partico-
lare possiamo trovare parecchie librerie e software utili (e forse indispensabili) allo sviluppo Java.
Uno dei più importanti software di Apache è Ant, la formichina software che lavora per voi
A
XML è la vera forza di questo progetto. La sintassi
nt si basa sui concetti di uno strumento di di XML è universalmente condivisa e semplice da
sviluppo molto vecchio: Make. Make è, ed è apprendere. Nei vecchi Makefile la sintassi era
stato per anni, uno strumento fondamen- particolarmente complessa. Ovunque c’è una virtual
tale per gli sviluppatori software. Make ese- machine Java c’è la possibilità di utilizzare Ant. Make
gue una sequenza di operazioni per ottenere un ri- invece è più difficile da installare proprio per la sua
sultato finale, che di solito è il pacchetto software da natura C.
distribuire. Ant fa lo stesso, ma con maggiore elegan- Make è a tutti gli effetti uno standard in tutti i
za e con un framework a plug-in, che permette di ag- sistemi operativi della famiglia Unix, comprese le
giungere funzionalità codificandole in classi Java. centinaia di distribuzioni Linux. Utilizzare Make
su Windows è un dramma perché siamo costretti a
Make crearci un ambiente particolare per eseguirlo. Ant
è molto più semplice, più flessibile e portabile. Per
Per capire a fondo cosa è e cosa fa Apache Ant, compilare un software Java su Linux, Mac OSX o
bisogna capire quali sono le esigenze che hanno Windows si utilizza sempre lo stesso file XML.
portato gli sviluppatori a crearsi strumenti per In Ant il nome predefinito per un file di build è
velocizzare operazioni ridondanti e noiose. Make è build.xml. Se si lancia il comando “ant” in una
un software che processa dei file di testo denominati directory, il programma cerca un file chiamato
Makefile. I Makefile sono file che contengono direttive build.xml e lo processa. Se non viene specificato il
raggruppate per target. I target sono dei gruppi di target, Ant esegue quello che viene dichiarato come
comandi che permettono di compilare i sorgenti, predefinito all’interno del progetto.
creare archivi dei binari, ecc. Make è nato per essere
utilizzato in ambiente C ma con il tempo è stato Il formato dei file build.xml
utilizzato per parecchi altri compiti.
Come già accennato il formato dei file di build è XML
La filosofia di Ant e la sua struttura può essere riassunta in breve con
questo esempio:
Quando James Duncan Davidson cominciò a
sviluppare Tomcat si trovò di fronte un sacco di <project name=”ProjectName”
sorgenti e parecchie operazioni da eseguire per default=”dist” basedir=”.”>
compilarli. Decise quindi che era arrivato il momento <target name=”dist”>
di creare un nuovo strumento di sviluppo. Ant nacque <!—Lista di task -->
proprio da questa esigenza: poter eseguire una </target>
serie di operazioni indipendentemente dal sistema </project>
operativo. Java, per definizione, è multipiattaforma e
quindi richiede un tool e un formato portabile per la
compilazione delle applicazioni. Il tag project è il contenitore generale di un file
Ovviamente il linguaggio più adatto per creare lo build.xml e al suo interno racchiude diversi blocchi
strumento è Java stesso, e il formato portabile per target. Ogni target al suo interno può contenere
una descrizione e due attributi “if” e “unless” che ne che ci permettono di caricare in automatico l’ultima
determinano l’esecuzione. Un esempio di target completo versione del software su un server FTP e magari segnalare
è il seguente: automaticamente via mail della sua creazione.
Per queste funzionalità esistono già dei task, ma se proprio
<target non vi accontentate potete crearvi un task personalizzato.
name=”compile” L’architettura di Ant è flessibile e permette l’introduzione
depends=”init,setup” di altri task personalizzati. Per creare un proprio task basta
description=”descrizione” estendere la classe Task di Ant. Comunque reputo remota
if=”a” unless=”b”> la necessità di dover scrivere un proprio task.
</target> Fra i più importanti task di terze parti ricordo: JUnit, FTP e
MS Visual SourceSafe. Alcune di questi sono, ovviamente,
Questo target si chiama “compile”, dipende dall’esecuzione utilizzabili solo su piattaforme specifiche. Ad esempio, il
di altri due target “init” e “setup” (nella seguenza indicata task per lavorare con SourceSafe non può essere utilizzato
nell’XML) e sarà eseguito se la variabile “a” sarà settata su Linux proprio perché il software di Microsoft non è
e se la variabile “b” non sarà settata. Pensate quindi ad disponibile per questa piattaforma.
un target specifico, che deve essere eseguito solamente in
un determinato caso; potete valorizzare una variabile che Ant nelle applicazioni Java
rappresenta lo stato booleano di quel caso. Nel caso in cui
quella particolare variabile sarà valorizzata, i task presenti Ant è nato dall’esigenza di sviluppatori Java; infatti i primi
all’interno del target saranno eseguiti. target a nascere sono stati:
Raramente ho utilizzato gli attributi if e unless. Anche
perché è possibile richiamare esplicitamente l’esecuzione di • Javac
un altro target, e di conseguenza condizionarlo. Solamente • Java
il nome è obbligatorio, gli altri attributi possono essere • Javadoc
tralasciati, oppure inseriti in varie combinazioni in base • Jar
alle caratteristiche che dovrà avere il target. Per esempio, if
e unless compaiono di rado insieme. Questi infatti sono presenti fin dagli albori del progetto.
La pratica comune è quella di creare innanzitutto target Ant è un ottimo strumento di sviluppo per un progetto
che racchiudono comandi destinati ad uno scopo preciso. Java e può essere utilizzato per eseguire le varie fasi. Le fasi
Il passo successivo è inserire le dipendenze fra questi standard di un progetto Java, possono essere riassunte in:
target, in modo che l’esecuzione di un target causi a
cascata l’esecuzione di tutti gli altri. Un probabile target 1. Inizializzazione dell’ambiente (init)
“init” potrebbe contenere una lista di task “mkdir”: 2. Compilazione dei sorgenti (compile)
questi creano la struttura del file system di partenza per 3. Creazione dell’archivio jar (build)
la compilazione e la creazione del pacchetto software da 4. Generazione della documentazione Javadoc
distribuire. Esempio: (doc)
5. Creazione del pacchetto per la distribuzione
<target name=”init”> (dist)
<mkdir dir=”build”/> 6. Rimozione dei file generati (clean)
<mkdir dir=”dist”/>
</target> La generazione della documentazione non è necessaria
ma in un progetto che si rispetti lo sviluppatore rilascia
Nella directory “build” andranno a finire i file compilati sempre la documentazione autogenerata da Javadoc. Ad
e nella directory “dist” verrano spostati i file binari e gli ogni voce di questo elenco va associato un target specifico.
altri file che andranno a far parte del pacchetto finale Prendiamo come esempio la preparazione di un pacchetto
da distribuire. Più avanti presenterò un file di build da di rilascio per una classe HelloWord.java. All’interno di
utilizzare per un progetto software Java. questi target farò uso di proprietà che inizializzerò con
visibilità globale nel progetto.
La libreria standard dei task
Inizializzazione dell’ambiente
La libreria standard dei task di Ant è molto vasta e
comprende strumenti basilari per la manipolazione di Preparare un ambiente per il rilascio di un pacchetto,
codice Java ma anche del file system e per altri migliaia significa creare le directory che conterranno i file
di scopi. Non si possono elencare qui tutti i task, pertanto compilati e il resto dei file che andranno a far parte della
nella Tabella 1 è riportata una lista dei più importanti con distribuzione. Questo target lo chiameremo “init” e non
a fianco una breve descrizione. avrà dipendenze con altri target. All’interno di questo
Con i task racchiusi in questa piccola lista è possibile fare target metteremo i task che creeranno le directory.
già parecchie cose. Nella maggior parte dei casi infatti, ci si
limita a creare directory, compilare, spostare e archiviare. <!-- Inizializzazione -->
Quasi tutto il lavoro si basa su operazioni specifiche <target name=”init”>
su file system. Ovviamente è interessante inserire task <mkdir dir=”${build}”/>
vadoc -->
<project name=”HelloWord” default=”dist” base- <target name=”doc”>
dir=”.”> <javadoc packagenames=”com.*”
sourcepath=”${src}”
<!-- proprieta’ utilizzate all’interno dei destdir=”${doc}”
target --> author=”true”
<property name=”src” value=”src” /> version=”true”
<property name=”build” value=”build” /> />
<property name=”dist” value=”dist” /> </target>
<property name=”doc” value=”doc” />
<property name=”version” value=”1.0” /> <!-- Creazione del pacchetto per la di-
stribuzione -->
<!-- Inizializzazione dell’ambiente --> <target name=”dist” depends=”build,doc”>
<target name=”init”> <zip destfile=”${dist}/
<mkdir dir=”${build}”/> ${ant.project.name}-${version}.zip”>
<mkdir dir=”${build}/classes”/> <fileset dir=”.” includes
<mkdir dir=”${dist}”/> =”${ant.project.name}.jar” />
<mkdir dir=”${doc}”/> <fileset dir=”.”
</target> includes=”${doc}/**/*” />
</zip>
<!-- Compilazione dei sorgenti --> </target>
<target name=”compile” depends=”init”>
<javac srcdir=”${src}” <!-- Rimozione dei file e directory gene-
destdir=”${build}/classes” /> rati -->
</target> <target name=”clean”>
<delete dir=”${build}”/>
<!-- Creazione dell’archivio jar --> <delete dir=”${dist}”/>
<target name=”build” depends=”compile”> <delete dir=”${doc}”/>
<jar destfile=”${ant.project.name <delete file=”${ant.project.name}
}.jar” basedir=”${build}/classes”/> .jar”/>
</target> </target>
Compilazione dei sorgenti A questo punto, dobbiamo creare l’archivio jar della classe.
Come per la compilazione, la creazione di un archivio jar
La compilazione dei sorgenti Java è una pratica si basa su un unico task che accetta diversi parametri
fondamentale e si basa tutta sul task Javac, che riproduce di configurazione. Si può creare un archivio partendo
le funzionalità del programma javac, distribuito con il JDK. dal contenuto di una intera directory, oppure si possono
Questo task permette di compilare le classi Java partendo specificare i file, utilizzando anche caratteri wildcard. Nel
da una directory base, dove sono presenti i sorgenti. Si caso specifico, creiamo l’archivio dal contenuto dell’intera
possono specificare i package e molti altri parametri, come directory “classes” presente all’interno della directory
ad esempio il target della JVM. “build”.
Questo target dipende dall’esecuzione del target
precedente. Al suo interno è dichiarato il task Javac <!-- Creazione dell’archivio jar -->
con i parametri “srcdir” e “destdir” che contengono, <target
rispettivamente, la directory dei sorgenti e la directory di name=”build”
destinazione delle classi compilate. depends=”compile”>
<jar destfile=”${ant.project.name}.jar”
<!-- Compilazione dei sorgenti --> basedir=”${build}/classes”/>
<target name=”compile” </target>
depends=”init”>
<javac
# ant
Buildfile: build.xml
init:
[mkdir] Created dir: /Users/michele/Desktop/Articolo Ant/esempi/build
[mkdir] Created dir: /Users/michele/Desktop/Articolo Ant/esempi/build/classes
[mkdir] Created dir: /Users/michele/Desktop/Articolo Ant/esempi/dist
[mkdir] Created dir: /Users/michele/Desktop/Articolo Ant/esempi/doc
compile:
[javac] Compiling 1 source file to /Users/michele/Desktop/Articolo Ant/esempi/build/classes
build:
[jar] Building jar: /Users/michele/Desktop/Articolo Ant/esempi/HelloWord.jar
doc:
[javadoc] Generating Javadoc
[javadoc] Javadoc execution
[javadoc] Loading source files for package com.acme...
[javadoc] Constructing Javadoc information...
[javadoc] Standard Doclet version 1.4.2_09
[javadoc] Building tree for all the packages and classes...
[javadoc] Building index for all the packages and classes...
[javadoc] Building index for all classes...
dist:
[zip] Building zip: /Users/michele/Desktop/Articolo Ant/esempi/dist/HelloWord-1.0.zip
BUILD SUCCESSFUL
Total time: 4 seconds
Generazione della documentazione javadoc la compressione, la lista dei file da includere ecc.
La sua esecuzione dipende da quella del target “build” e
In Java possiamo documentare il codice mentre lo poi del target “doc”.
scriviamo. In un secondo tempo, con lo strumento javadoc,
è possibile generare la documentazione in formato HTML <!-- Creazione del pacchetto per la distribuzione -->
delle classi. In questo target, chiamato “doc” si genera la <target name=”dist” depends=”build,doc”>
documentazione per la classe HelloWord e per tutte quelle <zip
classi che appartengono ad un package che inizia per destfile=”${dist}/${ant.project.name}-${version}.zip”>
“com”. <fileset dir=”.” includes=”${ant.project.name}.jar” />
<fileset dir=”.” includes=”${doc}/**/*” />
<!-- Generazione della </zip>
documentazione javadoc --> </target>
<target name=”doc”>
<javadoc packagenames=”com.*”
Rimozione dei file e directory generati
sourcepath=”${src}”
destdir=»${doc}» Questo target non fa parte di una procedura di build ma
author=»true» definisce tutte le operazioni necessarie affinché l’ambiente
version=»true»/> ritorni nello stato iniziale. Ciò garantisce che in una nuova
</target> procedura di build non si trovi “sporcizia” lasciata dalla
precedente. Questo target si chiama “clean” e va lanciato
Creazione del pacchetto per la distribuzione prima di rieseguire nuovamente il file di build.
Il pacchetto per la distribuzione sarà un file zip <!-- Rimozione dei file
contenente l’archivio jar appena creato e la directory con e directory generati -->
la documentazione. Il task per compiere questa operazione <target name=”clean”>
è zip e, come gli altri, ha una serie di parametri per definire <delete dir=”${build}”/>
Java 5, le buone
nuove e le novità
meno buone
seconda parte
>> di Ugo Landini (ugo.landini@javajournal.it)
C
e così via. Di fatto il compilatore sostituisce l’ellipsis
ontinuiamo la nostra carrellata sulle novi- con un array (di String in questo caso, ma potrebbe
tà di Java5 (linguaggio e piattaforma). Nel- ovviamente essere un array di Object o di quello che
la prima parte abbiamo trattato i Generics, volete), ma vi permette anche di non passare nessun
l’enhanced for, l’autoboxing, gli static im- parametro, cosa molto comoda. Iterare sulla lista di
port, la covarianza e il class sharing. In questa secon- argomenti è quanto di più semplice si possa pensare,
da parte vedremo le concurrent utilities, i typesafe ovviamente usando il nuovo ciclo for:
enums, i varargs e le annotations, ed in più vedremo
cosa bolle in pentola per Java6. for (String feature: features) {
Per tutti coloro che avessero perso la prima parte, System.out.println(feature);
riportiamo la tabella (riassuntiva e molto ad alto }
livello) dei più importanti cambiamenti introdotti in
Java5 (Tabella 1). Essendo di fatto un array, potete ovviamente memo-
rizzare i varargs tramite un semplice assegnamento:
Come dice il nome stesso, con Java5 si può ora dichia- o anche, perché no, passare un array come parame-
rare un metodo con numero variabile di argomenti, tro:
cosa che farà felice qualche programmatore C e farà
probabilmente inorridire i puristi della programma- new Phone(“Nokia”, “6310i”, new String[]{“Bluetooth”,
zione ad oggetti. Questa caratteristica apre anche la “MIDP 1.0”});
porta alla printf, nel più puro stile C. Sia come sia, è
una feature che può sicuramente tornare utile. Un Attenzione però alle conversioni! In qualche (raro)
costruttore con questa signature (notare l’ellipsis, caso, potrebbero interferire con le vostre vere inten-
ossia i 3 puntini) zioni. Supponiamo di voler stampare l’indirizzo di
un array di oggetti, magari per fare debugging, con
public Phone (String manufacturer, String name, questo codice:
String... features)
Object[] array = new String[] {“qualche”, “stringa”,
può essere invocato con: “a caso”}
out.printf(“ Indirizzo dell’array di oggetti: <%s> “,
new Phone(“Nokia”, “6310i”); array);
new Phone(“Nokia”, “6310i”, “Bluetooth”);
new Phone(“Nokia”, “6310i”, “Bluetooth”, “MIDP 1.0”); Essendo il secondo parametro di printf in realtà un va-
rarg, verrà passato il primo parametro dell’array a %s,
e non l’indirizzo come vi aspettereste. Per forzare la mano a Joshua Bloch propose allora una soluzione più o meno
java, bisogna indicare esplicitamente le nostre intenzioni: standard a questo problema, soluzione che potete trovare
nel suo eccellente libro Effective Java [BLOCH], e chiamò
out.printf(“ Indirizzo dell’array di oggetti: <%s> “, questo idioma “type safe enum”
(Object)array);
// idioma typesafe enum: ottimo fino al JDK 1.4
public class Suit {
Typesafe Enums (o Enumerated Types)
public static final Suit CLUBS = new Suit(“clubs”);
I typesafe enum sono un caso di idioma entrato diretta- public static final Suit DIAMONDS = new Suit(“diamonds”);
mente in una nuova release del linguaggio: qui è necessa- public static final Suit HEARTS = new Suit(“hearts”);
ria un po’ di storia per capire meglio. public static final Suit SPADES = new Suit(“spades”);
La keyword enum del C era stata volontariamente tenu- public String toString() {return name;}
ta fuori dal linguaggio Java, poiché non era altro che un private Suit(String name) {this.name = name;}
modo per dare un nome ad un set di costanti intere, senza private final String name;
nessun concetto di type safety. In java un idioma (idioma }
= pattern a livello di linguaggio) standard era quello di
dichiarare delle costanti direttamente nelle classi o in Questo idioma permette ovviamente una maggiore type
un’interfaccia, ma in fondo non era molto meglio del- safety: non c’è modo di usare oggetti di tipo Suit che non
l’equivalente enum in C. siano quelli elencati come static all’interno della classe
stessa: la classe non espone costruttori e non può quindi
// in C neanche essere estesa (se non sapete perché, vi consiglio di
typedef enum {CLUBS, DIAMONDS, HEARTS, SPADES} suit; ripassare i costruttori!), per cui l’idioma è sufficientemente
// in Java: NON USARE robusto.
public class Card { Esistono diverse varianti ed estensioni di questo idioma,
public static final int SUIT_CLUBS = 0; per aggiungere feature come la serializzabilità, l’estendi-
public static final int SUIT_DIAMONDS = 1; bilità, o per gestire tipi ordinali (si noti che nella forma
public static final int SUIT_HEARTS= 2; mostrata utilizza delle stringhe), che complicano legger-
public static final int SUIT_SPADES= 3; mente il tutto. Con Java5 si è deciso dunque di inserire
} questo idioma direttamente all’interno del linguaggio, in
modo da semplificarne un po’ il suo utilizzo, inserendo la sare a soluzioni alternative con “normali” classi. Se avete
parola chiave enum: invece bisogno di una lista di costanti e volete essere sicuri
che il compilatore controlli su eventuali abusi, enum è la
enum Suit {CLUBS, DIAMONDS, HEARTS, SPADES} soluzione perfetta.
Suit current = Suit.DIAMONDS; Le concurrent utilities sono, a mio modo di vedere, la no-
if (current == Suit.HEARTS) ... vità in assoluto più importante di Java5. Ma solo chi ha bi-
sogno di scrivere codice multithreaded ne può apprezzare
Andando più a fondo, una enum non è altro che una classe la portata, molto spesso passa inosservata.
un po’ speciale: Anche qui è d’obbligo un po’ di storia. Java, da sempre, ha
avuto un ottimo supporto alla programmazione concorren-
• usa la keyword enum al posto di class te, tramite le feature implicite in Object (wait() e notify()/no-
• come prima cosa deve dichiarare tutte le sue costanti, tifyAll()), le keyword synchronized e volatile e la classe Thread
prima di qualsiasi attributo o metodo aggiuntivo (e le altre classi/interfacce correlate).
• è implicitamente final, ma non può essere dichiarata
final (poiché non può essere direttamente estesa, ma le
costanti sono di fatto delle classi anonime che la esten-
dono!)
• non può estendere da altre classi perché implicita- I
vararg sono di fatto
mente estende java.lang.Enum e di conseguenza
un array: si possono trat-
o ha un toString() di default (che può ovviamente essere
overridden) che ritorna il nome della costante tare in modo ordinario, ma
o ha un metodo name() che ritorna il nome della costan-
te, e non può essere overridden attenti alle conversioni
o è implicitamente Comparable e implementa corretta-
mente hashCode e equals
o è impossibile da clonare, clone() è final e inoltre ritorna
l’eccezione CloneNotSupportedException
o ha un metodo ordinal() che ritorna il numero ordinale Come è risaputo, questi meccanismi base permettono – per
corrispondente alla costante chi li conosce e li sa usare correttamente, cosa più facile a
dirsi che a farsi – di gestire la maggior parte delle situazio-
• è implicitamente Serializable ni. Il problema è proprio che questi meccanismi, seppur
• ha due metodi statici automaticamente generati dal sufficienti, sono ad un livello di astrazione molto basso.
compilatore: Creare una classe thread-safe può essere molto più difficile
di quello che può sembrare, e creare un’applicazione con-
o public static E[] values() che torna la lista delle co- corrente senza deadlock e che sfrutti al massimo le risorse
stanti disponibili è invece appannaggio di pochi.
o public static E valueOf(String name) che ritorna la Per questo Doug Lea, professore specializzato nella pro-
costante associata al nome grammazione concorrente, cominciò nel 1995 a mettere
insieme una libreria avanzata di componenti ad alto livello
• non può fare l’override di finalize di astrazione sulla sua homepage [LEA]. La libreria ebbe
• non può essere dichiarata abstract, ma può avere metodi un notevole successo e diverse revisioni, fino alla pubblica-
abstract (questa è lunga da spiegare!) zione nel 1999 del libro “Concurrent programming in Java”
• le costanti possono essere usate in uno switch, a diffe- [CONCURRENT], best seller che - sfortunatamente - non è
renza dei normali oggetti ancora stato aggiornato. Le idee di Doug Lea trovarono poi
spazio nel JSR 166, che ebbe proprio il compito di inserire
Dopo tutte queste piccole differenze, può dichiarare me- le librerie ed i costrutti avanzati direttamente all’interno di
todi e membri come una qualsiasi altra classe. Il codice Java. Lavorando con il supporto dell’engineering, l’expert
generato per una enum è molto simile a quello dell’idioma group del JSR 166, guidato da Doug Lea, modificò addirit-
type safe enum di Bloch, ed usa ampiamente i generics. tura il memory model di Java e la Vm stessa per sfruttare
A mio modo di vedere le Enum sono un ottimo costrutto al meglio alcune idee. Il frutto di questi sforzi congiunti
se usate in maniera molto semplice, come nell’esempio si trova ora soprattutto nel package java.util.concurrent, è
riportato: se si comincia ad usarle aggiungendo comporta- perfettamente integrato con tutte le altre librerie ed è a
mento alle costanti e cose simili si ottiene solo un sostituto disposizione di tutti.
“povero” per la normale programmazione ad oggetti, con Di fatto, non esiste più ragione per utilizzare i “vecchi”
molte più limitazioni (fra l’altro spesso poco intuitive). meccanismi di sincronizzazione. Le nuove concurrent API
Anche qui il consiglio è: prendete le enum, ma a piccole permettono prestazioni spesso superiori, sono più facili da
dosi. Se vi trovate a complicarvi la vita, forse è meglio pen- usare, e risolvono in maniera diretta diversi problemi noti
Le annotation permettono di associare delle informazioni che indica che il metodo è deprecato, esattamente come il
ulteriori a del codice (metadati), informazioni che possono tag @deprecated di javadoc. La differenza è che l’override di
poi essere trattate da altri tool per gli scopi più vari. questo metodo genererà un warning a livello di compila-
Un esempio di annotazioni ante-litteram sono i javadoc. zione, ed un warning più dettagliato sul particolare meto-
@deprecated ,per esempio, è una forma di metadato, che do usando questa sintassi:
esprime la semantica “usatelo a vostro rischio e pericolo,
dalla prossima release potremmo cancellarlo”, semantica javac -Xlint:deprecation *.java
ovviamente non esprimibile in Java! Ovviamente un nor-
male commento non è una forma di metadato (o se lo è Dichiarare un metodo @Override farà invece in modo che il
molto primitivo), poichè non ha una struttura e dunque compilatore controlli effettivamente che il metodo effettui
non può essere gestito da un tool, mentre il tag @deprecated l’override di qualche altro metodo, ed è utile per control-
viene gestito dal tool javadoc, che lo inserisce automatica- lare i classici errori di battitura come tostring(), equal(),
mente nella documentazione di progetto. o hashcode() che spesso portano via prezioso tempo allo
Le annotations sono una generalizzazione di questo mec- sviluppatore.
canismo che permette di definire ed usare dei nuovi meta- Anche creare un nuovo Annotation Type è semplicissimo,
dati, per qualsiasi motivo ne abbiate bisogno (ovviamente tramite il costrutto @interface:
non per la documentazione, per quella c’è già javadoc) . Per
ottenere ciò, le annotations consistono di: public @interface TODO {
String nota();
• una sintassi per dichiarare annotation types }
• una sintassi per annotare il codice
• API per leggere le annotazioni per cui si potrà usare l’annotazione in questo modo, pas-
• modifiche alla rappresentazione dei class files per sando una stringa alla proprietà nota
“contenere” le annotazioni
• un tool per processare le annotazioni @TODO(nota=”Questo metodo va riscritto, è troppo complesso”)
public void faiQualcosa() { //... }
le annotations non influiscono direttamente sul runtime,
ossia non modificano la semantica del codice, ma in realtà Per concludere velocemente questa carrellata: si possono
possono farlo indirettamente, per esempio influenzando creare annotazioni con più di un parametro, si può omet-
l’eventuale ambiente in cui il codice è eseguito a runtime: tere il nome della proprietà se questa si chiama value, si
un application server potrebbe eseguire un particolare possono usare dei valori di default per i parametri e si pos-
componente utilizzando diversi cicli di vita a seconda di sono anche annotare le annotazioni (meta-metadati) per
come questo sia annotato, o decidere sulla base di un’an- definirne meglio il comportamento.
notazione se persistere l’oggetto e come. A runtime, si può poi interrogare un class file ed ot-
È per questo che le annotazioni possono semplificare mol- tenere informazioni sui metadati e sui valori delle
to la vita dei produttori di tool: non è un caso che le nuove proprietà associate tramite nuovi metodi delle reflection
specifiche EJB 3.0 utilizzeranno pesantemente questo API. (vedere l’interfaccia java.lang.reflect.AnnotatedElem
meccanismo. Pensandoci bene, le informazioni contenute ent per i dettagli). Dopo di che, l’uso che ne farete è
nei file XML di un EJB non sono infatti altro che metadati, completamente a vostro carico!
rappresentati tramite file XML in assenza di altri mecca- Per chiudere il cerchio, avrete a disposizione il tool apt, che
nismi Java. Se a questo punto vi viene in mente Xdoclet potete trovare nella solita $JAVA_HOME/bin. Brevemente,
[XDOCLET], siete sulla strada giusta. Se poi vi viene in questo tool serve per generare, di solito a build time, dei
mente di eliminare tutti i file di configurazione del vostro file che contengano delle informazioni derivate da quelle
software e sostituirli con delle annotazioni da distribuire presenti nelle annotazioni, ed è dunque fondamentale per
insieme al sorgente, siete probabilmente sulla strada sba- mantenere in modo automatico la sincronia fra le annota-
gliata: le annotations sono un’altra medicina da prendere zioni ed il mondo “esterno”. Vi rimando alla guida ufficiale
a piccole dosi, altrimenti è velenosa. per i dettagli [APT]
Un uso intelligente e non invasivo delle annotations è per
Esistono tre annotazioni standard predefinite in Tiger esempio fatto nei Testing framework (TestNG, Junit 4). Gli
(Java 5): unit tests devono infatti essere eseguiti da un ambiente
esterno, ed hanno bisogno di semantiche particolari come
@Override, indica che il metodo effettua l’override di un “questo metodo è un testcase”, “questo metodo deve esse-
altro metodo re eseguito prima di ogni testcase” che, seppur esprimibili
@Deprecated, equivalente al @deprecated per i javadoc correttamente in Java, sono sicuramente più chiari e con-
@SuppressWarnings, “spegne” gli warning del compilatore cisi se espressi tramite annotazioni come @test, @before e
per una porzione di codice @after.
della comunità molto più ampio. L’intero ciclo di sviluppo di andare in produzione con le nightly build di Java6, mi
questa release è stato infatti all’insegna della collaborazione raccomando!
e della trasparenza, con sorgenti, nightly build, forum, blog Mustang è sicuramente una release dedicata al Desktop: la
delle persone dell’engineering e paper vari a disposizione maggior parte degli sforzi si sono concentrati proprio in que-
sul sito del progetto [MUSTANG]. “Enter the Participation sto settore. È infatti noto che Java è ormai lo standard defacto
Age”, per dirla con i nuovi slogan del marketing Sun. per il server side computing, poiché – oltre alla portabilità -
Il nuovo ciclo di sviluppo di Java fa sì che le novità offre eccellenti caratteristiche a chi si occupa di middleware
verranno da ora introdotte in maniera graduale, poi- di qualsiasi tipo. Nel settore desktop però ci sono sempre stati
ché i rilasci fra una versione e l’altra saranno sempre diversi problemi, alcuni insiti nella natura stessa di linguag-
compresi fra 1 anno e mezzo e due anni, e quindi molto gio multipiattaforma, altri sicuramente dovuti al fatto che in
probabilmente non assisteremo più a “salti” come quel- questi anni in Java si è fatto soprattutto altro.
lo fra Java 1.4 e Java5. Inoltre la quantità e la qualità Ma vediamo (Tabella 2) alcune (elenco assolutamente
delle informazioni a disposizione degli sviluppatori è non esaustivo!) delle novità di Java6. La tabella 2 non è
molto migliorata: qualsiasi software house ha ora la ovviamente comparabile con quella generale su Java5, poi-
possibilità di pianificare correttamente la transizione da ché qui il livello di granularità è molto più basso. Se avessi
una release all’altra, anticipando i possibili problemi ed dovuto elencare a questo livello di dettaglio i cambiamenti
avendo un canale diretto con l’ingegneria del prodotto in Java5, mi ci sarebbero volute 10 pagine!
molto prima che sia effettivamente disponibile. Ovvia- È evidente che questa release, a differenza della preceden-
mente questo non va interpretato come un consiglio di te, è più orientata a caratteristiche “bells and whistles”.
JJ: Può spiegarci perché il nuovo OpenJDK Per la piattaforma Java SE abbiamo bisogno della
(la versione Open Source del JDK) è GPL con Classpath Exception perché alcune persone, quando
la eccezione “classpath”. Che cosa è questa distribuiscono una applicazione , distribuiscono anche
eccezione? la piattaforma Java.
Per esempio, senza la classpath exception, non sarebbe
SP: Abbiamo semplicemente scelto di utilizzare la possibile distribuire sia OpenJDK che Tomcat nello
licenza con cui le versioni open di Java erano distribuite. stesso pacchetto.
La più evidente era il progetto Classpath, quindi abbiamo Per quanto riguarda il JavaME, invece, non sei nella
deciso di distribuire OpenJDK con la stessa licenza del situazione di dover distribuire sia l’applicazione che la
progetto Classpath. Che è appunto la licenza GPL con piattaforma. I soli che hanno bisogno di farlo sono i
una eccezione che consente di distribuirlo insieme a produttori del dispositivo.
un prodotto proprietario, senza dover rilasciare l’intero
prodotto come GPL. JJ: Non siete preoccupati che possa esserci un
“fork” (versione divergente indipendente) di
JJ: Siccome ci sono già due progetti Java Open Java?
Source, il progetto Classpath e il progetto Apache
Harmony. Il rilascio del “vero” Java come Open SP: Non ho paura, perché penso che per il mercato
Source li renderà obsoleti? sarebbe una cattiva cosa creare un fork incompatibile. E
non credo che vedremo un fork incompatibile.
SP: Non credo che diventeranno obsoleti. La comunità Abbiamo parlato con le comunità di Classpath e di
di classpath ci è stata molto di aiuto, e credo che Harmony, ed entrambe sono convinte della necessità di
uniremo le forze con loro. essere compatibili.
SP: Gli ricorderemo che non può chiamare il prodotto SP: Avevamo un albero di decisioni davanti a noi. Prima
“Java” se non passa il TCK (il TCK è il Kit di Test di di tutto, internamente, per mantenere il codice sorgente
Compatibilità che assicura che una implementazione di Java usiamo TeamWare, che è molto vecchio e i cui codici
sia conforme alle specifiche, nda). Noi abbiamo rilasciato sorgenti non sono disponibili pubblicamente. Per cui
il codice sorgente, ma il codice sorgente non diventa abbiamo dovuto scegliere un diverso sistema di gestione
“Java” se non passa i test del TCK. dei codici sorgenti. E abbiamo dovuto confrontare i
sistemi di controllo di versione centralizzati, come
JJ: Ci sarà mai un Java “leggero”, piccolo e subversion, e quelli distribuiti. TeamWare è un sistema
semplice come il Flash Player? Cosa ne pensa se di controllo di versione distribuito, e per come è
qualcuno usa il sorgente per costruire un simile sviluppato Java, abbiamo scelto un sistema di controllo
applet player leggero? di versione distribuito.
La comunità di OpenSolaris aveva sperimentato diversi
SP: Penso che non potrà chiamarlo Java se non passa sistemi di controllo di versione, come Subversion,
il TCK. Mercurial, SCCS e altri. La conclusione è stata che il
sistema di controllo più adatto era Mercurial.
JJ: Non esiste ancora una versione Sun di JavaME
per la piattaforma Pocket PC. Il rilascio di Java JJ: Ma non è molto conosciuto …
come Open Source favorirà l’apparire di una
versione Sun per PocketPC? SP: Nessuno dei sistemi di controllo di versione
distribuiti è ben conosciuto. Ciononostante ci siamo
SP: Una volta che i sorgenti sono stati rilasciati ognuno convinti che Mercurial era la scelta migliore. Per il
può farci quel che vuole. Non vedo ostacoli al fatto che rilascio iniziale di Javac e Hotspot useremo Subversion.
qualcuno faccia il porting. Renderemo anche il codice disponibile come package
di Netbeans in modo che si possa utilizzare un sistema
JJ: È ben noto che IBM ha avuto benefici da Linux familiare.
vendendo hardware e servizi software. Java e
Solaris Open Source permetteranno a Sun di JJ: Quali parti della piattaforma Java non possono
vendere più hardware? essere rilasciati perché contengono codice
proprietario non posseduto da Sun?
SP: Sì.
SP: Due parti: il Gestore dei Colori, e il rasterizzatore dei
JJ: IBM è da molto tempo una azienda di servizi font True Type.
software. Sun sta diventando anche una azienda
di servizi software, che rilascia software open JJ: La comunità può aiutare a rimpiazzare queste
source e supporta i clienti nell’adattare il software parti con una implementazione open?
alle loro esigenze di business?
SP: Abbiamo parlato con la comunità Classpath e siamo
SP: Recentemente IBM si è ri-registrata al NY Stock molto lieti di collaborare con loro. In particolare in
Exchange (la borsa di New York) come una azienda di Classpath c’è già una implementazione alternativa del
servizi. Non è questa l’intenzione di Sun. Sun intende Gestore dei Colori. E sono stati molto lieti di contribuire.
rimanere una azienda di sistemi. Abbiamo un business Per quanto riguarda il rasterizzatore dei font, è un altro
di sistemi, storage, software e servizi, e Sun fa il suo problema perché l’architettura di Classpath è diversa
meglio combinando queste cose insieme in sistemi. Ci dall’architettura del JDK di Sun. Per cui c’è bisogno
sarà un incremento nel numero di soluzioni per sistemi di maggior lavoro, ma c’è già un team nel gruppo di
che forniamo.
Note Biografiche
JJ: Quale sarà il processo per poter contribuire ai
miglioramenti della piattaforma? Michele Sciabarrà Dopo aver scritto di Java e averlo insegna-
to per dieci anni, attualmente è il direttore esecutivo di Java
SP: È ancora in corso di definizione. Stiamo studiando Journal. Quando non cerca di imparare le ultime API o di-
alcune interessanti opinioni della community, ci squisisce della superiorità del modello Open Source, si dilet-
ta a programmare cellulari Symbian in C++ e amministra-
aspettiamo di poter dire di più in primavera. Intendiamo
re sistemi Linux.
realizzare un processo trasparente ed equo.
Resource
Management
con JMX
Java Management eXtension (JMX) è una specifica che offre una API ed una architettura per la
gestione ed il monitoraggio delle risorse in Java
L
standard tra i quali il più noto è il protocollo
a gestione di una risorsa software SNMP [1], acronimo di Simple Network Ma-
e/o hardware è la possibilità di poter nagement Protocol, usato nella gestione delle
misurare, a runtime e nel tempo, reti TCP/IP; mentre per l’application management
informazioni relative allo stato della esistono, per ogni prodotto, soluzioni proprie-
risorsa. È anche la possibilità di po- tarie costruite ad hoc. In questo contesto la
ter alterare il comportamento della specifica Java Management eXtension [2], o
risorsa a fronte delle evidenze riscontrate. più brevemente JMX, si presenta come una so-
Il deploy in un ambiente di produzione di una luzione standard e globale al tema del resource
applicazione software ben progettata, realizzata management in ambiente Java: infatti definisce
e testata, non è la conclusione di un progetto. una architettura, dei design pattern, una serie di
Tipicamente, per un software in produzione, API ed una serie di servizi per la gestione ed il
vi è la necessità di monitorare informazioni a monitoraggio delle applicazioni. Gli obiettivi ed
livello di business: per esempio il numero degli i benefici dell’architettura JMX si riassumono
ordini inevasi in un sistema di commercio elet- nei seguenti punti:
tronico. Oppure informazioni a livello di siste-
ma: per esempio, il consumo di memoria heap, • Scalabilità: l’approccio basato a componenti
il numero di thread attivi, il tempo medio per la consente di scalare nella gestione ed ammi-
garbage collection e così via. Queste misure sono nistrazione da decine a decine di migliaia di
indicatori diretti del corretto funzionamento risorse;
della applicazione. In modo analogo, la gestione • Integrazione con soluzioni legacy di mana-
della rete e dei dispositivi hardware è sempre gement come SNMP, WBEM (Web-Based
più critica. Gli amministratori di rete impiegano Enterprise Management), CIM (Common In-
un’ampia varietà di strumenti per il controllo formation Model, ossia il modello di dati che
del sistema, al fine di assicurare la continuità e descrive gli oggetti presenti in un ambiente di
l’affidabilità delle operazioni. gestione) e TMN (Telecommunications Ma-
Il resource management è la disciplina che orga- nagement Networks);
nizza la gestione delle risorse hardware e sof- • Semplicità nell’instrumentation, ossia nel ren-
tware di una organizzazione ed è caratterizzato dere accessibile via JMX, risorse software o
dalla necessità di: hardware.
• recuperare informazioni relative alla risorsa; Le informazioni esposte via JMX possono essere
• misurare nel tempo tali informazioni; recuperate e visualizzate da sistemi di manage-
• alterare a runtime il comportamento della ment evoluti come IBM Tivoli, HP Openview o
risorsa a fronte delle evidenze riscontrate. da semplici tool come l’HTML protocol adapter
della SUN [3] o la Jconsole [4] presente dal Java De- • Parametri per i costruttori ed i metodi;
velopment Kit 5.0. • Notifiche emesse dalla risorsa in broadcast attra-
verso l’infrastruttura JMX.
Tipo Descrizione
Sono gli MBean più semplici da definire ed implementare. Tutti gli attributi, le
operazioni e gli eventi associati ad uno Standard MBean sono specificati staticamente
nella sua interfaccia di gestione. Gli Standard MBean devono implementare una
interfaccia che è dichiarata seguento ben precise regole di coding convention (regole
Standard MBean
di codifica indicate con il termine lexical design pattern nella specifica JMX 1.2). Per
esempio per instrumentare una classe chiamata com.xyz.MyClass la interfaccia di
gestione si deve chiamare com.xyz.MyClassMBean. Un agente JMX attraverso un
processo di introspezione scopre la interfaccia di gestione di uno Standard MBean.
Un Open MBean è un Dynamic MBean dove tutti gli attributi del managed bean
appartengono ad un insieme ben definito di tipi di dati Java (per esempio String,
Integer, Boolean, etc.). Un Open MBean non estende nessuna particolare interfaccia,
Open MBean a parte l’interfaccia DynamicMBean, e l’agente JMX capisce che è in presenza di un
Open MBean perché riceve un oggetto che implementa la interfaccia OpenMBeanInfo
presente nel package javax.management.openmbean descrittiva dei metadati del
bean.
un managed bean server, da una serie di agent services dell’object name attraverso il quale si individua un
e almeno un protocol adapter e/o un connettore. Il oggetto (operazione detta di name lookup), e se ne
managed bean server, o più brevemente MBean server, invoca un suo metodo. Pertanto, una eventuale mo-
è il componente fondamentale nell’architettura difica introdotta nell’interfaccia del managed bean
JMX poichè tutte le operazioni di management su- non richiede la redistribuzione della medesima.
gli MBean sono mutuate dal server che si propone Questa scelta, se da un lato semplifica la gestione
come un broker fra le applicazioni di management di strutture complesse, costituite per esempio da
e le risorse gestite. Gli MBean sono registrati nel un alto numero di oggetti, dall’altro elimina il type
managed bean server che pertanto funge da registro checking sui parametri e sui valori restituiti (cfr. Fi-
centralizzato. Attraverso il concetto di object name, gura 2).
oggetto che identifica univocamente il managed La specifica JMX prevede come obbligatori quattro
bean registrato nel managed bean server, si realizza il agent services mentre altri possono essere aggiunti
disaccoppiamento tra applicazione di management dalle varie implementazioni proprietarie. Gli agent
e risorsa. Una applicazione di management può in- services definiti dalla specifica sono il Dynamic Class
teragire con un managed bean fornendo il suo nome Loading service, il Timer service, il Relation service ed il
all’agente JMX per ogni operazione invocata. Il Monitoring service. Il primo servizio consente di cari-
meccanismo di invocazione remota non si basa sul care e di instanziare dalla rete nuove classi o librerie
modello stub-skeleton, come accade per esempio nel- native; il Timer service fornisce un meccanismo di
le architetture RMI (Remote Method Invocation) schedulazione degli eventi e consente di eseguire
ed EJB (Enterprise JavaBean), ma solo sull’uso operazioni a determinati intervalli di tempo; il Rela-
tion service consente di creare relazioni fra gli MBean Il Distributed level contiene almeno un protocol adapter
e, per concludere, il Monitoring service misura ad in- o un connettore attraverso i quali gli agenti JMX sono
tervalli regolari di tempo la variazione del valore di accedibili remotamente. Gli adapter forniscono una
un attributo di una risorsa e in base al valore della vista degli agenti JMX attraverso un dato protocollo
variazione invia notifiche ai listener associati. Sono (per esempio HTTP o SNMP). Questi mappano la se-
disponibili tre tipi di monitor: mantica delle interazioni sugli MBean e sullo MBean
server in una rappresentazione adatta ad un dato
• Counter monitor; protocollo e ad un modello informativo differente
• Gauge monitor; come, per esempio, il protocollo SNMP. Nell’esem-
• String monitor. pio che segue useremo l’HtmlAdaptorServer [3] con
il quale l’interfaccia di gestione è visibile attraverso
Il Counter monitor osserva in continuazione gli in- un browser web. I connettori, viceversa, consentono
crementi non negativi degli attributi di tipo intero di connettere un agente JMX con un’applicazione
che si comportano come un contatore, inviando una remota compatibile al modello JMX usando una tec-
notifica quando il valore dell’attributo raggiunge o nologia distribuita, ad esempio RMI. Questo tipo di
supera un certo valore di soglia (threshold). È possi- comunicazione prevede un connettore che funge da
bile impostare un valore di offset che viene aggiunto server nell’Agent level e un connettore con il ruolo di
al valore di soglia ogni volta che questo è raggiunto client installato nella JVM dell’applicazione di ma-
e superato: in tal modo è possibile seguire l’anda- nagement (cfr. Figura 5).
FIGURA 3 Counter monitor: figura tratta dalla JMX Instrumentation and Agent Specification, v1.2
FIGURA 4 Gauge monitor: figura tratta dalla JMX Instrumentation and Agent Specification, v1.
FIGURA 5 Protocol Adapter e connettori: figura tratta dalla JMX Instrumentation and Agent Specification, v1.2
out.println(“CONF_1:”
public final class Configurazione {
+Configurazione.INSTANCE
.getValore(“conf_1”));
private static final String NOME_FILE
out.println(“CONF_2:”
= “/configurazione.xml”;
+Configurazione.INSTANCE
private Date lastUpdate = null;
.getValore(“conf_2”));
private final Properties prop = new Properties();
try {
Thread.sleep(10000L);
// Unica istanza della classe Configurazione
} catch (InterruptedException e) {…}
// presente ed invocabile da parte di altre classi.
}
public static Configurazione INSTANCE
}
= new Configurazione();
…
// Costruttore privato
private Configurazione(){loadConfigurazione();}
La classe Configurazione legge i parametri di configu-
razione, conf_1 e conf_2, dal file XML durante la fase
private void loadConfigurazione() {
di inizializzazione e li memorizza in un oggetto di
InputStream is = Configurazione.class
tipo java.util.Properties. La classe è un singleton (cfr. il
.getResourceAsStream(NOME_FILE);
pattern Singleton [GoF]) e pertanto è presente una
try {
sola instanza in memoria della classe referenziata at-
prop.clear();
traverso l’attributo pubblico e statico INSTANCE (cfr.
prop.loadFromXML(is);
il Listato 1 per i dettagli).
lastUpdate = new Date();
La risorsa software che desideriamo amministrare
} catch (Exception e) {
è la classe Configurazione. In particolare, attraverso
err.println(“Eccezione nella lettura del file:”
una console di amministrazione JMX, deve essere
+e.toString());
possibile:
}
}
• Eseguire a caldo, ossia senza fermare e far ripartire
l’applicazione, la rilettura del file XML di configu-
public synchronized
razione (metodo reload());
String getValore(String nomeProprieta)
• Visualizzare il valore di un parametro di configura-
{
zione presente nel file XML (metodo getValore());
return this.prop.getProperty(nomeProprieta);
• Visualizzare la data in cui è avvenuta l’ultima
}
lettura dei valori presenti nel file XML (attributo
lastUpdate).
// Metodo che legge il file XML.
public synchronized void reload()
Come è stato precedentemente descritto, l’instru-
{
mentation level definisce le regole per “instrumen-
loadConfigurazione();
tare” le risorse in modo che queste possano essere
}
gestite da un agente JMX. L’instrumentazione
delle risorse avviene attraverso gli MBean. Ini-
// Metodo che restituisce
ziamo con intrumentare la classe Configurazione
// l’ultima data di lettura del file XML.
attraverso uno Standard MBean. Pertanto, definia-
public Date getLastUpdate() {
mo l’interfaccia di gestione tramite la quale un
return lastUpdate;
oggetto della classe Configurazione potrà essere
}
manipolato. L’interfaccia deve esporre i metodi
}
da invocare per eseguire una operazione sulla
risorsa ed i metodi per la lettura e la modifica di
un attributo. La regola sui nomi degli attributi
LISTATO 1 La classe Configurazione segue la naming convention dei JavaBean e pertanto
in presenza dei metodi set () e get () l’agente JMX
Configurazione scrivendo sulla console di output il deduce che vi sia una proprietà in lettura e modi-
valore restituto dal metodo. Il metodo getValore() fica. L’assenza di uno dei due metodi implica che
consente di recuperare il valore di due parametri, l’attributo sia di sola lettura o di sola scrittura. I
denominati conf_1 e conf_2, memorizzati inizial- nomi dei metodi da invocare, ossia le operazio-
mente in un file XML. Di seguito riportiamo uno ni sulla risorsa, non seguono nessuna regola e
stralcio del codice dalla classe Esecutore esplicativo ogni metodo che non inizia per get o per set è per
di quanto descritto: l’agente JMX un metodo di esecuzione e non un
metodo per la manipolazione diretta di un attri-
… buto della classe. L’interfaccia di management
public void run() deve avere un nome formato dal nome della clas-
{ se da gestire con l’aggiunta del suffisso MBean.
while(true) { Per esempio la classe Java it.articolo.Configurazione
FIGURA 6 Console di amministrazione fornita dall’adapter HTTP della implementazione JMX della Sun
deve implementare l’interfaccia it.articolo.Configur t.MBeanServerFactory. La riga di codice che segue crea
azioneMBean. Di seguito la definizione della inter- un oggetto che implementa l’interfaccia javax.mana
faccia ConfigurazioneMBean: gement.MBeanServer mantenendo internamente una
reference all’oggetto appena creato. In tal modo attra-
public interface ConfigurazioneMBean { verso il metodo findMBeanServer(), sempre presente
// operazione per ottenere il valore nella classe MBeanServerFactory, è possibile ricercare
// di un parametro di configurazione e ritornare la reference all’istanza precedentemente
public String getValore(String nomeProprieta); creata.
// operazione di rilettura del file XML
public void reload(); MbeanServer server =
// attributo di sola lettura MBeanServerFactory.createMBeanServer();
public Date getLastUpdate();
} Lo stralcio di codice che segue mostra come regi-
strare un managed bean all’interno dello MBeanServer
Una volta che l’MBean è stato definito è necessario: in modo tale che possa essere acceduto attraverso
chiamate JMX:
1. Creare o recuperare una istanza del managed bean
server; ObjectName name =
2. Registrare l’MBean all’interno del server; new ObjectName(
3. Collegarsi al server attraverso un protocol adapter “Articolo:name=ConfigurazioneStandardMBean”);
e interagire con la risorsa, per esempio attraverso server.registerMBean(
una console HTML di amministrazione. Configurazione.INSTANCE ,name);
Tutte le operazioni sopra elencate sono racchiuse Ogni MBean deve essere univoco all’interno dello
nella classe AgenteHelper (cfr. Listato 2). Un’istanza stesso MBeanServer e il suo nome è gestito tramite
di MBeanServer può essere creata o recuperata at- la classe javax.management.ObjectName. Un ObjectNa-
traverso i metodi helper della classe javax.managemen me è composto da un domain name, che rappresen-
= new HtmlAdaptorServer();
ta il namespace all’interno del JMX Agent, seguito adapter.setPort(9092);
da una lista di proprietà che identificano univoca- ObjectName name
mente l’MBean e forniscono informazioni relative = new ObjectName(“Articolo:name=HTMLAdapter”);
all’oggetto: server.registerMBean(adapter ,name);
adapter.start();
domain: key1 = value1 , key2 = value2
Osservando le righe di codice sopra riportate, possia-
nel nostro esempio il domain name è Articolo e l’unica mo notare come l’HTML adapter sia esso stesso un
proprietà che impostiamo è il nome del managed MBean registrato nel managed bean server. Attraverso
bean. un qualsiasi browser è ora possibile collegarsi sulla
Infine, per accedere al managed bean utilizziamo porta 9092 all’host dove è in esecuzione l’agente
l’HTML protocol adapter fornito dalla SUN [3]. Le JMX ed interagire con gli MBean (Figura 6 e Figu-
seguenti righe di codice permettono la creazione, ra 7).
la registrazione e l’avvio dell’adapter sulla porta Con l’esempio precedente è possibile notare come
9092: instrumentare una classe Java attraverso uno
Standard MBean sia un’operazione sostanzialmen-
HtmlAdaptorServer adapter te semplice. Infatti, uno Standard MBean dichiara
FIGURA 7 Console di amministrazione fornita dall’adapter HTTP della implementazione JMX della Sun
sono dei tipi di Dynamic MBean, mentre è ricavata patibile con la specifica JMX. Al costruttore della
con la reflection Java dallo MBean server per gli Stan- classe RequiredModelMBean passiamo una istanza
dard MBean. Il diagramma delle classi della Figura della classe ModelMBeanInfo. È opportuno osservare
8 riporta tutte le classi che descrivono i metadati di come un Model MBean debba esporre i suoi metada-
un MBean. ti descrittivi attraverso un’istanza della classe Mo-
Nell’esempio che segue instrumentiamo sempre la delMBeanInfoSupport che estende la classe MBeanIn-
classe Java Configurazione ma in questo caso attraver- fo e implementa l’interfaccia ModelMBeanInfo. Nel
so un Model MBean. Le righe di codice che seguono nostro caso, la classe Java ConfigurazioneInfo (cfr.
mostrano come registrare il Model MBean nel managed il Listato 3 per i dettagli) restituisce un oggetto
bean server: ModelMBeanInfoSupport. Per terminare, definiamo
per l’instanza della classe RequiredModelMBean
name = new ObjectName( l’oggetto da gestire e sul quale eseguire tutte le
“Articolo:name=ConfigurazioneModelMBean”); operazioni di management:
RequiredModelMBean model =
new RequiredModelMBean( model.setManagedResource(
ConfigurazioneInfo.getInfo()); Configurazione.INSTANCE, “objectReference”);
model.setManagedResource(
Configurazione.INSTANCE, In modo analogo all’esempio precedente possiamo
“objectReference”); amministrare il bean attraverso la console HTML
server.registerMBean(model ,name); dello adapter SUN.
…
[1]_Protocollo_SNMP:_http://it.wikipedia.org/wiki/
SNMP Note Biografiche
[2]_Home page JMX : Fabio Staro, dottore in Fisica è Responsabile Tecnico per i pro-
[3]_Adapter_HTML_(presente nella JMX refer- getti Java presso la Direzione Ricerca ed Innovazione di Engi-
neering Ingegneria Informatica S.p.A
ence_implementation,_archivio_jmxtools.jar) :
COMMUNITY WATCH
Ü di Stefano Sanna
(stefano.sanna@javajournal.it)
Quando si presenta Java (linguaggio, piattaforma, itinerante, un roadshow che tocca diverse città italiane
tecnologia, librerie, applicazioni...) è inevitabile in tutta la penisola, portando la tecnologia Java anche
sottolineare che attorno ad esso vive una comunità in ambiti geografici normalmente esclusi dai circuiti
numerosa e operosa di programmatori e aziende. Non dei grandi eventi. Questa caratteristica fa di JavaDay
è, dunque, la sola “potenza tecnologica” a decretarne un momento unico e qualificante, dove la tecnologia,
il successo, ma anche lo spirito di collaborazione e le istituzioni, gli sviluppatori e le imprese si possono
condivisione che nelle community (reali e virtuali) incontrare direttamente sul proprio territorio per
trova la sua massima espressione. Questa pagina confrontarsi, capire, conoscere e verificare tante
di Java Journal vuole offrire una panoramica sulle opportunità”. Questa è la forza della community!
community (nazionali e non), dove poter segnalare
eventi, raccontare cosa accade nel mondo Java, cercare Avremo modo di “incontrare” i diversi gruppi nello
di trasmettere ed esaltare lo spirito di collaborazione di spazio offerto da Java Journal. Segnaliamo brevemente
cui si è detto. due JUG che si sono distinti in modo particolare. Il JUG
Sardegna ONLUS è stato premiato da James Gosling
La community italiana e gli eventi durante la JavaOne dello scorso maggio, ricevendo il
prestigioso Duke Award per il progetto “JUG Sardegna
In Italia esistono numerose realtà, a partire dai Java
per l’AVIS” (http://jug-avis.dev.java.net), destinato
User Group (JUG), che hanno respiro locale, fino alla
a supportare le attività di reperimento di donatori di
Java Italian Association (JIA); o comunità come Java
sangue condotte dall’Associazione Volontari Italiani
Italian Portal (JIP, uno dei gruppi più vivaci della
Sangue (http://www.avis.it). È doveroso, poi, un
penisola!). Community significa mailing list, forum,
riferimento al JUG Torino, che ha (coraggiosamente!)
risorse condivise ma soprattutto meeting, seminari,
dato inizio al JavaDay: l’evento nel capoluogo
giornate di approfondimento e supporto agli eventi
piemontese è stato un successo, grazie all’eccellente
nazionali. Se, infatti, gli incontri a livello locale
lavoro svolto dal team organizzatore.
mantengono viva l’attività all’interno dei singoli gruppi,
quelli di più ampio respiro costituiscono un’occasione
per conoscersi, scambiare esperienze, avviare nuove
collaborazioni. Oltre ai forum e alle liste, dunque,
una opportunità per aprire nuovi contatti. La Java Note Biografiche
Conference, evento nazionale per eccellenza organizzato
da Sun Microsystems, si avvale della collaborazione dei Stefano Sanna si occupa di sviluppo di applicazioni multi-
mediali per piattaforma Savaje presso Beeweeb Technolo-
JUG e delle altre community già dal 2005; e il legame gies (http://www.beeweeb.com). Ha lavorato per sette anni
è stato rafforzato nell’edizione di quest’anno. Nasce, nel gruppo Network Distributed Applications del CRS4, oc-
invece, dalle community il JavaDay, il primo evento cupandosi di mobile computing e applicazioni network-orien-
ted per cellulari e PDA. Collabora attivamente con JIA, JUG
itinerante su Java. Grazie allo sforzo congiunto dei JUG, Sardegna e Java Mobile Developers Forum. Il sito sito web
di JIA e JIP, come indicato sul sito ufficiale dell’iniziativa personale è http://www.gerdavax.it
(http://www.javaday.it), “JavaDay è una manifestazione
Accedere a file di
Excel in Java
Microsoft Excel è un applicativo molto usato, e quindi occorre “conviverci”, anche se siete program-
matori Java e amate la portabilità e l’apertura. Leggendo questo articolo, se i clienti vi chiederanno
l’importazione e l’esportazione di dati in formato Excel, saprete come fare
E
Excel:
ntrate in ufficio e il vostro collega • tramite uno strato API interamente Java
esperto in tecnologie Microsoft, • tramite un bridge per le API native di Micro-
è particolarmente sorridente e vi soft.
informa che “è arrivata la richiesta
di automatizzare la generazione I due prodotti che descriviamo in questo arti-
dei report amministrativi in Excel; colo sono Jakarta POI e JACOB: POI sfrutta l’ap-
è lavoro delicato perché i report andranno proccio Java mentre JACOB sfrutta l’approccio
all’amministratore delegato”, dice con tono nativo.
ironico e un po’ beffardo. E aggiunge: “Mi sa
che questa volta dovrò pensarci io”. Per circa 10
millisecondi temete abbia ragione lui; ma vi ri- Jakarta POI
prendete subito, sapendo di poter “competere”
anche nell’automazione dei documenti Office Il progetto nasce nel 2001 dall’esigenza di
Microsoft. Andrew Oliver di accedere ai file di Excel con
Esistono numerosi prodotti per generare re- uno strumento Open Source in Java. Nel corso
port aziendali (ad esempio, BusinessObjects, degli anni, le librerie POI sono diventate le più
iReport), che si interfacciano direttamente ai note e complete sul mercato dell’Open Source;
database per recuperare i dati, e che producono oggi sono un punto di riferimento in materia.
dei report con grafici altamente professionali. Quando Oliver si imbatté per la prima volta
Eppure molti utenti sono abituati ad utilizza- nel formato “Microsoft’s OLE 2 Compound “
re Microsot Office: principalmente perché lo dei documenti Office, si rese conto che questo
conoscono e non vogliono rinunciare a utiliz- formato non è altro che la trasposizione di par-
zarlo. Ma anche perché l’elevata diffusione di te di un file system su singolo file. Da questa
Microsoft Office garantisce che i file prodotti constatazione ebbe origine l’acronimo POI: Poor
siano facilmente accessibili e modificabili. Obfuscation Implementation (che tradotto, al-
Inoltre, l’installazione di software aggiuntivo è l’incirca suona come “scarsa implementazione
un’operazione non sempre vista di buon occhio di una offuscazione”).
dagli utenti ed è anche proibita in molti contesti
aziendali. Il progetto POI è formato da un insieme di com-
Automatizzare la generazione di questi docu- ponenti:
menti con .NET non presenta alcuna difficoltà.
Fare altrettanto tramite Java è più complesso, • POIFS è il cuore del progetto, ed è l’infra-
ed ha delle limitazioni che dipendono dal pro- struttura per leggere e scrivere OLE 2 Com-
dotto che avete deciso di utilizzare per interfac- pound Documents; tutti i componenti fanno
ciarvi a questi documenti uso di questo componente. Tramite POIFS
Esistono principalmente due approcci, utilizza- si possono accedere alle informazioni dello
Vediamo ora come si utilizzano queste librerie per L’ultima cosa che rimane da fare è scrivere il file su
risolvere il problema che avevamo in origine: leggere disco:
e scrivere un file excel.
FileOutputStream fileOut
= new FileOutputStream(“c:\\temp\\test.xls”);
wb.write(fileOut);
Java
fileOut.close();
ha le carte in
regola per competere Leggere il file di Excel
anche nell’automazione Il file appena creato può essere letto anche con
Microsoft Office, ma noi proviamo a leggerlo utiliz-
zando nuovamente le librerie POI. La lettura risulta
dei documenti Microsoft ancora più semplice della scrittura, e fino all’accesso
a livello di cella non c’è bisogno di alcun commento,
Office il codice parla da sé:
FileInputStream fis
= new FileInputStream(“c:/temp/test.xls”);
HSSFWorkbook wb = new HSSFWorkbook(fis);
Scrivere un file Excel
HSSFSheet sheet = wb.getSheetAt(0);
Iniziamo a creare un documento Excel, così da poter- HSSFRow row = sheet.getRow(0);
lo leggere in seguito. Le API sono molto intuitive ed HSSFCell cell = row.getCell(0);
autoesplicative. Non è necessario assegnare subito
un nome al file in fase di creazione, quest’operazione Per leggere il valore della cella occorre qualche
può essere rimandata all’atto del salvataggio del file spiegazione sul formato di memorizzazione: infatti,
su disco: Excel prevede una tipizzazione dei valori delle celle,
che è diverso da quello a cui siamo abituati nei data-
HSSFWorkbook wb = new HSSFWorkbook(); base relazionali o in Java. Questi tipi sono codificati
nell’oggetto HSSFCell e sono:
A questo punto possiamo creare i worksheet, le righe
e le celle del documento Excel. Ad ogni foglio, riga e • formula
cella è associato un indice che equivale alla posizione • numeric
in cui si vuole creare l’oggetto: • boolean
• string
HSSFSheet sheet = wb.createSheet(); • blank
HSSFRow row = sheet.createRow((short)0); • error