Nel precedente articolo abbiamo introdotto l‘argomento dei portali in un‘ottica generale, vedendone le caratteristiche e le possibilità d‘uso. Iniziamo con questo articolo ad approfondire l‘argomento, facendo un‘ampia carrellata di tutto ciò che il mondo Java mette a disposizione per la realizzazione di portali web.
Introduzione
Nel precedente articolo abbiamo introdotto l’argomento dei portali da un punto di vista generale cercando di inquadrare l’argomento e dando alcuni spunti per una migliore comprensione di ciò che è un portale e degli scopi a cui può assolvere. La discussione era stata affrontata senza entrare nel dettaglio di tecnologie specifiche, proprio per dare un senso di generalità a quanto discusso.
Con il presente articolo iniziamo invece ad entrare nel mondo Java ed a esaminare ciò che la piattaforma offre per la realizzazione di portali. In questo ambito vi è stata una grande evoluzione negli ultimi anni e da una situazione di immaturità e incompletezza di specifiche e strumenti si è arrivati oggi a una situazione in cui si può realmente dire di avere a disposizione standard e tecnologie che consentono di realizzare portali web in modo efficiente e completo. Il tutto ha le sue fondamenta nelle Java Portlet che è l’argomento che ci accingiamo a discutere.
Le Java Portlet
La Java Portlet Specification 1.0 definita nell’ambito della JSR 168 fu rilasciata nell’ottobre 2003. Questa è stata la prima specifica che definiva molti aspetti sulle portlet ed ebbe una notevole importanza perche’ diede una prima standardizzazione a un ambito che fino ad allora era andato sviluppandosi senza seguire una linea comune. La specifica, sebbene costituisse un primo passo verso la standardizzazione, non copriva molti importanti aspetti. A febbraio 2006 fu costituito il JSR 286 Expert Group al fine di arrivare alla Java Portlet Specification 2.0 rilasciata nel giugno 2008 che costituisce lo standard attuale per le portlet, le cosiddette Portlet 2.0.
Torneremo sugli aspetti della specifica, ma prima di ciò è lecito farsi una domanda fondamentale: cosa è una portlet? Possono essere date definizioni diverse più o meno rigorose da un punto di vista tecnico ma quella forse più semplice e di immediata comprensione è la seguente: una portlet è una applicazione web che viene eseguita in una porzione di una pagina web.
Il paradigma di funzionamento di una portlet è analogo a quello di una servlet visto che parliamo sempre di un modello richiesta/risposta. Chi ha familiarità con le servlet, e con le JSP, sa però che questi componenti sono responsabili del rendering di una intera pagina web.
Con le portlet il discorso cambia poiche’ una singola portlet con le sue funzionalità è responsabile solo di una porzione dell’intera pagina web. Possiamo quindi pensare alle portlet come a tanti mattoncini che messi insieme vanno a costituire la nostra pagina web.
Figura 1 – Le portlet in una pagina web.
L’ambiente di funzionamento
Affinche’ le portlet possano essere eseguite, è necessario un ambiente dedicato, un container, il portlet container, che è il corrispondente di ciò che è il servlet container per le servlet. È il portlet container che assolve ai compiti infrastrutturali necessari al corretto funzionamento di questi elementi di interfaccia detti portlet. Da un punto di vista del deployment, una portlet non è altro che una web application, un .WAR per intenderci, molto simile a una normale web application ma ovviamente con alcune specificità.
Si è parlato di portlet come componenti di interfaccia non perche’ una portlet non possa contenere nel suo codice anche logica di business. Ma per i principi di cui si è parlato molte volte nelle pagine di Mokabyte sappiamo come sia preferibile strutturare le applicazioni in layer ciascuno con il suo compito specifico. Non ci soffermeremo ancora su questi concetti ma in tal senso si fa riferimento alla portlet come ad un componente di front-end.
Un front-end componibile
Senza addentrarci al momento nei dettagli di portlet e portlet container, già la definizione data lascia intravvedere le grandi potenzialità delle portlet rispetto alle normali applicazioni web.
Con le portlet è possibile comporre in un’unica pagina funzionalità distinte che operano su sorgenti dati diverse. Ciò consente di aggregare, in una interfaccia omogenea, dati e applicazioni eterogenee senza costringere l’utente a viaggiare tra applicativi diversi per eseguire le funzionalità di cui ha bisogno.
Questo aspetto è di fondamentale importanza in quanto potremmo pensare alle portlet come a dei servizi componibili di front-end e quindi potremmo dire che le portlet sono per il front-end quello che i servizi di business sono per il back-end. Realizzando portlet realmente riusabili, quindi standard e dalle funzionalità ben specifiche, possiamo fare con l’interfaccia web quello che facciamo quando componiamo i servizi per costruire funzionalità di back-end.
Questo aspetto a mio avviso rende veramente attraenti le portlet in ottica di architetture a servizi e le rende preferibili a una semplice applicazione web.
Quando usare le portlet
Si potrebbe obiettare che se ho la necessità di risolvere un singolo problema funzionale in un ambito verticale ben specifico non ho bisogno delle portlet in quanto non devo costruire piccoli frammenti di interfaccia web da comporre, ma una singola applicazione web monolitica dai compiti ben definiti. Anche se in letteratura alcuni autori vedono l’uso delle portlet solo quando si intende proporre all’utente una vista di una applicazione aggregandola con altre ciò a mio parere non è esatto.
Questa logica a mio avviso è sicuramente valida quando si ha a che fare con applicazioni esistenti. Nel senso che se ho una applicazione esistente molto complessa e voglio rendere disponibili su un portale un sottoinsieme delle sue funzionalità allora posso esporre la logica di business con dei servizi web, costruire portlet per il front-end ed il gioco è fatto. Ma quando si affronta il problema di scegliere la soluzione per sviluppare una applicazione web da zero io suggerisco di valutare l’utilizzo di un portal container e delle portlet anche per applicazioni che inizialmente si propongono non in ottica portale.
Questo per diversi aspetti. Innanzitutto oggi la specifica delle portlet è molto più matura e consente di gestire con le portlet praticamente tutto quello che comunemente è richiesto nelle applicazioni web. Inoltre oggi esistono prodotti che sono veri e propri framework di sviluppo basati sulle stesse tecnologie usate per le applicazioni web ma con molte più funzionalità già pronte per l’uso. Molte delle cose che dovrei sviluppare nella mia applicazione le ho già a disposizione; per citarne a titolo di esempio solo alcune: la gestione di utenti, ruoli e gruppi, la gestione di menù applicativi, la gestione del layout delle pagine e cosi via. Oltre a ciò, sviluppare l’applicazione in ottica portlet rende la mia applicazione più modulare e già pronta per una pubblicazione futura in ottica portale.
Torneremo su questi aspetti ma il concetto, maturato con l’esperienza sul campo, è che a differenza di quanto accadeva solo pochi anni fa ora gli standard e gli strumenti a disposizione nell’ambito dello sviluppo di portlet rendono questo strumento attraente e da valutare anche quando non si è strettamente nella necessità di realizzare un portale.
Caratteristiche fondamentali delle portlet
Come le servlet anche le portlet sono componenti che hanno un ciclo di vita gestito da un container. Il ciclo di vita di una portlet è leggermente più complesso di quello di una servlet in particolare per ciò che riguarda la gestione delle richieste. Sappiamo che in una servlet il metodo service() gestisce la richiesta e produce una risposta generando l’intera pagina web. Come detto invece una portlet è responsabile solo di una porzione di pagina web e quindi il ciclo di gestione della richiesta è un po’ più articolato. Si distinguono diverse fasi nella gestione della richiesta.
Render Phase
È la fase che va in esecuzione ogni volta che la portlet si visualizza nella pagina web.
Action Phase
È la fase in cui la portlet esegue delle azioni che provocano una cambiamento nel suo stato che poi si riflette nella fase di render.
È la fase in cui la portlet gestisce gli eventi per i quali è in ascolto.
Resource Serving Phase
È la fase in cui una portlet serve all’utente una particolare risorsa, quale ad esempio un file.
Oltre ad avere diverse fasi nella gestione di una richiesta, una portlet ha anche un comportamento diverso a seconda del tipo di richiesta che viene effettuata. Se viene richiesta un’azione a una portlet verrà eseguita la action phase seguita dalla render phase, mentre se viene richiesto solo di visualizzare il proprio contenuto, la portlet attraverserà solo la fase di render. Questo è comprensibile pensando a quanto detto fino ad ora: una pagina web è composta da diverse portlet ognuna responsabile di un frammento di pagina. L’utente effettuerà una azione sull’interfaccia a cui risponderà una sola delle portlet che costituiscono l’intera pagina. Tutte le altre semplicemente si renderizzeranno a fronte di questa richiesta. Per cui la portlet sulla quale è stata fatta l’azione attraverserà le fasi di action e di render, le altre solo quella di render.
Nella Figura 2, tratta da “Portlets in Action”[2], è raffigurato quanto detto, ossia la gestione di una render request e di un action request da parte di una portlet.
Figura 2 – Gestione delle richieste di tipo action e render.
Ovviamente la gestione delle richieste e del ciclo di vita delle portlet è possibile grazie ai servizi offerti dal portlet container che riceve le richieste dal portal server e attiva in modo opportuno i metodi delle portlet interessate.
Interfacce
Come per gli altri componenti tipo le servlet, affinche’ una classe Java assuma il comportamento di una portlet deve implementare delle ben definite interfacce. Ogni portlet deve implementare l’interfaccia javax.portlet.Portlet e può opzionalmente implementare le interfacce javax.portlet.EventPortlet e javax.portlet.ResourceServingPortlet.
L’interfaccia javax.portlet.Portlet definisce i metodi principali del ciclo di vita:
init()
È il metodo invocato dal container dopo che la portlet viene caricata e istanziata e consente di effettuare operazioni di inizializzazione una tantum in perfetta analogia a quanto vale per le servlet
render()
È il metodo responsabile della generazione del contenuto della porzione di pagina gestita dalla portlet. Va in esecuzione a seguito di una richiesta di tipo render.
processAction()
È il metodo che va in esecuzione a seguito di una azione dell’utente sull’interfaccia, quindi a seguito di una richiesta di tipo action.
destroy()
È il metodo invocato dal container quando la portlet viene rimossa dalla memoria è può essere usato per operazioni di deallocazione di risorse, anche questo in perfetta analogia con quanto accade per le servlet
Modi di esecuzione
Oltre a diversi tipi di richiesta da gestire le portlet hanno anche diversi modi di esecuzione ciascuno con il suo scopo ben preciso. I modi di esecuzione sono i seguenti:
VIEW
È la modalità, che corrisponde al metodo doView(), mediante cui la portlet visualizza il proprio stato, quindi la modalità di visualizzazione principale ed obbligatoria della portlet in termini di visualizzazione delle proprie funzionalità per l’utente.
HELP
È la modalità, che corrisponde al metodo doHelp(), mediante cui la portlet genera contenuto che descrive il funzionamento della portlet.
EDIT
È la modalità, che corrisponde al metodo doEdit(),mediante cui la portlet genera contenuto che consente di personalizzare il contenuto e il comportamento della portlet stessa.
Ciclo di vita, tipi di richiesta e modalità di funzionamento sono alcuni dei concetti di base sulle portlet. Non ci addentriamo oltre nei minimi dettagli della specifica per evitare una inutile ripetizione di quanto è possibile leggere molto diffusamente nei riferimenti bibliografici.
Ciò che in questo momento è opportuno sottolineare è che le portlet, come le servlet, sono componenti con un preciso ciclo di vita gestito da un container che funge da mediatore tra le azioni eseguite dall’utente sull’interfaccia web e le portlet stesse. Il paradigma di funzionamento è simile poiche’ è sempre basato su una logica del tipo richiesta/risposta, ma mentre nel caso delle servlet un solo componente gestisce la richiesta ed è responsabile della risposta e dell’intera pagina web, in questo caso la richiesta è gestita da diversi componenti ognuno responsabile della sua porzione di pagina.
Nuove caratteristiche delle Portlet 2.0
Abbiamo già accennato al fatto che nella specifica 2.0 delle portlet sono state inserite alcune importantissime novità che coprono alcune aree che la vecchia specifica non affrontava.
Di seguito vengono elencate alcune di queste non allo scopo di fornire una spiegazione nei minimi particolari della specifica ma piuttosto di evidenziare le nuove possibilità a disposizione del programmatore, scaturite dalla standardizzazione di nuovi aspetti riguardanti le portlet.
Inter portlet communication
Uno dei principali problemi della specifica 1.0 era la mancanza di un meccanismo standard che consentisse alle portlet di comunicare l’una con l’altra. L’unico meccanismo disponibile era quello di utilizzare la PortletSession, l’oggetto in comune tra le diverse portlet di una medesima applicazione. Lo svantaggio nell’utilizzo della PortletSession è essenzialmente che ciò richiede che le portlet che devono comunicare devono far parte della stessa applicazione web. Ciò rende quindi impossibile realizzare portlet realmente riusabili e che possano comunicare con portlet sviluppate da altri. Nella specifica 2.0 si è colmata questa grossa lacuna grazie all’introduzione di due meccanismi fondamentali: i parametri pubblici delle render request e gli eventi.
I render parameter sono i parametri ricevuti dalla portlet nelle richieste di tipo render. I public render parameter introdotti nelle Portlet 2.0 non sono altro che una estensione dello scope dei parametri di render alle altre portlet anche non appartenenti alla stessa web application.
La dichiarazione che un parametro di render ha uno scope pubblico la si fa semplicemente configurando opportunamente il portlet.xml, il file che definisce le proprietà della portlet. I public render parameter costituiscono il metodo più semplice per ottenere la comunicazione inter-portlet in quanto non implicano modifiche al codice ma solo alla configurazione. Hanno il vantaggio della semplicità e consentono a portlet appartenenti a web application diverse di interoperare. Hanno un grosso limite nel fatto che affinche’ ciò sia possibile le portlet devono appartenere alla stessa pagina visto che si tratta sempre di parametri di request.
L’altro metodo definito per la comunicazione tra le portlet è quello basato sugli eventi. In base a questo modello, avremo una portlet che genera un evento e una o più portlet configurate per stare in ascolto sull’evento stesso. Il modello non è ovviamente una novità, ma applicato alle portlet ne ampia notevolmente le possibilità di applicazione. È sempre nel portlet-xml che una portlet dichiara gli eventi che è in grado di generare e gli eventi per i quali si pone in ascolto. La gestione degli eventi è possibile se la portlet implementa l’interfaccia javax.portlet.EventPortlet a cui si accennava prima. Il modello a eventi consente di creare vere e proprie catene di eventi tra portlet e apre quindi scenari molto più vasti alle possibilità dell’interfaccia web di un portale. È chiaro che, a differenza del metodo dei public render parameter, che è frutto esclusivamente di una configurazione, il modello a eventi richiede lo sviluppo di codice ad hoc e quindi va utilizzato solo in casi più complessi. Al di là del meccanismo utilizzato, che renderemo più chiaro nei prossimi articoli con qualche semplice esempio, ciò che è importante sottolineare a questo livello di approfondimento è che ora la specifica definisce meccanismi standard per la comunicazione inter-portlet a cui tutti gli implementatori devono uniformarsi il che rende possibile la realizzazione di portlet interoperanti sviluppate da soggetti diversi.
Portlet Filter
In perfetta analogia ai servlet filter, la specifica definisce i Portlet Filter, ovvero dei componenti pluggabili in fase di configurazione, nei quali è possibile inserire logica riusabile di elaborazione di richieste e risposte. Il concetto di filtro è ben noto nel mondo delle web application Java, quindi non si ritiene opportuno specificarlo oltre. È molto importante evidenziare che la possibilità di realizzare filtri esiste ora anche nel mondo delle portlet. Ciò consente di estrarre dal codice delle stesse tutte quelle funzionalità tipiche dei filtri di pre-processing delle richieste o di post-processing delle risposte. Ovviamente dal momento che nel caso delle portlet i tipi di richieste sono diversi, esistono anche diversi tipi di filtri ognuno specializzato nel pre-processing e post-processing di un particolare tipo di richiesta/risposta e quindi si parla di interfacce ActionFilter, RenderFilter, EventFilter e Resource Filter.
Risorse
Nelle portlet 1.0 non era possibile servire risorse al client direttamente dalla portlet ma era necessario ricorrere a una servlet dedicata allo scopo. Questa lacuna è stata colmata in quanto le portlet 2.0 possono invece servire sia risorse referenziate con URL statici facenti parte della stessa web application sia risorse dinamiche referenziate con URL costruiti dinamicamente. Allo scopo è stato definito il metodo serveResource() dell’interfaccia ResourceServingPortlet già menzionata. In tal caso il portlet container non serve altro contenuto nella risposta se non quello generato dal metodo in questione ma agisce solamente come un proxy nei confronti del client.
Queste nuove caratteristiche delle portlet 2.0 insieme alle altre non citate ma consultabili nella final release della specifica [3] rendono le portlet uno strumento più efficiente e valido per la realizzazione di portali web e di applicazioni web in genere. Nei prossimi articoli inizieremo a entrare un po’ più a fondo in qualche esempio pratico di portlet utile ad una migliore comprensione dei concetti esposti.
Conclusioni
Nel presente articolo abbiamo introdotto il concetto di portlet illustrandone ad altissimo livello le principali caratteristiche e soprattutto le novità contenute nella specifica 2.0. La filosofia di questa serie non è quella di costituire un manuale di riferimento per lo sviluppo di portlet; un tale obiettivo non avrebbe alcun senso e sarebbe reso inutile dalla numerosa e ottima letteratura disponibile sull’argomento. Piuttosto lo scopo è quello di fornire le informazioni di base e gli spunti di riflessione necessari alla comprensione di questo importante argomento. Nel prosieguo della serie, esaminando qualche semplice esempio, molti dei concetti esposti si chiariranno e prenderanno significato nel quadro complessivo della realizzazione di un portale web.
Riferimenti
[1] Richard Sezov jr, “Liferay in Action”, Manning Pubblications, MEAP Edition, 2010
[2] Ashish Sarin, “Portlets in Action”, Manning Pubblications, MEAP Edition, 2010
[3] Stefan Hepper, “JSR000286 Portlet Specification 2.0 Final Release”, 25 gennaio 2008