Servlet 3.0

Le Servlet java, una tra le tecnologie maggiormente utilizzate per la costruzione di applicazioni web-based con contenuti dinamici, arricchiscono le loro caratteristiche con un primo rilascio della versione Servlet 3.0 (JSR). Questa Java Specification Request è stata approvata nella forma JSR 315 ed è stata progettata per la Java Enterprise Edition 6 (JSR 316) o superiore. A differenza delle precedenti release, le Servlet 3.0 comprendono innovative caratteristiche che rispondono alle nuove esigenze delle applicazioni web-based.

In questo articolo vogliamo descrivere le nuove caratteristiche chiave introdotte nella nuova versione delle Servlet java. Ovviamente è da tener presente che questa prima release è soggetta a variazioni visto che è ancora work in progress.

Le Servlet 3.0 si focalizzano sulle seguenti nuove features:

  • - Facilità di sviluppo
  • - Pluggability ed extensibility
  • - Supporto asincrono
  • - Migliorare la sicurezza
  • - Altri cambiamenti eterogenei

E’ evidente che le nuove servlet hanno preferito adattarsi alle peculiarità delle altre tecnologie della Java Enterprise Edition. La loro bellezza tuttavia, resta nella loro semplicità e abilità a processare le richieste HTTP e restituire la risposta al client web. Le nuove features delle Servlet 3.0 mirano quindi a facilitare lo sviluppo e ne beneficiano sia gli sviluppatori di servelt che quelli dei framework.

Facilità di sviluppo

La facilità di sviluppo è la chiave del successo di qualsiasi tecnologia. Le API Servlet 3.0 si focalizzano su questa peculiarità utilizzando le notazioni JSR 175 per permettere stili-dichiarativi di programmazione. Essa permette infatti, il rapido sviluppo di servlet o di filter class semplicemente annotandoli con l’appropriata notazione, come ad esempio @Servlet o @ServletFilter. Queste notazioni non solo prendono facilmente il codice di una servlet, un filter o una listener class, ma prendono anche i deployment descriptor opzionali per una web application. Il web container è responsabile di processare le notazioni che si trovano in classi nella directory WEB-INF/classes, in un file .jar della directory WEB-INF/lib o in classi che si trovano in altri classpath dell’applicazione.

Notazioni vs Deployment descriptor

E’ interessante notare che i deployment descriptor hanno precedenza sulle notazioni. In altre parole, essi prelevano le informazioni di configurazione specificate attraverso il meccanismo delle notazioni. La versione 3.0 dei web deployment descriptor contengono un nuovo attributo chiamato metadata-complete nell’elemento web-app; esso definisce se il web descriptor è completo, o se i file class dell’applicazione web devono essere esaminati per le annotazioni che specifica il deployment information. Se l’attributo è settato a true il deployment tool deve ignorare qualsiasi notazioni servlet presente nei file class ed usare solo i dettagli della configurazione definita nel descriptor. Altrimenti se il valore non è specificato oppure è settato a false, il container deve esaminare tutte i file class dell’applicazione per trovare le notazioni specificate. Questo fornisce un modo di abilitare o disabilitare l’utilizzo delle notazioni ed il loro processo durante l’avvio dell’applicazione. Tutte le notazioni introdotte possono essere trovate all’interno dei package javax.servlet.http.annotation e javax.servlet.http.annotation.jaxrs.

Nella sezione seguente viene mostrato il set di notazioni delle Servlet 3.0:

@Servlet: javax.servlet.http.annotation. E’ una notazione class-level la quale afferma che le classi annotate e i suoi metadati devono essere dichiarati come servlet. L’attributo urlMapping è un’attributo obbligatorio di @Servlet che specifica il pattern dell’url che invoca la servlet. Quando arriva una richiesta, il container confronta l’URL nella request con l’urlMapping della servlet e se corrispondono, la servlet associata viene invocata per servire la request. Tutti gli altri attributi di questa notazione sono opzionali con valori di default. Possono arrivare metodi annotati con uno delle notazioni dell’HttpMethod, come GET, PUT, POST, HEAD, o DELETE nella classe servlet. Questi metodi devono prendere l’HttpServletRequest e l’ HttpServletResponse come parametri del metodo. La versione 3.0 può essere implementata anche come Plain Old Java Objects (POJOs) a differenze delle precedenti versioni.

Andiamo adesso ad analizzare la differenza tra con la precedente versione (2.5). Il web container inizializza le servlet solo se è stato configurato il deployment descriptor:

public class MyServlet extends HttpServlet {

public void doGet (HttpServletRequest req,

HttpServletResponse res) {

….

}

}

Deployment descriptor (web.xml)

<web-app>

<servlet>

<servlet-name>MyServlet</servlet-name>

<servlet-class>samples.MyServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>MyServlet</servlet-name>

<url-pattern>/MyApp</url-pattern>

</servlet-mapping>

</web-app>

Vediamo invece lo stesso risultato ottenuto con l’utilizzo delle API Servlet 3.0. MyServlet è dichiarata servlet tramite la notazione @Servlet, e viene inizializzata durante l’avvio del web container. In questo caso il deployment descriptor è opzionale.

@Servlet(urlMappings={“/MyApp”})

public class MyServlet {

@GET

public void handleGet(HttpServletRequest req,

HttpServletResponse res) {

….

}

}

@ServletFilter e @FilterMapping: Si può facilmente creare un servlet filter dichiarandolo tramite la notazione @ServletFilter del package javax.servlet.http.annotation.ServletFilter. Questa notazione include anche i metadati del filtro che si sta dichiarando. E’ obbligatorio avere anche la notazione @FilterMapping nella classe filter. Tutti gli altri attributi della @ServeltFilter sono opzionali, con relativi valori di default. La v3.0 della filter class possiamo vederla adesso come una classe POJO e non ci saranno interfacce Filter o costruttori public senza argomenti, richiesti per questa classe. Nel codice seguente vediamo l’utilizzo di una filter class con le Servlet v2.5 API:

public class MyFilter implements Filter {

public void doFilter(ServletRequest req,

ServletResponse res,

FilterChain chain)

throws IOException, ServletException {

……

}

}

Deployment descriptor (web.xml)

<web-app>

<filter>

<filter-name>My Filter</filter-name>

<filter-class>samples.MyFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>My Filter</filter-name>

<url-pattern>/foo</url-pattern>

</filter-mapping>

</web-app>

Un esempio di filter class usando le Servlet 3.0 è mostrato di seguito. Il container segna MyFilter come filter class tramite la notazione @ServletFilter. MyFilter intercetta tutte le richieste in arrivo con l’URL pattern /foo. Per la configurazione dei filtri il deployment descriptor è opzionale.

@ServletFilter

@FilterMapping(“/foo”)

public class MyFilter {

public void doFilter(HttpServletRequest req,

HttpServletResponse res) {

…..

}

}

@InitParam: questa notazione può essere usata per inizializzare i parametri da passare alla Servlet o alla filter class. Esso è un attributo delle notazioni @Servlet e @ServletFilter. Nel codice seguente possiamo vedere un esempio:

@Servlet(urlMappings={“/MyApp”}, initParams ={@InitParam(name=”lang”, value=”english”)})

public class MyServlet {

@GET

public void handleGet(HttpServletRequest req,

HttpServletResponse res) {

….

}

}

@ServletContextListener: La notazione javax.servlet.http.annotation.ServletContextListener dichiara la classe come servlet context istener. Il context listener riceve la notifica quando il web container crea o distrugge il ServletContext. Il context listener sarà una classe POJO e non dovrà implementare l’interfaccia ServletContextListener. Di seguito è mostrato un esempio di listener class scritto utilizzando le Servlet 2.5 API. Il container riconoscerà il listener class solo se sono configurati i dettagli nel deployment descriptor.

public class MyListener implements ServletContextListener {

public void contextInitialized(ServletContextEvent sce) {

}

…..

}

Deployment Descriptor (web.xml)

<web-app>

<listener>

<listener-class>samples.MyListener</listener-class>

</listener>

….

</web-app>

Utilizzando la versione 3.0, con il deployment descriptor opzionale, abbiamo:

@ServletContextListener

public class MyListener {

public void contextInitialized (ServletContextEvent sce) {

}

…..

}

Pluggability ed extensibility

