Anche nel mondo JSP, come in quello delle classiche applicazioni Java, ci si trova, non di rado, nella situazione di dover affrontare e risolvere gli immancabili errori che sorgono quando si utilizza una tecnologia potente e complessa come Java. In JSP gli errori più comuni possono essere catalogati in due categorie:
- HTTP Status 404 – File Not Found Error
- HTTP Status 500 – Internal Server Error
Errori causati da risorse non disponibili
La prima categoria riguarda gli errori che scaturiscono da situazioni in cui una risorsa richiesta non venga trovata. Se, ad esempio, si utilizza Tomcat come Web Application Server per le nostre pagine JSP, un errore 404 indicherà che Tomcat ha regolarmente ricevuto la richiesta da un client ma non è stato in grado di reperirla e gestirla.
Questo genere di errore, solitamente, si risolve verificando accuratamente che siano stati indicati correttamente sul client il path ed il file relativi alla richiesta e che, nella locazione indicata dalla URL, sia effettivamente presente sul server la risorsa desiderata.
Errori di Compilazione
La seconda categoria di errori viene identificata dal server attraverso il messaggio HTTP 500, che corrisponde ad un errore interno del Server (Internal Server Error). A questa categoria appartengono sia gli errori causati da problemi intercorsi durante la compilazione di una pagina JSP sia quelli che si verificano a run-time.
Nel primo caso, il server riceve la richiesta dal client e riesce con successo ad identificare la risorsa associata a tale richiesta. Tenta, quindi, di eseguire la compilazione della pagina in questione ma, a causa di un errore nel codice, fallisce e, pertanto, non riesce ad esaudire la richiesta del client.
Per risolvere questo genere di errori, solitamente è sufficiente esaminare con attenzione il messaggio contenuto nella pagina di errore generata dal Server. Ad esempio, supponiamo di avere la seguente pagina JSP:
Listato 1. Pagina JSP
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>Informazioni Utente</title></head>
<body>
<%
String nome = request.getParameter("nome");
String cognome = request.getParameter("cognome")
%>
<h1>Dati utente</h1>
<p>Ecco le informazioni relative all'utente inserito:</p>
<table cellspacing="5" cellpadding="5" border="1">
<tr><td align="right">Nome:</td><td><%= nome %></td></tr>
<tr><td align="right">Cognome:</td><td><%= cognome %></td></tr>
<tr><td align="right">Eta':</td><td><%= Integer.parseInt(request.getParameter("eta")) %></td></tr>
</table>
<p>Per inserire un nuovo utente, cliccare sul pulsante "Back"
del browser oppure sul pulsante Nuovo Inserimento in basso.</p>
<form action="addUser.html" method="post">
<input type="submit" value="Nuovo Inserimento">
</form>
</body>
</html>
Si crei, quindi, una directory a propria scelta sotto la cartella "WebApps" di Tomcat (ad es. "SimpleJSP") e si salvi il codice precedente denominandolo, ad esempio, "show_user.jsp".
Nel codice della pagina JSP, la riga evidenziata in rosso è priva di punto e virgola finale e serve per causare un errore.
A questo punto, per eseguire la nostra pagina JSP, costruiamo, per completezza, una semplice pagina HTML che raccolga i dati in input ed abbia come action la pagina "show_user.jsp" (potremmo, naturalmente, anche invocare la pagina JSP direttamente fornendole i parametri sulla URL).
Listato 2. Pagina HTML con il form
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>Inserimento Utente</title></head>
<body>
<h1>Inserimento utente</h1>
<p>Per inserire un utente riempire i campi sottostanti.<br />
Al termine,cliccare sul pulsante Invia.</p>
<form action="show_user.jsp" method="get">
<table cellspacing="5" border="0">
<tr>
<td align="right">Nome:</td>
<td><input type="text" name="nome"></td>
</tr>
<tr>
<td align="right">Cognome:</td>
<td><input type="text" name="cognome"></td>
</tr>
<tr>
<td align="right">Eta':</td>
<td><input type="text" name="eta"></td>
</tr>
<tr>
<td></td>
<td><br><input type="submit" value="Invia"></td>
</tr>
</table>
</form>
</body>
</html>
La pagina JSP precendete ci rimanda a questo form se clicchiamo sul pulsante "Nuovo Inseriemnto". Salviamola, quindi, come "addUser.html". Proviamo, adesso ad eseguire il tutto, partendo proprio dalla pagina HTML appena salvata. Digitiamo sul browser l'indirizzo
http://localhost:8080/SimpleJSP/addUser.html
ed inseriamo i dati nel form
All'invio del form, Tomcat restituirà la seguente pagina di errore:
In essa è specificato, chiaramente, che il server ha incontrato un errore alla linea 8 durante la compilazione della pagina e che l'errore stesso è dovuto alla mancanza del punto e virgola al termine di un'istruzione.
Risolto il problema, basterà risalvare il nostro file e ricaricare nuovamente la pagina JSP. Adesso, il risultato sarà quello atteso:
Errori a Run-Time
Per quanto riguarda gli errori a run time, il risultato visivo è analogo a quello mostrato nella figura precedente; in questi casi verrà evidenziato il punto del codice che ha causato un'eccezione inattesa all'interno della pagina, durante l'esecuzione del codice Java in essa contenuto.
Ad esempio, nella JSP precedente, se si fornisce una stringa per il parametro eta, al posto di un intero, il metodo Integer.parseInt()
scatenerà una NumberFormatException
non riuscendo, quindi, a soddisfare la richiesta e causando il seguente errore HTTP 500:
Abbiamo visto fin'ora come il Web Application Server si comporti in presenza di errori di compilazione o eccezioni non gestite. In questa parte dell'articolo vediamo come gestire questi errori in modo personalizzato.
Pagine di Errore personalizzate
Per quanto riguarda gli errori a run-time, apriamo una breve parentesi relativamente alla opportunità di visualizzare la pagina di errore generata automaticamente dal server.
Si capisce che, per i non addetti ai lavori, la visualizzazione di una web form contenente informazioni di carattere prettamente tecnico potrebbe risultare poco gradevole e, talvolta, irritante.
Questo è il motivo per cui dovremo fare attenzione ad utilizzare un simile approccio soltanto nelle fasi di sviluppo e collaudo di un'applicazione e, invece, ricorrere ad una pagina più "digeribile" quando porteremo la nostra applicazione in ambiente di produzione.
Per far questo basterà definire una pagina di errore generica, impostando in essa la direttiva isErrorPage
a true
, e inserire nelle pagine JSP appartenenti alla nostra applicazione l'attributo errorPage
, impostandone il valore con la URL della pagina di errore personalizzata (Per specificare delle pagine di errore relative ad un'intera applicazione è possibile avvalersi del tag
Nella nostra semplice pagina JSP (show_user.jsp), ad esempio, basterà inserire all'inizio il seguente tag:
<%@ page errorPage="genericError.jsp" %>
per rindirizzare l'utente alla pagina "genericError.jsp" in caso di errori a run-time. Il codice di una generica pagina di errore potrebbe essere, ad esempio:
Listato 3. Pagina di errore generica
<%@ page isErrorPage="true" import="java.io.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head><title>Errore Applicazione</title></head>
<body>
<h1>Errore</h1>
<p>Si e' verificato un errore imprevisto. Si prega di riprovare piu' tardi.</p>
<p><em><%= exception %></em></p>
<%
out.println("<!--");
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
exception.printStackTrace(pw);
out.print(sw);
sw.close();
pw.close();
out.println("-->");
%>
</body>
</html>
Inseriamo, adesso, lo stesso input che aveva causato l'ultimo errore HTTP 500 e, questa volta, otterremo:
Ci sono due cose interessanti da evidenziare nel codice java della pagina di errore:
- L'oggetto implicito exception (evidenziato in rosso nel codice precedente) viene utilizzato direttamente nell'espressione:
<%= exception %>
, in quanto automaticamente convertito in stringa - Lo scriptlet finale (in grassetto), che consente di raccogliere maggiori informazioni sull'eccezione verificatasi ma che scrive tale contenuto in un commento HTML, in modo che i dettagli tecnici non siano direttamente visibili sulla pagina ma siano consultabili, all'occorrenza, da un tecnico
Infatti, se andiamo a visualizzare il codice sorgente, attraverso il browser, potremo notare le seguenti righe:
Listato 4. Commento generato dalla pagina di errore personalizzata
<!--
java.lang.NumberFormatException: For input string: "Trentanove"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at org.apache.jsp.show_005fuser_jsp._jspService(show_005fuser_jsp.java:77)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:97)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
...
...
-->
Identificazione degli errori attraverso la Servlet generata dal Server
Per prima cosa, riproduciamo l'errore di compilazione iniziale, eliminando un punto e virgola da un'istruzione della nostra pagina JSP e salviamo il codice.
Esiste un ulteriore metodo, come ultima spiaggia, per scovare eventuali errori occorsi durante la compilazione o il processamento di una pagina JSP. Prima, però, è bene rinfrescare la memoria relativamente al flusso che segue una pagina JSP prima di poter essere visualizzata su un browser. Vediamo il grafico seguente:
Ogni pagina JSP, alla prima richiesta, viene sempre tradotta e compilata in una servlet. Tutte le susseguenti richieste vengono gestite rifacendosi alla servlet generata e creando dei nuovi thread che processino le singole richieste pervenute.
Dunque, in fase di collaudo, qualora non fossimo riusciti ad identificare un problema attraverso i suggerimenti fin qui descritti, sarà sempre possibile andare ad esaminare direttamente il codice della Servlet associata alla nostra pagina JSP.
In Tomcat, tutte le servlet generate vengono salvate sotto la directory "work/Catalina/localhost".
Nel nostro caso, sotto la directory "localhost", troveremo una ulteriore cartella denominata "SimpleJSP", navigando all'interno della quale sarà possibile trovare il codice della Servlet generata, come mostrato nella seguente figura:
Nel caso mostrato in figura, la nostra Servlet è stata generata ma, per qualche ragione (sappiamo benissimo quale!) Tomcat non è riuscito a produrre il .class. Aprendo il file potremo navigare all'interno del codice e scoprire che c'è una riga (Evidenziata in rosso nel listato 1) che non contiene il punto e virgola finale.
Torniamo, quindi, alla pagina JSP salvata in WebApps/SimpleJSP, correggiamo il codice e rilanciamo l'applicazione. Non ci sorprende, adesso, scoprire che tutto funziona correttamente. Curiosando ancora nella cartella in cui abbiamo trovato il codice sorgente della nostra Servlet, possiamo verificare che il .class è stato adesso regolarmente generato: