Introduzione
L'utilizzo piu' comune che si fa dell'application server di Apache e' quello di sviluppare applicazioni web e poi deployarle (generando un war) all'interno della cartella webapps. Questa cartella e' configurata di default per autoscompattare i files war che vi si trovano, e cercare al loro interno un file di nome WEB-INF/web.xml. Questo files e' il vero cuore dell'applicazione web che stiamo deployando, serve a descrivere il mapping tra le servlet e gli url e quindi in poche parole il legame tra la richiesta del browser e la classe java che servira' la risposta.
La cartella webapp ha una particolarita', e' gestita dal portale come un UNICO host (potremmo chiamarlo "sito") con all'interno molte parti (le varie applicazioni che vi sono state deployate).
Un esempio pratico:
Abbiamo 2 applicazioni che convivono contemporaneamente, deployate come webapps, GestioneUtenti e Comunicazioni. Percio' la struttura del tomcat sara':
<tomcat base>
| - webapps
| - GestioneUtenti
| - Comunicazioni
| - bin
| - etc etc..
e queste due applicazioni saranno visibili agli url:
http://localhost:8080/GestioneUtenti
http://localhost:8080/Comunicazioni
Il problema
Cosa succede se (ed e' la norma ovviamente) in questo ambiente usassimo delle jsp legate alle servlet? E se all'interno di queste due applicazioni avessimo 2 jsp con lo stesso nome, ad esempio index.jsp?
Immaginiamo che di default gli url citati sopra portino a queste index.jsp e vediamo cosa succederebbe.Visto quanto abbiamo detto prima, che la cartella webapps rappresenta un unica applicazione, si ha che tutte le applicazioni deployate all'interno condividono la stessa work directory, ovvero il percorso fisico che tomcat usa per immagazzinare le sessioni, salvare i files temporanei e le jsp compilate.
Se noi avviassimo tomcat e accedessimo ad http://localhost:8080/GestioneUtenti/ , ci apparirebbe sicuramente la pagina che ci aspettiamo (la nostra GestioneUtenti/index.jsp)
Ma nel momento in cui noi accedessimo al secondo url, http://localhost:8080/Comunicazioni/, verrebbe propagata la richiesta per "index.jsp" e il catalina (il motore di tomcat) ed in particolare jasper (il gestore delle jsp) andrebbero in primo luogo a cercare una versione cachata di tale pagina. Dal momento che tutte queste applicazioni condividono la stessa working directory jasper, verrebbe trovata una versione cachata di "index.jsp" la quale verrebbe servita come risposta, ma in realta' questa pagina non sarebbe che la cache della index.jsp dell'applicazione GestioneUtenti!
La Soluzione
Per ovviare al problema ci sono 2 approcci, in relazione ai permessi che avete a disposizione sul tomcat.
La prima soluzione prevede il deploy di un nuovo context.xml (che deve trovarsi all'interno della cartella META-INF, ad esempio GestioneUtenti/META-INF/context.xml). All'interno di questo file e' possibile modificare il context dell'applicazione, slegandola appunto da tutte le altre webapps.
Il nodo radice ,secondo la DTD del file, deve essere l'elemento Contex e proprio qui noi andremo a lavorare, infatti aggiungendo l'attributo workDir e' possibile modificare la working directory per far si che ogni applicazione, utilizzando percorsi diversi non corra piu' il rischio di trovarvi dentro la cache jsp di ALTRE applicazioni. Continuando l'esempio dovremmo avere:
<Context workDir="work/GestioneUtenti/"> in GestioneUtenti/META-INF/context.xml
<Context workDir="work/Comunicazioni/"> in Comunicazioni/META-INF/context.xml
Ma ci potrebbero essere delle complicazioni, infatti sempre potrebbe essere possibile includere un nuovo context, in quanto quest'opzione e' a discrezione dell'amministratore del tomcat e potrebbe non essere modificabile.
Se questo e' il caso, come agire (oltre a prendersela a parole con suddetto amministratore)?
La soluzione e' utilizzare il web.xml che configura la nostra singola applicazione!
all'interno di questo files infatti e' possibile ridefinire (localmente alla nostra applicazione) le varie servlet globali definite nelle impostazioni di tomcat, in particolare a noi interessa la:
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
questa servlet e' quella che definisce il motore di compilazione delle jsp ed e' su questa che noi possiamo intervenire! Bastera' infatti aggiungere questo init-parameter (un parametro che la servlet legge all'avvio) per riuscire a modificare la directory in cui vengono posizionate le jsp compilate (che di default coincide con la workDir del context)
Percio' se noi aggiungiamo al web.xml di ogni applicazione del nostro esempio
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
<init-param>
<param-name>fork</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>xpoweredBy</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>scratchdir</param-name>
<param-value>/tmp/<NOMEAPPLICAZIONE></param-value>
</init-param>
<load-on-startup>3</load-on-startup>
</servlet>
saremo sicuri che nessuna delle due sovrascriva la cache jsp dell'altra e non capitera' mai di vedere pagine "sfasate" tra le varie applicazioni!
Conclusione
Con i metodi illustrati nell'articolo e' possibile differenziare la posizione dei file di cache generati dal motore di compilazione delle jsp di tomcat (jasper) e fare si che ogni applicazione deployata nelle webapps abbia un proprio percorso privato in modo da evitare che la cache jsp di pagine con lo stesso nome venga servita in applicazioni diverse.