Oggigiorno, i framework web com Struts, JSF e Spring sono molto utilizzati e stabiliscono le tecniche per la costruzione di applicazioni web-based. Integrare questi framework in un’applicazione web non è così facile; infatti essi richiedono di mettere insieme differenti pezzi tra di loro, e occorre quindi modificare il file descriptor per definire come tutti questi pezzi vanno attaccati. La maggior parte dei framework richiedono la configurazione del framework stesso come servlet class, (tipicamente un Controller Servlet), filter class, o listener class nel deployment descriptor dell’applicazione. La ragione principale di queste configurazioni è che le applicazioni web di oggi supportano solo un singolo deployment descriptor dove si definiscono tutte le informazioni di deployment. Quando la misura delle applicazioni incrementa, tuttavia la dipendenza sui framework esterni potrebbe aumentare, generando così deployment descriptor molto comlessi, e impossibili da gestire.

Per risolvere questi problemi, uno dei più significativi concetti introdtti dalle Servlet 3.0 è l’idea dei web fragments o modular web.xml. I web fragment sono una partizione logica di applicazioni web in elementi, come servlet, servlet-mapping, servlet-filter, filter-mapping, servlet-listener ed i loro elementi figli. Gli sviluppatori di framework possono personalizzare queste caratteristiche per definire i loro web fragments che risiedono nel framework, e gli sviluppatori possono utilizzarle in più framework semplicemente includendo le librerie nel classpath dell’applicazione, senza modificare i deployment descriptor esistenti. In breve, queste caratteristiche mirano ad evitare configurazioni quando si lavora con i framework o le librerie.

Il deployment descriptor è stato cambiato per includere un nuovo elemento chiamato <web-fragment>, che definisce i dettagli del web fragment. Se questi è impacchettato come un file .jar e i suoi metadati con le informazioni in forma di deployment descriptor, allora il web.xml deve essere incluso all’interno della directory META-INF del file .jar. Al momento del deployment, il container controlla il classpath delle applicazioni e scopre tutti i web fragment e i loro processi. Il flag metadata-complete esamina tutto durante l’avvio dell’applicazione. Vediamo un esempio di web fragment:

<web-fragment>

<servlet>

<servlet-name>myservlet</servlet-name>

<servlet-class>samples.MyServlet</servlet-class>

</servlet>

<listener>

<listener-class>samples.MyListener</listener-class>

</listener>

</web-fragment>

Per migliorare la pluggability, le Servlet 3.0 forniscono il supporto per l’aggiunta programmatica di servlet e filter class con l’aiuto di nuove APIs aggiunte al ServletContext. Queste nuove APIs, permettono di dichiarare le servlet, filter class e i loro URL mapping programmaticamente. Queste classi devono essere inizializzate durante l’avvio dell’applicazione oppure in runtime. La cosa più importante però, è che queste API possono essere chiamate solo dal metodo contextInitialized del ServletContext.

Un semplice esempio di codice è mostrato di seguito:

@ServletContextListener

