Il
Tag Library Descriptor
Dopo i tag handler, di cui ci siamo occupati il mese
scorso, il secondo elemento fondamentale di una Custom
Tag Library (detta anche CTL) è dato dal tag
library descriptor - in breve TLD - ossia un documento
XML avente suffisso .tld e contenente, in forma dichiarativa,
le specifiche funzionali della CTL stessa.
La conoscenza degli elementi caratterizzanti del linguaggio
XML, in virtù del suo sempre più ampio
utilizzo in questi ultimi anni, è oggi così
diffusa da non richiedere ulteriori chiarimenti in questa
sede. Per lo stesso motivo non ci soffermeremo sui vantaggi
derivanti dall'utilizzo di XML in termini di standardizzazione,
riuso, accesso e presentazione delle informazioni in
simbiosi con tecnologie quali XSTL e XPath, vantaggi
che lo hanno reso un componente essenziale all'interno
del framework J2EE nel ruolo di strumento per la redazione
di specifiche funzionali di componenti software.
Il
ruolo di un Tag Library Descriptor consiste nella descrizione
delle caratteristiche strutturali, sintattiche ed implementative
di una Custom Tag Library. Tali informazioni vengono
fornite tramite un insieme di tag XML descritti da un
apposito DTD. Nel presente articolo faremo esclusivo
riferimento al nuovo TLD Document Type Definition facente
parte integrante delle specifiche di Java Server Pages
1.2 [2].
Si noti che JSP 1.2 garantisce la piena backward compatibility
con le Custom Tag Library realizzate per la precedente
versione 1.1 di JSP, il cui DTD [3] continua ad essere
pienamente supportato. Una CTL dichiara la propria intenzione
di servirsi del nuovo Document Type Definition di JSP
1.2 semplicemente facendo ad esso riferimento nel suo
tag <!DOCTYPE>.
Nel
caso di Custom Tag Library complesse il Tag Library
Descriptor tende a divenire un documento piuttosto lungo
e prolisso, la cui stesura viene tipicamente automatizzata
dagli wizard dell'application server ovvero dell'ambiente
di sviluppo utilizzato. Per questa ragione non analizzeremo
in dettaglio tutti i numerosi tag supportati dal TLD
Document Type Definition di JSP 1.2, ma ci limiteremo
ad analizzarne i tre principali.
Il
root element di un TLD è rappresentato dal tag
<taglib>, la cui definizione legge:
<!ELEMENT
taglib (tlib-version, jsp-version?, short-name, uri?,
display-name?, small-icon?, large-icon?, description?,
validator?, listener*, tag+) >
I
principali elementi di tale definizione sono:
-
tlib-version: numero di versione della Custom Tag
Library, gestito dal suo autore;
jsp-version: versione opzionale del framework JSP
per cui la CTL corrente è stata realizzata;
-
short-name: identificatore associato alla tag library.
Tipicamente viene scelto ed utilizzato a tal fine
il prefisso con cui per convenzione si importa la
Custom Tag Library nelle pagine JSP che ne fanno uso;
- description:
descrizione libera ed opzionale della tag library;
validator: questo elemento opzionale rappresenta una
novità di JSP 1.2 e permette di specificare
un'apposita classe Java - sulle cui caratteristiche
ci soffermeremo più tardi nel corso del presente
articolo - deputata alla validazione a livello globale
delle pagine JSP che fanno uso della Custom Tag Library
in oggetto;
- listener:
tramite gli elementi opzionali listener, anch'essi
introdotti a partire da JSP 1.2, è possibile
stabilire un binding tra tag CTL e gli eventi globali
dell'applicazione definiti a partire dalla versione
2.3 della Servlet API;
- tag:
la definizione dei tag caratterizzanti una CTL viene
fornita tramite uno o più elementi <tag>
innestati nel root tag <taglib>. Il
tag <tag> costituisce il singolo elemento di
maggiore importanza di un TLD:
<!ELEMENT
tag (name, tag-class, tei-class?, body-content?, display-name?,
small-icon?, large-icon?, description?, variable*, attribute*,
example?) >
Si
noti che il valore di ogni attributo fornito ai tag
delle Custom Tag Library deve essere delimitato da apici
singoli o doppi, nel rispetto delle norme XML.
Utilizzo
di una Custom Tag Library
L'intenzione di servirsi di una Custom Tag Library dall'interno
di una pagina JSP va dichiarata tramite un'apposita
direttiva <taglib>:
<%@
taglib uri="<uri>" prefix="<prefisso>"
%>
L'attributo
uri specifica la posizione del TLD associato alla Custom
Tag Library, mentre l'attributo prefix comunica al motore
JSP il prefisso con il quale si desidera fare riferimento
ai tag della Custom Tag Library nella pagina corrente.
Si noti che il prefisso associato ad una CTL non rappresenta
una proprietà della tag library stessa, ma può
venire liberamente scelto dall'autore della pagina JSP.
Dal momento che ciò può rendere il codice
confuso e difficilmente comprensibile, si consiglia
di scegliere ed utilizzare i prefissi delle CTL in maniera
logica e coerente, attenendosi alla relativa documentazione.
Uno standard comunemente accettato consiste nell'utilizzare
prefissi chiari e significativi, facendo possibilmente
uso al loro interno del nome della propria azienda o
organizzazione - in maniera sostanzialmente analoga
a quanto avviene per i package Java - al fine di evitare
possibili conflitti nella nomenclatura delle Custom
Tag Library.
In questa sede vale la pena di notare che i prefissi
jsp:, jspx:, java:, javax:, servlet:, sun: e sunw: sono
da considerarsi riservati e non possono venire assegnati
a tag library di terze parti.
Una
pagina JSP può contenere un numero qualsiasi
di direttive <taglib>, le quali possono venire
collocate liberamente all'interno della pagina, purché
antecedentemente al primo utilizzo di un tag della Custom
Tag Library cui fanno riferimento. Per chiarezza si
preferisce usualmente raggruppare tutte le direttive
<taglib> utilizzate in testa alla pagina.
L'importazione di una Custom Tag Library il cui TLD
risulti irraggiungibile in fase di traduzione ovvero
l'utilizzo di un tag il cui tag handler non sia reperibile
a run time fanno scattare delle apposite eccezioni ed
interrompono il processing della pagina JSP corrente.
Deploying
di una Custom Tag Library
Il deploying di una Custom Tag Library può avvenire
secondo tre diverse modalità.
Il meccanismo consigliato, particolarmente adatto a
Custom Tag Library di utilizzo generale per le quali
si intende garantire il decoupling da una particolare
applicazione o contesto Web, consiste nel distribuire
la CTL sotto forma di un archivio JAR contenente le
classi tag handler ed il Tag Library Descriptor, collocato
nella directory /META-INF con il nome di taglib.tld.
A
tale archivio JAR - tipicamente innestato nella directory
/WEB-INF/lib/ delle Web Application per evitare problemi
a livello di CLASSPATH - faranno quindi riferimento
le direttive <taglib> delle diverse pagine JSP,
secondo la seguente sintassi:
<%@
taglib uri="/WEB-INF/lib/<ctl.jar>"
prefix="<prefisso>" %>
Nel
caso di Custom Tag Library strettamente accoppiate ad
un'applicazione e non concepite in un'ottica di riusabilità
è altresì possibile far uso di un meccanismo
alternativo, consistente nell'innesto della CTL all'interno
del file WAR della Web Application che ne fa uso. Per
sfruttare questa tecnica è necessario inserire
un riferimento alla Custom Tag Library nell'Application
Deployment Descriptor dell'applicazione (ossia il file
web.xml) secondo la seguente sintassi:
<taglib>
<taglib-uri><identificativo uri
della CTL></taglib-uri>
<taglib-location><percorso del
TLD></taglib-location>
</taglib>
La
scelta dell'identificativo (uri) con cui la Custom Tag
Library verrà importata dalle pagine JSP è
completamente libera, ed il percorso del Tag Library
Descriptor - vale a dire del documento XML con suffisso
.tld contenente le specifiche della CTL - viene specificato
relativamente al file WAR. Tipicamente, per proteggerne
i contenuti da accessi indesiderati, tutti i Tag Library
Descriptor utilizzati da un'applicazione vengono collocati
nella directory /WEB-INF o in una sua sottodirectory,
ad esempio /WEB-INF/tlds/.
Il
terzo ed ultimo meccanismo - utilizzato nel contesto
di sistemi ed applicazioni particolarmente semplici
o di test - consiste nel rendere il Tag Library Descriptor
di una Custom Tag Library accessibile tramite una URL
pubblica ed esterna alla Web Application, impostando
al contempo il contesto di esecuzione in maniera che
le relative classi tag handler si trovino nel CLASSPATH
dell'applicazione stessa.
In questo caso la direttiva <taglib> ha il seguente
aspetto:
<%@
taglib uri="<URL pubblica del file .tld>"
prefix="<prefisso>" %>
L'utilizzo
di quest'ultimo meccanismo è assolutamente sconsigliato
in ambienti di produzione, dal momento che esso non
contempla in alcuna forma il concetto di packaging di
una Custom Tag Library come entità indipendente.
Si noti inoltre che il Tag Library Descriptor della
CTL risulta pubblicamente accessibile.
Validazione
di una Custom Tag Library
Per validazione si intende la possibilità di
stabilire dei vincoli di correttezza sintattica e semantica
nell'utilizzo di una Custom Tag Library, il mancato
rispetto dei quali porti ad intraprendere apposite azioni
correttive o faccia scattare opportune procedure di
errore.
Un primo livello di validazione è dato, in maniera
abbastanza evidente, dallo stesso Tag Library Descriptor,
il quale è in grado di stabilire con una certa
precisione i limiti sintattici dell'utilizzo di un tag
CTL.
E d'altronde chiaro che a volte si rendono necessari
dei meccanismi di verifica e controllo più flessibili,
legati non solamente ad una rigida definizione sintattica
di un tag, ma al contesto semantico in cui esso viene
utilizzato.
Il
framework Java Server Pages offre due diversi meccanismi
di custom validation, il primo dei quali è disponibile
sin dalla versione 1.1 di JSP e consiste nell'istanziazione
di una classe figlia di javax.servlet.jsp.tagext.TagExtraInfo,
utilizzata per effettuare la verifica del corretto utilizzo
di un tag in translation time. Tale meccanismo - per
quanto di semplice implementazione - permette di definire
politiche di validazione sufficientemente espressive
per i bisogni della maggior parte delle Custom Tag Library.
Come abbiamo già visto in precedenza, l'associazione
di un oggetto di classe TagExtraInfo ad un tag di una
Custom Tag Library viene dichiarata a livello di TLD
tramite il subtag <tei-class> del tag <tag>,
il quale contiene il nome completo della relativa classe
Java, la quale verrà istanziata in sede di traduzione
della pagina dal motore JSP.
L'implementazione
di funzionalità di validazione tramite un oggetto
TagExtraInfo richiede l'overriding di tre metodi:
public
void setTagInfo(javax.servlet.jsp.tagext.TagInfo tagInfo)
L'accessore
setTagInfo() viene invocato dal JSP engine sull'oggetto
TagExtraInfo prima della validazione vera e propria.
L'oggetto TagInfo, che normalmente le implementazioni
di questo metodo si limitano a salvare in vista di un
successivo utilizzo, contiene tutte le informazioni
circa il tag corrente fornite nel Tag Library Descriptor.
public
javax.servlet.jsp.tagext.TagInfo TagInfo getTagInfo()
Il
compito di getTagInfo() consiste semplicemente nel ritornare
l'oggetto TagInfo precedentemente associato ad un oggetto
di classe TagExtraInfo.
public
boolean isValid(javax.servlet.jsp.tagext.TagData tagData)
isValid()
implementa il vero e proprio meccanismo di validazione.
Tale metodo viene invocato durante la fase di traduzione
dal motore JSP per ogni utilizzo del tag all'interno
di una pagina JSP, ed il suo contratto consiste nel
ritornare true qualora l'utilizzo del tag sia da ritenersi
corretto e false altrimenti. L'argomento tagData è
sostanzialmente un data container per mezzo del quale
isValid() può accedere alle informazioni circa
gli attributi ed i valori loro assegnati nel contesto
corrente del tag. Si noti che, avvenendo la validazione
in translation time, le informazioni di valorizzazione
non risultano disponibili per gli attributi dinamici,
ossia per quegli attributi il cui corrispondente elemento
rtexprvalue nel Tag Library Descriptor è stato
impostato a true secondo quanto descritto in precedenza
.
Al
meccanismo di custom validation appena visto e basato
sulla classe TagExtraInfo la nuova versione 1.2 di Java
Server Pages affianca il concetto di validazione a livello
di Custom Tag Library. In altre parole, si introduce
la nozione di uno schema di validazione i cui confini
semantici non siano limitati all'orizzonte del tag corrente,
ma possano prendere in considerazione l'intera tag library
e la sua dinamica di utilizzo all'interno di una singola
pagina JSP.
A
questo fine - come già visto in precedenza -
è possibile dichiarare nel Tag Library Descriptor
di una Custom Tag Library una classe globale di validazione
tramite l'attributo validator del root tag <taglib>.
Essa deve estendere la classe astratta javax.servlet.jsp.tagext.TagLibraryValidator
e viene invocata dal motore JSP tramite il seguente
metodo di callback, definito dalle Servlet API 2.3:
javax.servlet.jsp.tagext.ValidationMessage[]
validate(String prefix, String uri, javax.servlet.jsp.tagext.PageData
pageData)
Il
JSP engine provvederà ad invocare il metodo validate()
in fase di traduzione per ogni tag utilizzato, fornendo
all'oggetto di classe TagLibraryValidator le seguenti
informazioni:
L'identificatore e l'uri del tag corrente, rispettivamente
memorizzati nei parametri prefix e uri;
un oggetto di classe javax.servlet.jsp.tagext.PageData
contenente l'intera pagina JSP corrente sotto forma
di documento XML.
Il
metodo validate() è tenuto a ritornare null se
l'utilizzo del tag è da ritenersi corretto ed
un vettore di messaggi di errore ValidationMessage in
caso contrario.
Si
noti che la precedente versione 2.2 delle Servlet API
definisce il metodo validate() in maniera leggermente
diversa, consentendo a quest'ultimo di ritornare un
unico messaggio di errore codificato direttamente come
oggetto String:
String
validate(String prefix, String uri, javax.servlet.jsp.tagext.PageData
pageData)
L'introduzione
della classe TagLibraryValidator in JSP 1.2 rappresenta
una novità particolarmente significativa ed utile
nell'ambito di Custom Tag Library ricche e complesse,
in quanto consente a queste ultime di arrivare ad una
decisione circa la validità del particolare utilizzo
di un tag tenendo conto di tutti gli elementi della
pagina (tag a qualsiasi livello di nesting, scriptlet,
body content) e - se necessario - ritornando messaggi
di errore chiari, comprensibili e localizzati.
Conclusione
Con il presente articolo abbiamo ultimato la trattazione
dei componenti fondamentali delle Custom Tag Library,
trattando in particolare il Tag Library Descriptor -
vale a dire il documento XML contenente le specifiche
funzionali di una CTL - ed i meccanismi di custom validation
dei contenuti di una pagina JSP, fronte sul quale la
versione 1.2 di Java Server Pages introduce il concetto
di un front-end globale di validazione.
Nel prossimo articolo rivolgeremo la nostra attenzione
agli altri elementi che caratterizzano una Custom Tag
Library; in particolare, analizzeremo la gestione degli
attributi, degli errori, degli eventi, del tag nesting
e delle variabili di scripting.
Bibliografia
[1] Lavinio Cerquetti: "Custom Tag Library in ambienti
J2EE - I parte", Mokabyte N. 73 - Aprile 2003
[2] JSP 1.2 - Tag Library Descriptor Document Type Definition:
http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd
[3] JSP 1.1 - Tag Library Descriptor Document Type Definition:
http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd
Lavinio
Cerquetti si occupa di design e sviluppo del software
in ambienti distribuiti ed in architetture J2EE multi-tier.
Può essere contattato all'indirizzo di e-mail
lcerquetti@mokabyte.it
|