Esercitazione Servlet


1. Esercizio: Configurare ed avviare Tomcat

L'esecuzione di componenti servlet richiede un Container compatibile con questa specifica. Obiettivo di questa esercitazione è installare ed avviare il Container open source Tomcat.

Step 1: Installare ed avviare Tomcat. Tomcat può essere installato in vari modi sui diversi sistemi utilizzati dagli studenti. Il primo obiettivo è quindi quello di individuare sul sistema che utilizzate:

  • il comando per avviare tomcat, che potrebbe essere uno dei seguenti:

    tomcat start
    oppure:
    <tomcat-dir>/bin/startup.sh
  • individuare la cartella webapps in cui dovrete effettuare il deploy dei vostri servlet, che potrebbe essere:

    /usr/share/tomcat/webapps
    oppure:
    <tomcat-dir>/webapps
  • Assicurarvi di avere i diritti in scrittura sulla directory webapps

  • Individuare e controllare il contenuto dei log di tomcat che sono prodotti nella directory <tomcat-dir>/logs/

Per ulteriori informazioni far riferimento al sito ufficiale di Tomcat.

[Suggerimento] Suggerimento

La visualizzazione dei log è un'aspetto diagnostico fondamentale durante lo sviluppo ed esecuzione di un'applicazione web. Per una comoda consultazione suggeriamo l'utilizzo di un tool per la visualizzazione di documenti con aggiornamento in real time. Ad esempio, per linux:

tail -f <tomcat-dir>/log/catalina.log

2. Esercizio: Servlet "Hello World!"

Implementiamo una servlet che risponde al richiedente con un messaggio di saluto.

Step 1. Creare un nuovo progetto.

  • Creare un nuovo progetto di tipo Dynamic Web Project

    [Suggerimento] Suggerimento

    Se non è disponibile il Dynamic Web Project dovrete passare alla versione di Eclipse denominata Eclipse IDE for Java EE Developers.

  • Inserire il nome del progetto, ad esempio Esercitazione Servlet , e selezionare Finish

Step 2. Creare una nuova Servlet.

  • Cliccare con il tasto destro il progetto appena creato e selezionare New -> Servlet

  • Inserire il nome della servlet HelloWorld e cliccare Finish

Eclipse genera lo scheletro della servlet, con i metodi doGet, per le richieste HTTP GET, e doPost, per le richieste HTTP POST, da implementare.

[Importante] Importante

Il package javax.servlet non è incluso nella JDK, quindi Eclipse non ne dispone. Per risolvere i riferimenti in errore ai metodi della Servlet API, aggiungere quindi al buildpath del progetto l'implementazione presente tra le librerie di Tomcat in: <tomcat-dir>/lib/tomcat-servlet-3.0-api.jar

[Nota] Nota

Tutti i metodi di cui non facciamo l'override sono implementati per rispondere HTTP 501: Not implemented

Step 3: Configurazione del deployment della Servlet. Dobbiamo informare il container, Tomcat, della presenza della servlet e di come questa deve essere esposta come servizio. Eclipse genera la configurazione, a seconda della versione di Servlet gestita, aggiungendo un apposito deployment descriptor (web.xml) o annotando la classe come @WebServlet. In entrambi i casi viene configurato l'URL pattern al quale la servlet risponderà. Modificare il valore generato in modo che l'URL pattern sia "/hello"

Step 4: Implementazione della logica della Servlet. Procediamo quindi ad implementare la logica della servlet. Dal momento che viene richiesto di rispondere ad una richiesta get, implementiamo solo il metodo corrispondente doGet come segue:

  • Impostare a text/plain il Content-type del messaggio di risposta (setContentType())

  • Scrivere il messaggio di saluto nello stream di uscita (getWriter())

Step 5: Deploy dell'applicazione. Per il deploy in un container JEE, dobbiamo creare un archivio WAR in accordo alle specifiche standard. Per facilitarci questo compito usiamo le funzioni di esportazione di Eclipse:

  • Cliccare con il tasto destro sul progetto

  • Selezionare Export -> WAR file

  • Come cartella di destinazione impostare ~/isi/tomcat7/webapps

Verificare dal log di Tomcat che il deploy dell'applicazione sia eseguito senza errori.

