Introduzione
Avete mai provato ad avvicinarvi, amichevolmente,
ad un programmatore Java ed a sussurrargli all'orecchio
la parola 'JSP' ? Non fareste altro che provocare, in
lui come in ogni altro membro della sua specie, una
reazione di aperta ostilità.
Il framework JSP [1] - acronimo di JavaServer Pages
- introdotto da Sun in tutta fretta alcuni anni or sono
per dotarsi di uno strumento analogo al protocollo ASP
di Microsoft, ha infatti avuto una vita tormentata nel
panorama dei prodotti e protocolli Java. A lungo - e
giustamente - criticata per via delle sue numerose lacune
architetturali, questa tecnologia è stata considerata
una sorta di 'pecora nera' nell'ambito del mondo J2EE,
e per anni le sono stati preferiti framework di templating
indipendenti - quali FreeMarker [2], Velocity [3] e
WebMacro [4] - o più specificatamente votati
all'implementazione di architetture Model-View-Controller
come Jade [5] e Struts [6].
Le principali critiche mosse a JSP prendono spunto dal
fatto che, per via del suo ridotto time-to-market iniziale,
esso non risulti ben integrato con le linee guida e
l'insieme di best practice e design pattern caratterizzanti
lo sviluppo di software distribuito e multi-tier, e
che la sua struttura porti alla realizzazione di applicazioni
scarsamente manutenibili ed inerentemente non scalabili,
caratterizzate da un'insufficiente separazione di ruoli
logici e responsabilità funzionali tra i diversi
software layer.
A queste considerazioni si aggiunga come, in seguito
alle evoluzioni strutturali del panorama di API e protocolli
Java ed alla sempre maggiore disponibilità di
soluzioni alternative, il ruolo di JSP nella realizzazione
di applicazioni Java Enterprise e le sue effettive possibilità
ed opportunità di integrazione con strumenti
di valore già noto ed assodato siano risultati
a lungo poco chiari ed abbiano costituito una continua
fonte di dubbio per la stessa comunità degli
sviluppatori.
Sun,
riconoscendo i limiti che hanno impedito al framework
JSP di giocare un ruolo di primo piano nell'implementazione
di sistemi software Java-based, si è ben presto
messa al lavoro allo scopo di identificarne e risolverne
tanto le lacune di design quanto i problemi tecnici.
Un primo risultato è stato raggiunto, due anni
or sono, con l'introduzione del JSP Model 2, approccio
strutturale volto a rendere compatibile il framework
JSP con architetture Model-View-Controller e con i pattern
fondamentali utilizzati nello sviluppo di strati di
presentazione per software distribuito (Business Delegate,
Composite View, Service to Worker e View / Helper).
Tale chiarimento 'filosofico' del ruolo di JSP è
stato accompagnato, a partire dalla versione 1.1 delle
specifiche, da innovazioni tecniche che hanno costituito
il presupposto per l'evoluzione presente e futura di
questa tecnologia, da un lato nell'ottica di un generale
miglioramento della sua integrabilità ed user-friendliness,
dall'altro nel senso di un suo effettivo inquadramento
all'interno dell'architettura J2EE come software layer
deputato alla gestione del presentation tier in client
Web-based a servizi remoti e componenti distribuiti.
Delle nuove possibilità offerte da JSP la libreria
JSTL [7] - discussa in quest'articolo - costituisce
al contempo un esempio ed un'applicazione fondamentale:
tale Custom Tag Library, rilasciata nella sua versione
1.0 nel mese di Giugno, diverrà ufficialmente
standard con l'imminente specifica 2.0 di JSP, di cui
è già disponibile il Proposed Final Draft
[8], e costituisce il tanto atteso punto di svolta nell'evoluzione
di questo framework, al punto che non è errato
asserire che esistano due JSP: un JSP ante-JSTL ed un
JSP post-JSTL.
Il
ruolo di JSTL nell'utilizzo odierno di JSP
JSP, essenzialmente, può venire descritto come
un ambiente per la produzione di contenuti Web dinamici
che si materializzano grazie alla possibilità
di innestare, all'interno di componenti statici di presentazione
- tipicamente implementati tramite pagine HTML - comportamenti
aggiuntivi i cui esiti vengono risolti solamente a run-time.
Tali comportamenti sono stati espressi, nelle prime
versioni di JSP, attraverso dei brani di codice Java
inseriti direttamente nelle pagine HTML e denominati
scriptlet, ovvero tramite dei tag proprietari (action
in gergo JSP) normalmente associati al namespace jsp
ed usualmente utilizzati per accedere a proprietà
e metodi di oggetti esterni.
Purtroppo tale utilizzo di JSP, come già fatto
notare nell'introduzione di questo articolo, oltre ad
essere caratterizzato da una quantità di problematiche
irrisolte a livello di design, porta a delle pagine
HTML estremamente difficili da gestire e manutenere,
rendendo nella pratica difficilmente realizzabile quella
separazione di ruoli tra sviluppatori software e grafici
Web che è alla base delle moderne pratiche collaborative
di software development in architetture complesse e
multi-tier.
Il framework JavaServer Pages, a partire dalla versione
1.1, ha introdotto la possibilità per gli sviluppatori
di arricchire il contesto di esecuzione delle pagine
JSP di nuovi comportamenti, espressi tramite tag aggiuntivi
e redatti sotto forma di classi Java raggruppate in
contenitori denominati 'Custom Tag Library', ovvero
'JSP Tag Extensions'; da qui alla formalizzazione di
una libreria di action standard, con la quale fornire
ai programmatori un patrimonio comune di tag in grado
da un lato di garantire la sostanziale compatibilità
delle pagine JSP al variare del Web Container e dall'altro
di fornire quei costrutti di programmazione necessari
per svincolare il framework di Sun dal continuo ricorso
agli scriptlet Java, il passo è stato breve.
Tale
libreria di tag, sviluppata in seno al Java Community
Process [9] dall'Apache Group, è appunto JSTL.
Tecnicamente parlando, essa consiste in una collezione
di Custom Tag Library, organizzate e suddivise per categorie
funzionali.
Si noti che JSTL utilizza funzionalità ed API
delle Custom Tag Library introdotte a partire dalla
versione 1.2 di JSP, e non risulta pertanto compatibile
con Web Container che implementino versioni precedenti
di questo framework.
Come già detto, JSTL diverrà un componente
standard di JSP - e quindi dei differenti J2EE Server
- a partire dalla versione 2.0 di JavaServer Pages;
sino ad allora sarà necessario provvedere esplicitamente
alla sua installazione, usualmente copiandone la distribuzione
nella directory WEB-INF/lib delle singole applicazioni
J2EE.
Componenti
fondamentali di JSTL
JSTL si compone di quattro Custom Tag Library, ognuna
delle quali viene mappata in namespace (detti anche
prefix in gergo JSP) ed associata ad URI differenti
e stabiliti per convenzione:
-
core: tale libreria, specificatamente oggetto di quest'articolo,
fornisce tag sostanzialmente paralleli ai costrutti
strutturati di programmazione in Java, al fine di
ridurre al minimo il bisogno di innestare scriptlet
direttamente all'interno delle pagine JSP. La libreria
core implementa inoltre alcune utility action volte
alla manipolazione di URL e contenuti esterni;
- XML
processing: libreria orientata alla gestione di documenti
XML e XSLT;
- I18N
capable formatting: libreria di tag rivolta alla localizzazione
delle applicazioni;
- relational
db access (SQL): libreria di tag rivolta all'utilizzo
di connessioni JDBC dall'interno delle pagine JSP;
si noti che tale libreria, in maniera piuttosto evidente,
non rispetta la separazione dei ruoli tipici delle
applicazioni multi-tier, dal momento che consente
di integrare sezioni di business logic all'interno
di pagine JSP, vale a dire del presentation layer.
Tuttavia la disponibilità di facility per la
gestione diretta di database dall'interno dello strato
di interfaccia utente gioca un ruolo importante nell'implementazione
di sistemi prototipo e di applicazioni di complessità
elementare - oltre ad avere un preciso appeal a livello
di marketing - ragion per cui questa libreria è
stata inclusa come componente standard nella versione
1.0 di JSTL.
Ogni
libreria viene dichiarata nelle pagine JSP che ne richiedono
l'utilizzo tramite la sintassi:
<%@
taglib prefix="<namespace>" uri="<URI>"
%>
Ad
esempio la dichiarazione per la libreria core leggerà:
<%@
taglib prefix="c" uri="http://java.sun.com/jstl/core"
%>
Per
quanto le URI ed i prefissi associati alle singole librerie
siano da intendersi solamente come raccomandazioni formali,
è tuttavia buona pratica attenersi agli standard
indicati per due ordini di motivi:
- Seguendo
tali standard si contribuisce ad incrementare la comprensibilità
e la riusabilità del codice;
- l'utilizzo
degli URI segnalati permette ai singoli J2EE Server
di 'riconoscere' le librerie utilizzate e di implementare
eventuali politiche di ottimizzazione.
Gli
Expression Language
Perché una pagina JSP risulti di una qualche
utilità è indispensabile che essa sia
in grado di rapportarsi alla ricca Object API che contraddistingue
il mondo Java; sorge in altre parole il problema di
come sia possibile accedere ad oggetti esterni e combinarne
le proprietà in espressioni semanticamente significative.
A questo problema sono state date, nel corso dell'evoluzione
di JSTL, due risposte differenti:
EL:
tale acronimo sta semplicemente per Expression Language,
un linguaggio estremamente immediato ed user-friendly
per l'accesso ad oggetti e per l'utilizzo delle loro
proprietà a run-time dall'interno di pagine JSP.
EL, per la sua sintassi semplificata - volutamente ispirata
ad ECMAScript e XPath - ed in virtù del fatto
che non richiede conoscenze specifiche in area Java,
rappresenta lo strumento consigliato nell'utilizzo di
JSTL, ed è l'Expression Language su cui ci soffermeremo
nel corso di quest'articolo;
RT
(Request-time expression language): questo linguaggio,
ormai obsoleto, consente di utilizzare all'interno di
tag JSTL espressioni specificate direttamente nel linguaggio
di scripting della pagina, vale a dire usualmente in
linguaggio Java, in maniera assai simile a quanto permesso
dall'ormai famigerato tag "<%=".
Espressioni
scritte in un Expression Language possono venire utilizzate
sia negli attributi di tutti i tag JSTL - con l'eccezione
dei soli attributi var e scope - sia negli attributi
di eventuali Custom Tag Library di terze parti o proprietarie.
Il
linguaggio EL
Come anticipato, la sintassi del linguaggio EL è
sorprendentemente semplice: ogni espressione EL è
racchiusa all'interno delle sequenze di caratteri '${'
e '$}', ed è possibile accedere alle proprietà
di un oggetto sia secondo la tradizionale sintassi basata
sull'operatore '.' sia considerando l'oggetto alla stregua
di un vettore associativo, le cui proprietà costituiscono
le chiavi del vettore. Ad esempio, per accedere alla
proprietà id dell'oggetto customer (implementata
dai metodi getId() e setId()) è possibile utilizzare
le seguenti sintassi:
${customer.id}$
${customer["id"]}$
Il
vantaggio della seconda sintassi - utilizzabile anche
per estrarre valori da oggetti che implementano l'interfaccia
java.util.Map - risiede, in maniera abbastanza ovvia,
nella possibilità di decidere a runtime la proprietà
cui si desidera accedere, memorizzandone il nome in
una variabile ed accedendovi tramite una sintassi del
tipo:
${customer[propertyName]}$
L'immediatezza
di EL si manifesta anche nella sintassi per l'accesso
ad oggetti di tipo vettore, vale a dire array Java ovvero
oggetti che implementino l'interfaccia java.util.List:
${customerList[0]}$
La
lista dei rimanenti operatori di EL non riserva parimenti
alcuna sorpresa: è interessante notare come per
alcuni operatori matematici e booleani siano definiti
dei sinonimi al fine di mantenere la compatibilità
sia con ECMAScript che con XPath e per evitare il bisogno
di ricorrere alle entity qualora si utilizzi JSP in
modalità XML:
Come
è lecito attendersi gli operatori booleani di
confronto lavorano su oggetti String in modalità
per valore.
Ogni
oggetto definito in uno scope JSP valido viene automaticamente
riconosciuto e può venire utilizzato liberamente
all'interno delle espressioni EL; gli scope JSP sono
esaminati, alla ricerca degli oggetti specificati dall'utente,
nel seguente ordine:
Scope
di pagina;
scope di richiesta HTTP;
scope di sessione;
scope di applicazione.
EL
definisce inoltre una serie di oggetti cosiddetti impliciti:
EL
riconosce, oltre ad oggetti e variabili, costanti espresse
nei formati consueti:
-
Costanti stringa: sequenze di caratteri racchiuse
tra apici singoli o doppi, al cui interno il carattere
di backslash viene utilizzato per identificare dei
caratteri di controllo convenzionali ('\n', '\t',
etc.); per inserire un carattere di backslash all'interno
di una costante stringa, lo stesso deve essere preceduto
da un altro backslash;
- costanti
intere: sequenze numeriche precedute da uno specificatore
opzionale di segno ('+' o '-');
- costanti
decimali: sequenze numeriche precedute da uno specificatore
opzionale di segno e composte di una parte intera
e di una parte decimale, separate tra di loro dal
punto decimale '.'; la parte decimale può venire
espressa in notazione esponenziale;
- costanti
booleane: 'true' e 'false'.
La
libreria JSTL core
Laddove EL definisce un linguaggio per la specifica
di espressioni, la libreria JSTL core definisce i tag
che implementano i controlli di flusso ed i costrutti
strutturati grazie ai quali è possibile esprimere
algoritmi, all'interno di pagine JSP, senza più
dover ricorrere al tag di escape in Java "<%".
Nello
spirito di JSTL, anche i tag sono caratterizzati da
una notevole immediatezza d'uso e facilità di
comprensione, al punto da risultare facilmente intellegibili
anche senza conoscerne in dettaglio le caratteristiche.
A titolo di esempio la visualizzazione dei nominativi
di tutti i contatti memorizzati in un ipotetico address
book potrebbe venire realizzata con un codice simile
al seguente (il namespace c si riferisce, come da convenzione,
alla libreria JSTL core):
<table
border="1">
<tr>
<td>Contatto</td>
</tr>
<c:forEach var="contact" items="${addressBook.contacts}$">
<tr>
<td>
<c:out value="${contact.name$}" />
</td>
</tr>
</c:forEach>
</table>
Tale
codice, utilizzando le tradizionali pratiche di programmazione
JSP basate su scriptlet Java, avrebbe un aspetto simile
al seguente:
<jsp:useBean
id="addressBook" scope="..." />
<table border="1">
<tr>
<td>Contatto</td>
</tr>
<%
Iterator i=addressBook.getContacts().iterator();
while (i.hasNext()) {
Contact contact=(Contact)i.next();
%>
<tr>
<td>
<%= contact.getName()%>
</td>
</tr>
<%
}
%>
</table>
I
vantaggi in termini di leggibilità, manutenibilità
ed interoperabilità sono immediatamente evidenti.
Si noti anche come l'utilizzo di EL e della sua funzionalità
automatica di ricerca degli oggetti nella catena degli
scope correnti ci dispensi dall'utilizzo dei tag "<jsp:useBean>".
Tornando
all'analisi dei tag della libreria JSTL core, possiamo
raggrupparli da un punto di vista logico in tre macrocategorie:
- Tag
di supporto al linguaggio di espressioni: il fine
di questi tag è quello di fornire un 'ponte'
tra il linguaggio di espressioni utilizzato e la libreria
JSTL core. Appartengono a questo gruppo i seguenti
tag:
- out:
utilizzato per valutare un espressione - specificata
nell'attributo value - ed inviarne il risultato
al JspWriter corrente, in maniera analoga a quanto
accade con il tag "<%=";
- set:
imposta il valore di un attributo JSP o di una
proprietà di un oggetto;
- remote:
elimina un attributo / oggetto dallo scope specificato;
- catch:
permette di gestire errori non critici direttamente
dall'interno della pagina JSP.
- Tag
di controllo di flusso: il fine di questi tag è
di fornire versioni JSTL dei costrutti di iterazione
e di scelta:
- if:
implementa un costrutto di scelta analogo allo
statement if del linguaggio Java;
- choose,
when ed otherwise: questi tag implementano un
costrutto di scelta multipla in maniera simile
agli statement Java switch, case e default;
- forEach:
realizza un costrutto di looping, sia basato su
iteratore (come nell'esempio visto in precedenza)
sia - in base agli attributi forniti al tag -
in forma più generica, analogamente allo
statement for di Java; si noti che forEach è
in grado di iterare automaticamente su array di
tipi primitivi, Collection, Iterator ed Enumeration;
- forTokens:
implementa un costrutto di iterazione tramite
parsing di una stringa in maniera simile a quanto
realizzato dalla classe StringTokenizer.
- Tag
di gestione di URL:
-
import: utilizzato per rendere disponibile sotto
forma di variabile il contenuto di un'URL; questo
tag può venire utilizzato semplicemente
per includere il contenuto di un'URL esterna all'applicazione
nella pagina JSP corrente - azione non supportata
dal tag "<jsp:include>" - ovvero
per importare e processare dati remoti, magari
in formato XML, con l'ausilio della libreria JSTL
XML processing;
- url:
permette la costruzione di URL a run-time, in
base agli attributi specificati ed al contesto
dell'applicazione corrente;
- redirect:
provoca una browser redirection.
Conclusioni
In questo articolo abbiamo fornito una visione d'insieme
dei fini e delle funzionalità di JSTL - ed in
maniera più dettagliata di due suoi componenti
fondamentali, l'Expression Language EL e la libreria
JSTL core - nell'ambito dell'evoluzione e degli odierni
campi di utilizzo ed integrazione del framework JSP
in contesti applicativi distribuiti e multi-tier.
Nel
prossimo articolo, avvalendoci delle conoscenze teoriche
appena introdotte, metteremo JSTL alla prova realizzando
un semplice Web Client JSP-based per un'ipotetica applicazione
corporate, che successivamente provvederemo ad internazionalizzare
sfruttando le funzionalità della libreria JSTL
I18N capable formatting e quindi ad integrare - grazie
alla libreria JSTL XML processing - con servizi XML
esterni.
Bibliografia
[1] JSP - JavaServer Pages: http://java.sun.com/products/jsp
[2] FreeMarker: http://www.freemacro.org
[3] Velocity: http://jakarta.apache.org/velocity
[4] WebMacro: http://www.webmacro.org
[5] Jade: http://sourceforge.net/projects/salmon
[6] Struts: http://jakarta.apache.org/struts
[7] JSTL - JSP Standard Tag Library: http://java.sun.com/products/jsp/jstl
[8] JavaServer Pages 2.0 Specification - Proposed Final
Draft: http://jcp.org/aboutJava/communityprocess/first/jsr152/
[9] JCP - Java Community Process: http://jcp.org
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
|