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 | |
---|---|
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
|
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 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 selezionareFinish
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 cliccareFinish
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 | |
---|---|
Il package |
Nota | |
---|---|
Tutti i metodi di cui non facciamo l'override sono implementati per
rispondere |
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 casolocalhost
port
: la porta dove è esposto il servizio http di Tomcat. Per default la8080
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
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 | |
---|---|
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
eDebug
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.
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 | |
---|---|
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 | |
---|---|
Affichè lo Schema XML per la validazione sia disponibile all'applicazione
deve essere incluso nel WAR copiandolo sotto la cartella getServletContext.getRealPath("path della risorsa")
tenendo presente che il path è relativo alla location |
Suggerimento | |
---|---|
Per utilizzare una libreria non disponibile in Tomcat,
come ad esempio la libreria Lai,
dobbiamo includerla nel WAR. Per farlo è sufficiente andare in
|
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 | |
---|---|
Per copiare i dati della risposta dallo stream di Input della connessione allo stream di
Output della servlet, è possibile utilizzare il metodo |
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 | |
---|---|
Per eseguire la soluzione occorre:
|
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 | |
---|---|
Il validatore deve essere configurato per utilizzare gli XML
Schema di entrambi i servizi. Per farlo basta utilizzare il metodo
Schema schema = schemaFactory.newSchema(new Source[] { new StreamSource(xsd1), new StreamSource(xsd2) });
|
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 | |
---|---|
Per eseguire la soluzione occorre:
|