Step 6: Interrogazione della Servlet. Eseguiamo una richiesta alla Servlet via browser. La URL da invocare è nella forma http://host:port/context/urlpattern dove:

  • host: è il nome o ip della macchina che ospita Tomcat, nel nostro caso localhost

  • port: la porta dove è esposto il servizio http di Tomcat. Per default la 8080

  • context: il nome del contesto dell'applicazione. Per default il nome del WAR.

  • urlpattern: il path della servlet specificato nell'annotazione @WebServlet o nel deployment descriptor

ad esempio: http://localhost:8080/EseServlet/hello. Verificare che sul browser sia visualizzata la scritta Hello World!.

Soluzione: Servlet HelloWorld

3. Esercizio: Debug e Logging di un'applicazione remota

Obiettivo di questo esercizio è di riuscire ad eseguire il debug e logging della servlet implementata nell'esercizio precedente.

Step 1: Stampare un testo nel log di Tomcat. Per le nostre applicazioni utilizziamo una modalità molto basilare di logging utilizzando il metodo log della ServletContext:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		this.getServletContext().log("Ricevuta una richiesta GET alla servlet HelloWorld!");
		....
}

Eseguire il deploy della servlet e verificare che, ad ogni richiesta, il log di Tomcat presenti il messaggio di log.

Step 2: Abilitare la porta di debug in Tomcat.

[Suggerimento] Suggerimento

Le installazioni in dipartimento sono già configurate con il debug abilitato.

Per le installazioni personali è necessario configurare Tomcat per abilitare la porta di debug (per convenzione sulla porta 8000).

Step 3: Configurare Eclipse.

  • Selezionare Run->Debug Configurations...

  • Cliccare su Remote Java Applications, poi su "New"

  • Impostare un titolo e selezionare il progetto da debuggare. Verificare che sia indicata la porta 8000 (o quella diversamente configurata).

  • Selezionare Apply e Debug

Adesso proviamo a mettere un breakpoint all'interno del codice, selezionando Run -> toggle breakpoint, e inviamo una nuova richiesta alla servlet sempre tramite browser. Eclipse abiliterà il layout in modalità debug e vedremo che il processamento è stato sospeso al breakpoint (evidenziando la linea di codice in verde) in attesa di un nostro comando. Durante la sospensione possiamo visualizzare tutti i valori assunti dalle classi in uso. I bottoni dell'interfaccia di debugging consentono di far avanzare l'elaborazione.

4. Esercizio: Proxy applicativo

Implementiamo una servlet che funga da proxy applicativo per le chiamate ai servizi di eBay. Il suo compito sarà quello di gestire la valorizzazione degli header HTTP richiesti dai servizi eBay.

Step 1. Recuperare il client Shopping API. Recuperiamo il client eBay sviluppato nell'esercitazione HTTP e verifichiamone il corretto funzionamento invocando il servizio. Fatta la verifica, modifichiamolo in modo che non inserisca più gli header proprietari di eBay (X-EBAY-*) e che invochi il proxy che andremo a sviluppare modificando la URL di connessione.

Step 2. Aggiungere la servlet. Aggiungiamo al progetto una nuova servlet ed implementiamo il metodo doPost in modo che emetta un log "Ricevuta richiesta POST". eseguiamo il deploy dell'applicazione e modifichiamo il client in modo che invii le richieste al proxy appena implementato, verificando che ad ogni invocazione venga stampata la stringa di testo nel log di Tomcat.

[Nota] Nota

Fino alla completa implementazione del proxy, il client potrà dare errore perché le risposte non sono quelle previste.

Step 3. Parsing e validazione della richiesta. Modifichiamo la logica del proxy. Come già fatto nell'esercitazione XML, validiamo e parsiamo il messaggio XML ricevuto in input (request.getInputStream()) ed arricchiamo il log del proxy stampando il nome del root element della richiesta. In caso di errori di validazione, rispondiamo al client con un errore HTTP 400 Bad Request (response.setStatus()). Verifichiamo il corretto funzionamento sia in caso di richiesta corretta che di richiesta malformata.

[Suggerimento] Suggerimento

Affichè lo Schema XML per la validazione sia disponibile all'applicazione deve essere incluso nel WAR copiandolo sotto la cartella WebContent del progetto. Per essere poi utilizzato, possiamo leggerlo con il comando

getServletContext.getRealPath("path della risorsa")

tenendo presente che il path è relativo alla location xxxx.war/WEB-INF/classes

[Suggerimento] Suggerimento