public class MyListener {

public void contextInitialized (ServletContextEvent sce) {

ServletContext sc = sce.getServletContext();

//Declare servlet and servlet mapping

sc.addServlet(“myServlet”, “Sample servlet”, “samples.MyServlet”, null, -1);

sc.addServletMapping(“myServlet”, new String[] {“/urlpattern/*”});

//Declare filter and filter mapping

sc.addFilter(“myFilter”, “Sample Filter”, ” samples.MyFilter”, null);

sc.addFilterMapping(“myFilter”, new String[] {“/urlpattern/*”}, “myServlet”, DispatcherType.REQUEST, false);

}

}

Supporto asincrono

Molte volte le servlet rallentano la loro esecuzione aumentando i tempi di attesa, in particolar modo quando devono aspettare una risposta da un web service, una connessione JDBC, un messaggio JMS, e così via. Ci sono scenari ad esempio, in cui la servlet deve aspettare il completamento di tutti i processi, per generare una risposta, causando il blocco delle operazioni che, a loro volta, consumano threads o altre limitate risorse del container. Un altro effetto avverso, si ha in caso di una connnesione JDBC, quando ad esempio il database ha i threads in attesa per l’accesso. Anche questo tipo di scenario causa attese indefinite determinando una bassa qualità dei servizi per l’intero web container.

Per risolvere i difetti appena mensionati, le Servlet 3.0 introducono il supporto per sospendere e riprendere le richieste, e permettere alle servlet di servirle in modo asincrono non bloccante. Quando una richiesta viene sospesa, il thread la elabora e ritorna al container senza generare risposte e si mette in attesa per eseguire altri tasks. Il metodo resume nella request, riprende il processo della richiesta. Ogni volta che la risorsa invocata diventa disponibile, il thread lascia che l’evento riprende la richiesta sospesa e procede per generare la risposta. Di seguito sono indicate alcune delle capacità dell’asincronismo delle servlet:

  • - L’abilità di ricevere i dati da un client senza bloccarsi anche quando i dati sono in arrivo lentamente (non-blocking input).
  • - L’abilità di inviare i dati al client senza bloccarsi, anche se il client o il network sono lenti (non-blocking output).
  • – L’abilità di gestire le richieste che ritardano. Questo si verifica quando una risorsa remota/lenta deve essere ottenuta prima di servire una richiesta, oppure se l’accesso ad una specificata risorsa deve essere accelerato per gestire accessi simultanei.
  • - L’abilità a gestire le riposte in ritardo chiuse; ad esempio, la response deve essere tenuta aperta per permettere l’invio di ulteriori dati quando l’evento asincrono si verifica.
  • - L’abilità di notificare eventi bloccanti o non-bloccanti.

Un set di nuove APIs sono state aggiunte alla ServletRequest ed alla ServletResponse per sospendere, riprendere e interrogare sullo stato della request e della response. Gli eventi di notifica per riprende, sospendere, ed i metodi completi della request, sono disponibili agli sviluppatori tramite i metodi requestSuspended(), requestResumed() e requestCompleted(). La sequenza di eventi che prendono i dati da un web service remoto usando il metodo asincrono delle servlet è illustrato nella figura seguente.

Flow Servlet 3.0

Security

Questo argomento non è incluso nella prima versione delle Servlet 3.0. Tuttavia, la proposta consigliata prevede l’abilità di entrare (login) ed uscire (logout) programmaticamente. Le nuove APIs devono essere aggiunte all’HTTPServletRequest per abilitarle. Il metodo di login dell’ HTTPServletRequest permette all’applicazione o framework di forzare un’autenticazione container-mediated. Il metodo di logout dell’HTTPServletRequest e dell’HTTPSession invece permette ad un’applicazione di resettare lo stato di autenticazione della request.

Altri cambiamenti eterogenei

Di seguito sono elencati alcuni cambiamenti apportati alle esistenti APIs per facilitare e migliorare lo sviluppo.

HttpOnly Cookies: Le Servlet 3.0 consentono ai cookie di essere marcati come HTTPOnly cookies. Questa notazione non è esposta lato-client con script di codici, per prevenire attacchi tramite scripting. La maggior parte dei moderni browser supporta questa caratteristica. Di seguito i metodi aggiunti alla classe Cookie per il supporto a HTTPOnly cookies:

void setHttpOnly(boolean isHttpOnly)

boolean isHttpOnly()

API changes: I seguenti metodi si aggiungono alla ServletRequest per facilitare il recupero della ServletResponse, e la ServletContext, istanza associata con un oggetto request.

ServletResponse getServletResponse()

ServletContext getServletContext()

RoadMap

La prima release delle Servlet 3.0 è stata completata nel Giugno 2008 ed hanno come obiettivo il loro utilizzo nella piattaforma Java EE 6 o superiori. La versione finale quindi dovrebbe arrivare in concomitanza della Java EE 6. Comunque la prima parte delle specifiche sarà resa disponibile attraverso GlassFish, che è il riferimento per l’implementazione della Java EE 6. Ci si aspetta quindi che le Servlet 3.0 siano integrate proprio nella versione 3 di GlassFish.

Risorse:

You can leave a response, or trackback from your own site.

2 Responses to “Servlet 3.0”

  1. blogring.org scrive:

    Blogring per servlet…

    Blogring per servlet…

  2. diggita.it scrive:

    Servlet 3.0…

    Le Servlet java, una tra le tecnologie maggiormente utilizzate per la costruzione di applicazioni web-based con contenuti dinamici, arricchiscono le loro caratteristiche con un primo rilascio della versione Servlet 3.0 (JSR). Questa Java Specification …

Leave a Reply

Subscribe to RSS Feed Follow me on Twitter!