Nel precedente articolo della serie abbiamo descritto le servlet, il componente della J2EE che costituisce la spina dorsale di tutte le web application. In questo articolo introduciamo le Java Server Pages, la tecnologia per la costruzione dell‘interfaccia utente nelle applicazioni web J2EE.
Introduzione
Nel precedente articolo abbiamo descritto i concetti di base riguardanti la Servlet API. Abbiamo visto come le servlet costituiscano la spina dorsale di ogni applicazione web J2EE consentendo di gestire in maniera molto semplice per lo sviluppatore il paradigma richiesta/risposta tipico di queste applicazioni. Come abbiamo già accennato il ruolo principale di una servlet è quello di controller; una servlet gestisce le richieste dei client e delega l‘elaborazione a componenti opportuni in base alla logica applicativa. Nel primo esempio di servlet abbiamo anche visto come sia possibile inviare al client un flusso HTML di risposta inserendo direttamente nel codice di uno dei metodi di servizio, doGet() e doPost(), il codice della pagina HTML. Questa tecnica, interessante solo da un punto di vista didattico, non è quella usata nelle applicazioni reali per la costruzione dell‘interfaccia utente. Per il livello di presentation di una web application J2EE ci viene in aiuto un‘altra specifica fondamentale nella piattaforma J2EE, le Java Server Pages.
Le Java Server Pages
Il layer di presentation di una applicazione web, e di una applicazione in generale, è estremamente importante perché è quello che consente all‘utente di fruire delle funzionalità dell‘applicazione stessa. Una interfaccia utente costruita correttamente sia dal punto di vista grafico sia funzionale è molto importante per il successo di una applicazione. Nel mondo delle applicazioni web l‘interfaccia utente è costituita da un internet browser, Internet Explorer Mozilla Firefox o altri, che è in grado di interpretare codice HTML. Abbiamo già discusso nel primo articolo la differenza tra pagine statiche e dinamiche e abbiamo visto come siano le seconde a assumere particolare rilevanza nel mondo delle applicazioni web. La tecnologia che nell‘ambito della J2EE ci consente di costruire pagine web dinamiche è la Java Server Pages.
Dal punto di vista dello sviluppo una JSP a prima vista non sembra molto diversa da una comune pagina HTML. Il sorgente è un normale file di testo contenente tag HTML e una serie di direttive, dichiarazioni e tag particolari che vedremo.
Ma nonostante l‘aspetto del suo sorgente una JSP è qualcosa di molto diverso da una comune pagina web statica. La differenza risulta evidente quando si analizza cosa accade quando una pagina JSP viene invocata da un client e va in esecuzione.
Innanzitutto è bene sottolineare che, come si evince dal nome stesso, una JSP è un componente server-side, che va in esecuzione nel web container e, anche se viene scritta come fosse una pagina HTML, non va in esecuzione lato client.
La cosa però veramente importante da sottolineare è che una JSP è una classe Java ed in particolare è una servlet. Una JSP unisce quindi tutte le caratteristiche di una normale servlet alla possibilità di creare una interfaccia web dinamica utilizzando le stesse tecniche usate nella scrittura di pagine web statiche.
Il sorgente di una pagina JSP è un file di testo con estensione .jsp che contiene al suo interno tag HTML più altri elementi caratteristici della specifica JSP.
Una pagina JSP viene deployata nel web container è può essere invocata da un internet browser analogamente a quanto accade per una semplice pagina HTML. A differenza però di quanto avviene per una semplice pagina HTML il processo di elaborazione di una JSP è molto più complesso.
Quando il web server riceve una richiesta per una pagina JSP non essendo in grado di soddisfarla delega l‘elaborazione al web container. La pagina JSP a questo punto viene tradotta dal web container in una classe Java, viene compilata, viene caricata in memoria ed inizializzata analogamente a quanto visto per una comune servlet. Dopo la prima richiesta la servlet generata dalla traduzione e dalla compilazione della pagina JSP sorgente resta in memoria nello stato di servizio per ricevere e gestire le richieste dei client.
Da questo momento in poi la JSP è in grado di servire tutte le richieste client ad essa dirette in modo assolutamente identico a quanto accade per una servlet. Dopo il processo di elaborazione costituito da traduzione, compilazione, caricamento in memoria e istanziamento la JSP non è altro che una servlet e segue lo stesso ciclo di vita.
Nella Figura 1 è rappresentato il processo descritto:
Figura 1 – L‘elaborazione di una pagina JSP
La codifica di una pagina JSP
È interessante capire come quello che scriviamo in una pagina JSP venga poi tradotto nella classe generata dal container. Come primo esempio possiamo vedere una pagina JSP molto semplice che produce un output analogo a quello prodotto dalla servlet vista nel precedente articolo della serie. Il sorgente della nostra prima pagina hello.jsp è il seguente:
<%@ page contentType="text/html;charset=windows-1252"%>
hello
HELLO WORLD!
E‘ facile notare come il codice della pagina hello.jsp sia quasi del tutto del puro e semplice codice HTML a meno della prima riga che vedremo essere una direttiva JSP.
La pagina in questione però non viene servita direttamente al client dal web server ma subisce il processo di elaborazione descritto al paragrafo precedente. A seguito della traduzione che il web container esegue quando un client invoca per la prima volta la pagina JSP si ottiene la seguente classe Java:
package org.apache.jsp;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase
implements org.apache.jasper.runtime.JspSourceDependent {
private static java.util.List _jspx_dependants;
public Object getDependants() {
return _jspx_dependants;
}
public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
JspFactory _jspxFactory = null;
PageContext pageContext = null;
HttpSession session = null;
ServletContext application = null;
ServletConfig config = null;
JspWriter out = null;
Object page = this;
JspWriter _jspx_out = null;
PageContext _jspx_page_context = null;
try {
_jspxFactory = JspFactory.getDefaultFactory();
response.setContentType("text/html;charset=windows-1252");
pageContext
= _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write(" ");
out.write(" ");
out.write(" ");
out.write(" ");
out.write("hello ");
out.write(" ");
out.write(" ");
out.write("HELLO WORLD! ");
out.write(" ");
out.write("");
} catch (Throwable t) {
if (!(t instanceof SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
out.clearBuffer();
if (_jspx_page_context
!= null) _jspx_page_context.handlePageException(t);
}
} finally {
if (_jspxFactory
!= null) _jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
La classe hello_jsp.java è stata generata eseguendo la JSP su Jakarta Tomcat 5.5 uno dei più diffusi web container, ma il risultato sarebbe stato analogo in un qualsiasi altro web container J2EE compliant.
Già da questo semplice esempio è facile osservare dove vada a finire il codice scritto nel sorgente della pagina e cosa aggiunga di suo il traduttore JSP.
Il codice HTML statico viene generato mediante delle out.write() analogamente a quanto facevamo nel primo esempio di servlet proprio allo scopo di fare vedere che questa è la tecnica usata nelle servlet generate dalle pagine JSP. Il codice che genera il flusso HTML fa parte del metodo _jspService() che è l‘analogo dei metodi doGet() e doPost() di una normale servlet. All‘inizio del metodo _jspService() il traduttore inserisce la definizione di una serie di oggetti standard quali ad esempio il ServletConfig ed il ServletContext. Questi oggetti detti "impliciti" perché vengono definiti automaticamente in fase di traduzione sono a disposizione in tutte le pagine JSP e consentono quindi di svolgere tutte le operazioni comunemente effettuate all‘interno dei metodi di una servlet.
L‘esempio banale presentato ha lo scopo quindi di far comprendere che una pagina JSP non è altro che una Java Servlet, che all‘interno di essa è possibile inserire codice Java così come si fa con una normale classe e che una pagina JSP ha la visibilità di tutti gli oggetti a disposizione delle servlet di una applicazione.
Gli elementi fondamentali delle pagine JSP
La prima JSP che abbiamo visto è estremamente semplice e differisce da poco da una normale pagina HTML. In realtà in una pagina JSP sono molti gli elementi di differenza rispetto ad una pagina statica.
Gli elementi fondamentali che costituiscono una pagina JSP sono
- direttive
- scriptlet
- espressioni
- dichiarazioni
Le direttive sono delle istruzioni che si possono dare al container in modo da influenzare la fase di traduzione della pagina JSP in classe Java. Ad esempio con una direttiva si può importare un package nel sorgente della classe java generata dalla pagina JSP. Una direttiva è inserita tra i simboli <%@ %> come nell‘esempio che segue:
<%@ page import="miopackage.*" %>
Le direttive sono tre, page include e taglib,e per una loro descrizione approfondita rimandiamo al tutorial J2EE [2]. La cosa importante a questo livello da sottolineare è che una direttiva agisce in fase di traduzione di una pagina JSP non in fase di compilazione nà© di esecuzione.
Altro elemento fondamentale sono gli scriptlet. Gli scriptlet sono normali istruzioni Java inserite nel sorgente di una pagina JSP tra i simboli <% %> che il traduttore inserisce nel corpo del metodo _jspService() in fase di traduzione. Utilizzando gli scriptlet è quindi possibile scrivere qualsiasi cosa in Java in una pagina JSP anche se questa pratica è estremamente sconsigliata perché porta alla realizzazione di pagine JSP incomprensibili e difficili da mantenere. Alcuni consigli sulle best practises per la realizzazione di pagine JSP scriptless sono riportate in [3].
Ulteriore elemento fondamentale sono le espressioni. Una espressione è racchiusa tra i simboli
<%= %>
e consente di inviare nell‘output della pagina qualsiasi cosa che sia il risultato dell‘istruzione inserita tra i due tag visti. In pratica il container prende qualsiasi cosa si inserisca tra i tag <%= %> e lo mette come argomento di una istruzione che stampa sullo stream di risposta.
Ad esempio scrivere in una pagina JSP:
<%= miooggetto.getValore() %>
viene tradotto nel metodo _jspService() in una istruzione del tipo
out.write(miooggetto.getValore())
In pratica l‘output del metodo getValore() dell‘oggetto miooggetto viene stampato sulla pagina.
Altro elemento di base sono le dichiarazioni. Una dichiarazione consente di definire variabili o metodi nella classe Java generata dalla traduzione della pagina JSP. Anche con uno scriptlet è possibile definire una variabile ma a differenza di queste le variabili definite con una dichiarazione non sono locali al metodo _jspService() ma esterne, ovvero sono variabili di istanza. Le dichiarazioni sono inserite tra i tag <%! %>.
Quind scrivere <% int numero = 0; %> si traduce nel definire una variabile numero di tipo int inizializzata al valore 0 all‘interno del metodo _jspService(). Scrivere invece <%! int numero = 0; %> si traduce nel definire un attributo di nome numero di tipo int inizializzato a 0 nella classe generata dalla traduzione della pagina JSP.
così come si definiscono variabili con le dichiarazioni è possibile definire metodi anche se questa è una pratica poco diffusa in quanto la best practice ripetiamo è quella di scrivere pagine scriptless [3].
Il ruolo delle JSP
Abbiamo introdotto nei paragrafi precedenti alcuni elementi di base della tecnologia JSP per far comprendere prima di tutto cosa sia una JSP e come venga elaborata dal web container. La carrellata degli elementi di base che costituiscono una pagina JSP non è ovviamente esaustiva perché sono molti gli aspetti che meriterebbero attenzione e che non possono essere oggetto di questo primo articolo introduttivo.
Una cosa da sottolineare subito è però il ruolo che hanno le pagine JSP in una applicazione web ben strutturata. così come avevamo visto che il ruolo delle servlet è quello di controller possiamo affermare che il ruolo delle JSP è quello di presentation. Una JSP deve realizzare il livello di presentazione all‘utente dei dati dell‘applicazione e deve rispondere agli input dell‘utente notificandoli allo strato di controllo dell‘applicazione. Quello che non deve essere assolutamente inserito in una pagina JSP sono istruzioni relative alla business-logic dell‘applicazione. Il fatto che in una pagina JSP sia possibile inserire codice Java analogamente a quanto si fa in una regolare classe è una forte tentazione soprattutto per lo sviluppatore inesperto. Questa pratica conduce ad applicazioni non gestibili, difficili da comprendere e manutenere, nelle quali non c‘è una separazione logica tra i vari livelli che la costituiscono. Inoltre così facendo si vanificano tutte le potenzialità che un linguaggio object-priented come Java ci può offrire. In conclusione come regola di buon senso si può dire che una pagina JSP dovrebbe somigliare più ad una pagina HTML che ad una classe Java.
Ovviamente per ottenere questo risultato si devono utilizzare alcuni strumenti non visti in questo capitolo come l‘espression language e i custom tag già trattati in parte negli articoli della serie sulle JSTL [3].
Conclusioni
In questo articolo è stata introdotta la tecnologia delle Java Server Pages lo strumento della J2EE per la costruzione della view di una applicazione web. Come già fatto nel caso delle servlet l‘intento era di fornire un‘introduzione di natura più concettuale che pratica per far capire soprattutto a chi per la prima volta si avvicina allo sviluppo di applicazioni web in Java quali siano gli strumenti che la J2EE mette a disposizione. Nei prossimi articoli affronteremo aspetti più di dettaglio che ci faranno capire come poi si possano utilizzare tutti questi strumenti per la realizzazione di applicazioni reali.
Riferimenti
[1] Bryan Basham - Kathy Sierra - Bert Bates, "Head First - Servlet & Jsp", O‘Reilly, 2004
[2] Autori Vari, "The J2EE 1.4 Tutorial ", Sun Microsystems, 2003
[3] Alfredo Larotonda, "La Java Server Pages Standard Tag Library. I parte: Scrivere JSP scriptless" MokaByte 91, dicembre 2004