Per utilizzare una libreria non disponibile in Tomcat, come ad esempio la libreria Lai, dobbiamo includerla nel WAR. Per farlo è sufficiente andare in Project > Properties > Deployment Assembly ed aggiungerla alla lista delle risorse esportate.

Step 4. Indentificazione dell'operazione richiesta. Verificare che l'XML ricevuto sia una richiesta di getCategoryInfo controllando il nome del root element. In caso affermativo, arricchire ulteriormente il log stampando l'informazione acquisita, altrimenti rispondiamo al client con un errore HTTP 501 Not Implemented. Verificare il funzionamento sia in caso di richiesta corretta con una getCategoryInfo, sia in caso di richiesta non supportata richiedendo una geteBayTime.

Step 5. Route della richiesta. Nel caso di richiesta getCategoryInfo, creare una connessione verso lo ShoppingService impostando gli headers HTTP richiesti dal servizio esattamente come faceva originariamente il client e serializzare il DOM nel contenuto della richiesta. Stampare nel log la risposta ottenuta dal servizio e verificare che sia quella attesa.

Step 6. Forward della risposta. In caso di risposta di successo, eseguiamo il foward della risposta all'applicativo chiamante.

[Suggerimento] Suggerimento

Per copiare i dati della risposta dallo stream di Input della connessione allo stream di Output della servlet, è possibile utilizzare il metodo StreamUtils.copy(InputStream in, OutputStream out) fornito dalle Lai API v.1.0.2

In caso di errore, viene loggato il dettaglio dell'errore e restituito un HTTP 502 Bad Gateway. Verifichiamo con il client il corretto funzionamento dell'applicazione.

Soluzione: Client Shopping API

Soluzione: Servlet Proxy

[Nota] Nota

Per eseguire la soluzione occorre:

  • Modificare il codice del Servlet Proxy inserendo le proprie chiavi sviluppatore ebay

  • Aggiungere lo schema XSD nella cartella WebContent/WEB-INF/xsd nel progetto (da creare se non esiste)

  • Aggiungere al progetto la libreria Lai

  • Esportare in WAR e deployare in tomcat

  • Eseguire il client verificare che siano listate le categorie ebay

5. Esercizio: Router applicativo

Obiettivo dell'esercizio è quello di estendere le funzionalità del Proxy sviluppato nell'esercizio precedente affichè gestisca anche il servizio Trading API ed esegua il corretto routing delle richieste tra i due servizi.

Step 1. Implementare il client Trading API. Utilizzando come base il client dell'esercizio precedente, scriverne uno equivalente che effettui una richiesta di addItem al servizio Trading API come visto nell'esercitazione Web API Eseguire la richiesta e verificare, accedendo ad eBay, che l'oggetto sia effettivamente aggiunto.

Step 2. Implementare la logica di routing. Come fatto per le richieste getCategoryInfo, validare la richiesta rispetto all' XML Schema della richiesta, riconoscere l'operazione addItem e inoltrarla al servizio Trading API.

[Suggerimento] Suggerimento

Il validatore deve essere configurato per utilizzare gli XML Schema di entrambi i servizi. Per farlo basta utilizzare il metodo newSchema() fornendo in input l'array degli XML Schema:

Schema schema = schemaFactory.newSchema(new Source[] {
	new StreamSource(xsd1),
	new StreamSource(xsd2)
});

[Importante] Importante

Nel caso di schemi con lo stesso targetNamespace, come nel nostro, è necessario aggiungere uno schema che li includa come questo da inserire come ultimo nell'array degli schema.

Modificare il client Trading API affinchè invochi il router e verificare che le comunicazioni si completino correttamente. Verificare inoltre di aver mantenuto il supporto per il servizio Shopping eseguendo il client Shopping API dell'esercizio precedente.

Soluzione: Client Shopping API

Soluzione: Servlet Proxy

[Nota] Nota

Per eseguire la soluzione occorre:

  • Modificare il codice sia del Servlet Router che del Client inserendo le proprie chiavi sviluppatore ebay

  • Aggiungere i tre XSD nella cartella WebContent/WEB-INF/xsd nel progetto (da creare se non esiste)

  • Aggiungere al progetto la libreria Lai

  • Esportare in WAR e deployare in tomcat

  • Eseguire il client e verificare l'item sia stato messo in vendita (dal messaggio di risposta o dal portale di ebay)

Footer BGFooter BG
Tito Flagella - © 2007-2015