MokaByte 84 - Aprile 2004 
Portlet e Web Services
sottotitolo
di
Valerio Summo
Per distribuire efficientemente sul Web informazioni ed applicazioni, i portali necessitano di integrare al loro interno Web Services come fonti di dati e componenti applicativi remoti. Per aggregare e visualizzare dinamicamente contenuti diversi, un portale dovrà essere strutturato in maniera modulare e differenziata, tramite la tecnologia dei Portlets

Introduzione
I portali stanno diventando i principali mezzi di integrazione di informazioni e applicazioni disponibili nelle intranet e in Internet. Chiunque cerchi oggi di sviluppare un sito Web, lo fa usando una sorta di tecnologia tipica dei portali. Se vogliamo infatti scoprire il perché questa tecnologia sia ormai così popolare, dobbiamo per esempio osservare al come si è evoluti dai tempi dell' MS-DOS, in cui, per passare da un'applicazione all'altra, bisognava prima chiuderne una per poi fare partire la seconda, ai tempi di Windows, in cui si è in grado di associare ad ogni applicazione una sua finestra. Da questo ragionamento nasce il concetto di "aggregazione di applicazioni", che diventerà la funzione primaria di un portal server.
Analogamente, dal momento che i servizi Web stanno diventando il metodo predominante per rendere le informazioni e le applicazioni disponibili via Internet, molto presto i portali avranno la necessità di permettere l'integrazione dei Web Services come fonti di dati e come componenti applicativi remoti.
Per aggregare e visualizzare dinamicamente contenuti diversi, un portal server dovrà fornire una struttura che sia in grado di inserire i contenuti del portale in opportuni moduli, quali possono essere i Portlets.

Ciascun portlet sarà responsabile nel fornire specifiche informazioni e servizi, dovrà svolgere compiti di controllo di accesso al suo contenuto ( come per esempio da un sito Web, da un database o da un Web service ) e quindi trasformare e modellare il contenuto stesso cosicché questo possa essere efficientemente reso al client.
Tipicamente, i portlets girano sul portal server, elaborando i dati in ingresso e visualizzandone i risultati. I dati richiamati dal portlet sono solitamente locali, ma potrebbero anche essere remoti, facendo per esempio uso di Web services.
Un tipico esempio può essere quello di un News Portlet che permette all'utente di scegliere le categorie di notizie da seguire, aggiornandole in tempo reale direttamente dai Web Services corrispondenti.
Normalmente la presentazione delle notizie viene svolta dal portlet locale, mentre il Web Service fornisce soltanto le informazioni grezze nella forma di un documento XML, ma, come vedremo, una possibile via di sviluppo può prevedere anche l'utilizzo di Web services remoti nelle vesti di portlets remoti, in grado di contenere sia una logica applicativa che una logica di presentazione. In tal caso si parla di Remote Portlet Web Services.
Da un punto di vista lato-user, un portlet si presenta come una "piccola" finestra all'interno della pagina del portale, a cui è quindi associato uno specifico servizio o delle informazioni ( es. itinerari di viaggio, news, servizi meteo, informazioni sportive o pubblicitarie ). L'utente potrà personalizzare il contenuto, la struttura e la posizione del portlet secondo le preferenze di profilo settate dall'amministratore a cui il portlet appartiene.
Da un punto di vista applicativo lato-server, un portlet è invece un modulo disegnato per girare all'interno di un portlet container; in altre parole è una componente implementata come una JSP che definisce un contenuto statico e dinamico per un soggetto specifico (meteo, news, ecc.) nella pagina del portale.

 

Portlet e Web services
Ci sono due opzioni importanti per integrare i servizi Web all'interno di un portale che fa uso di portlets, il tradizionale data-oriented Web service ed il presentation-oriented and interactive Web service.

  • La prima opzione prevede che i portlet siano posti su un Portal Server in grado di accedere ai servizi Web per ottenere informazioni o attivarne le procedure previste. In pratica è una infrastruttura secondo la quale ad ogni portlet è associato un servizio presente su un Web service remoto



Figura 1
- Esempio di portale con portlets che richiamano Web Services

In questo caso si fa anche uso di cache locali al portal server per effettuare refresh più frequenti del contenuto dei portlets.
I data-oriented Web services ricevono richieste SOAP e forniscono come risposta dati codificati in documenti Xml, sempre secondo lo standard SOAP. Sarà poi dovere del service consumer elaborare i dati ricevuti nella maniera corretta ed offrire quindi il proprio servizio. Tali Web Services non si occupano però di presentare i risultati, ma solo di restituirli come risposta.
Lo svantaggio di questo genere di Web Services si presenta quando un portale necessita di integrare velocemente contenuti e applicazioni da sorgenti differenti e diverse tra loro.
E' quindi immediato comprendere come questa opzione venga usata in particolar modo in quei casi in cui è necessario avere dei buoni tempi di risposta del servizio.

  • La seconda opzione prevede invece che i portali possano pubblicare i portlet essendo questi in realtà dei servizi remoti.


Figura 2
- Esempio di portale che usa Remote Portlet Web Services

In questo caso i Web Services si presentano in realtà come dei Remote Portlet Web Services che, a differenza della prima opzione, contengono una logica sia di presentazione che di applicazione. Invece cioè di fornire solo dati grezzi o funzioni varie che richiedono poi un rendering da parte del portale, i portlet remoti sono in sostanza dei Web Services visuali, che si presentano semplicemente come delle applicazioni web aggregabili che possono quindi essere invocate attraverso una interfaccia standard di portlet proxy dalla parte del portale.
In altre parole gli user-facing Web services includono anche la presentazione come parte del servizio stesso. Essi non restituiscono dati che devono poi essere elaborati e girati in una presentazione dal consumatore, ma invece producono frammenti di markup facilmente aggregabili dal portale.

In ogni caso, ciascun portlet sarà responsabile di fornire specifiche informazioni e servizi, dovrà svolgere determinati compiti e quindi trasformare e modellare il contenuto stesso così che questo possa essere efficientemente reso al client nella forma a lui più adeguata.
Un buon portale dovrà comunque essere in grado di :

  • supportare portlets locali
  • includere portlets remoti
  • condividere portlets locali rendendoli disponibili ad altri portali come Remote Portlet Web Services

Portlets e Servlets
I portlets possono essere considerati come dei tipi speciali di servlets, con proprietà che permettono loro di inserirsi e girare facilmente sui portal server.
I portlets hanno altre varie caratteristiche, così come però anche alcune restrizioni. Non come le servlets, i portlets non possono mandare reindirizzamenti o errori direttamente al browser, inoltrare richieste o scrivere arbitrariamente markup al flusso di output.
Generalmente, i portlets sono amministrati più dinamicamente delle servlets.
Il portlet container si affida ad una architettura J2EE, implementata per esempio da IBM WebSphere Application Server.
In questo modo, gli sviluppatori di portlet traggono beneficio proprio perché:

  • le Portlet API riusano le ben note Servlet API, estendendole quando necessario
  • gli sviluppatori che conoscono le Servlet API possono immediatamente scrivere portlets
  • gli sviluppatori possono usare tools esistenti per sviluppare portlets e componenti JSP, facendo sempre uso di tecnologie J2EE

I portlets sono impacchettati in file WAR come applicazioni web J2EE e sono quindi presentati come servlets. Così come una servlet, un portlet viene definito alla applicazione server tramite un descrittore di applicazione web Xml (web.xml ) che definisce la classe portlet, la servlet mapping e i parametri di inizializzazione. A differenza del descrittore delle servlets, i portlets devono però anche fornire un descrittore portlet in grado di specificare la proprie capacità al portal server, quali parametri di configurazione di un particolare portlet o portletApplication o comunque informazioni generali appartenenti a tutti i portlets, come per esempio il tipo di markup che esso supporta.
Il portal server userà quindi queste informazioni per fornire i servizi per il portlet. Per esempio, se viene associato al portlet un supporto di aiuto o di edit mode nel descrittore Xml, allora il portal server fornirà le icone per permettere l'accesso alle pagine di help o di edit all'utente.

 

Architettura del portal server
Una delle possibili soluzioni per lo sviluppo di un portale web di servizi fa uso della piattaforma IBM WebSphere Portal Server, con l'ausilio della tecnologia delle Portlet Applications, secondo la quale, come già detto, ad ogni componente Portlet viene associato un servizio.
Per realizzare un sistema in grado di rispondere alle specifiche tipiche di un portale, è necessario disporre di una architettura completa e flessibile nella quale vengono definiti gli elementi base dell'infrastruttura così come le interfacce ed i protocolli che li pongono in relazione fra loro. Tale architettura dovrà coprire tutto il percorso dai dispositivi di Front End del client, attraverso portali e portlet locali o remoti, fino ai Web services. Deve inoltre comprendere i meccanismi ed i formati sia per introdurre il codice dei portlets localmente nei portali e sia per trovare e agganciarsi ai Web Services remoti.
La figura qui sotto mostra una possibile architettura di portale implementato con WebSphere:


Figura 3
- Architettura del Portal Server
(clicca per ingrandire l'immagine)

I clients accedono al portale attraverso il protocollo HTTP, sia direttamente che attraverso appositi Proxy o Gateway come quelli WAP o vocali. I linguaggi di mark-up usati da questi dispositivi possono essere molto diversi; ad esempio, i telefoni WAP usano normalmente WML, i telefoni iMode usano cHTML , i Browser vocali usano di solito VoiceXML, mentre il più noto Web Browser dei PC usa HTML.
Per soddisfare le esigenze di tutti questi dispositivi, i portali devono quindi supportare i vari linguaggi di mark-up.
Quando le pagine vengono aggregate per creare le videate del portale, quest' ultimo richiama tutti i portlets che appartengono a quella determinata pagina attraverso le Portlet API.

I portlets, così come avviene, sotto certi aspetti, con le servlets, vengono inseriti in modo analogo all'interno di portlet container che fanno sempre parte del portale.
I portlets sono dotati di API simili a quelle delle servlets, ma, a differenza di queste ultime che funzionano in un servlet container autonomo, in questo caso funzionano in un ambiente portale. Inoltre, mentre le servlets comunicano direttamente con i loro client, i portlets vengono richiamati indirettamente attraverso le applicazioni del portale.

Per funzionare correttamente nel contesto di un portale, i portlets devono produrre contenuti adatti ad essere aggregati in pagine più grandi e per fare ciò vuol dire che essi dovrebbero produrre porzioni di linguaggio mark-up conformi alle linee guida di riferimento così da assicurare contenuti sempre aggregabili tra loro.

Ritornando alla descrizione dell'architettura, quando un portale riceve una richiesta servlets, genera una portlet request ed invia, tramite il dispatcher, gli eventi associati a tutti i portlets implicati nell'operazione e successivamente ne attiva il funzionamento preparandosi a riceverne i risultati.
Un modello che si è dimostrato molto adatto alla programmazione del portlet è quello basato sui pattern Model-View-Controller ( MVC ).
Esso ripartisce le varie funzionalità del portlet in un Controller che riceve le richieste in entrata, attivando dei comandi che funzionano all'interno di un modello Model che incapsula i dati e la logica dell'applicazione ed infine richiama le viste View per la presentazione dei risultati.
I portlets hanno inoltre accesso alle funzioni relative ai portali ed ai dati attraverso le interfacce dei Portlet Service ( Portlet API ). Queste interfacce forniscono al portlet le funzioni che comprendono l'accesso alle informazioni dell'infrastruttura del portale, del profilo dell'utente, ai dati specifici dell'azione o allo stato del portale.
Oltre a queste funzioni ,specifiche dei portali, i portlets possono anche usare tutti i servizi J2EE che sono disponibili alle servlets per poter accedere ai dati di Back-End, alle applicazioni locali o persino ai servizi Internet. Per accedere ai database ed effettuare tutte le operazioni tipiche di un DataBase Management System vengono utilizzate le JDBC API.
Ogni portlet prevede inoltre un suo descrittore web ( portlet.xml ), utile per contenere informazioni sull'applicazione, sul suo identificativo, sul suo nome, opzioni di visualizzazioni, etc.
Per facilitarne l'impiego, i portlets possono essere raggruppati in Portlet Applications, inserite a loro volta in Portlet File Archives che contengono i file descrittori, le classi Java, i file jar e tutte le risorse implicate nel loro funzionamento.

 

Creare un proprio Portlet e Web service
Viene qui di seguito mostrato un semplice esempio di portlet che visualizza le ore ed i minuti restanti nel giorno ed è aggiornato ogni volta che viene effettuato un refresh. La classe RemainingTimePortlet estende l'interfaccia AbstractPortlet, utile per generare una nuova applicazione di portlet. Così come le servlets, anche i portlets presentano un metodo service che viene invocato dal portale quando viene richiesto a tutti gli effetti il contenuto del servizio.

package esempio;
import java.io.*;
import java.util.*;
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlets.*;

public class RemainingTimePortlet extends AbstractPortlet {

  public void service(PortletRequest request, PortletResponse response)
              throws PortletException, IOException {

    // Calcola le ore ed i minuti rimanenti.
    Calendar calendar = Calendar.getInstance();
    int hours = 24 - calendar.get(Calendar.HOUR_OF_DAY), minutes = 0;
    if (calendar.get(Calendar.MINUTE) > 0) {
      hours -= 1;
      minutes = 60 - calendar.get(Calendar.MINUTE);
    }
    PrintWriter writer = response.getWriter();
    writer.println("<p>Il giorno terminerà tra " + hours +
     " ore e " + minutes + "     minuti.</p>");
  }
}

Diamo ora uno sguardo all'esempio precedente, usando il modello MVC.

package esempio;
import java.io.*;
import java.util.*;
import com.ibm.wps.portlets.*;
import org.apache.jetspeed.portlet.*;
import org.apache.jetspeed.portlets.*;

// Classe Controller
public class RemainingTimeController extends AbstractPortletController {
  protected String jspHTML = "/WEB-INF/time/html/";

  // Metodo per inizializzare il portlet
  public void init(PortletConfig config)
    throws UnavailableException {
    super.init(config);
    // Carica la JSP dalla configurazione del Portlet
    jspHTML += config.getInitParameter("view.HTML");
  }

  // Metodo per rendere la vista del portlet
  public void doView(PortletRequest request, PortletResponse response)
    throws PortletException, IOException {
    // Calcola le ore ed i minuti rimanenti.
    Calendar calendar = Calendar.getInstance();
    int hours = 24 - calendar.get(Calendar.HOUR_OF_DAY), minutes = 0;
    if (calendar.get(Calendar.MINUTE) > 0) {
      hours -= 1;
      minutes = 60 - calendar.get(Calendar.MINUTE);
    }

    // Crea un bean per passare il tempo rimanente alla View JSP
    TimeBean timeBean = new TimeBean();
    timeBean.setHours(hours);
    timeBean.setMinutes(minutes);
    // Inserisci il bean nella request per la JSP da usare
    request.setAttribute("timeBean", timeBean);
    // Richiama la View JSP per visualizzarla
    getPortletConfig().getContext().include(jspHTML, request, response);
  }
}


package esempio;
import java.io.*;

// Bean usato per passare dati alla View JSP
public class TimeBean implements Serializable {
  // Ore rimanenti
  private int hours = 0;
  // Minuti rimanenti
  private int minutes = 0;
  // Setta le ore rimanenti

  public void setHours(int hours) {
    this.hours = hours;
  }
  
  // Prendi le rimanenti ore
  public int getHours() {
    return hours;
  }

   // Setta i minuti rimanenti
  public void setMinutes(int minutes) {
    this.minutes = minutes;
  }
  
   // Prendi I minuti rimanenti
  public int getMinutes() {
    return minutes;
  }

}

<!--------------------------------------------------------------------------->
<!- DisplayRemainingTime.jsp ------------------------------------------------>
<!- View JSP usata per visualizzare i dati nel Portlet del tempo rimanente -->
<!--------------------------------------------------------------------------->
<%@ page contentType="text/html" errorPage="" %>
<jsp:useBean id="timeBean"
  class="com.ibm.wps.sample.time.TimeBean"
  scope="request"/>
<p>Il giorno finirà tra <%= timeBean.getHours() %> ore e
<%= timeBean.getMinutes() %> minuti.</p>


La prima cosa da notare in questo esempio è che la prima classe non estende più la classe AbstractPortlet, ma la classe AbstractPortletController che fornisce una astrazione di un controllore per portlet. Questo oggetto definisce comunque gli stessi metodi di setup come la classe AbstractPortlet: init, login, logout e destroy.
Occorre notare che la classe non ridefinisce più direttamente il metodo service, ma invece ridefinisce un metodo associato con una particolare modalità portlet.
I portlets hanno infatti quattro modalità principali di operazione:

  • Portlet.Mode.VIEW
  • Portlet.Mode.EDIT
  • Portlet.Mode.HELP
  • Portlet.Mode.CONFIGURE

In pratica, l'operazione viene suggerita proprio dal nome della modalità corrispondente. Per ciascuna di queste modalità la classe AbstractPortletController ne fornisce un metodo: doView, doEdit, doHelp e doConfigure.

Ora diamo un'occhiata a ciò che succede quando il portlet è richiamato per rendere la sua modalità VIEW. Prima di tutto il tempo rimanente è calcolato a partire dall'ora corrente. Viene poi creato un TimeBean per mantenere le ore ed i minuti che dovranno poi essere visualizzati. Il TimeBean viene poi passato alla request corrente usando il metodo setAttribute dell'oggeto portlet request. Questo permetterà alla componente JSP VIEW di ottenere il bean dalla request usando il tag JSP useBean, come mostrato nel codice precedente. Infine, la componente JSP che produrrà il markup HTML per il portlet è chiamata per visualizzare i risultati, come mostrato qui di seguito:


Figura 4
- Portlet RemainingTimePortlet

Esempio di programmazione Web Service
Ci sono molte ragioni per le quali usare un Web service può rappresentare un obiettivo valido ed efficiente. Se per esempio occorre sviluppare un servizio che deve poi essere reso disponibile a tanti client in un sistema generico e ciascuno con i propri vincoli ambientali, allora l'approccio ai Web services può essere di aiuto, essendo questi in grado di fornire una piattaforma indipendente, necessaria per integrare uniformemente tutte le componenti del sistema.
Ritornando all'esempio descritto fin quì, verrà ora descritta una modalità per integrare l'applicazione portlet con un servizio Web. Verrà quindi creato un Web service in grado di fornire i minuti e le ore rimanenti nel giorno. Sebbene questo esempio risulterà essere abbastanza semplice, esso permetterà comunque di limitare la complessità del codice per porre invece l'attenzione sugli importanti fattori nel creare, distribuire ed integrare un servizio Web.
Questo servizio sarà poi semplicemente richiamato dalla applicazione portlet precedentemente sviluppata.
Il primo passo per la creazione del Web service è quello di determinare le operazioni pubbliche che dovranno poi essere rese disponibili.
Viene quindi creata un'interfaccia RemainingTimeService:

package esempio;
import java.util.*;

public interface RemainingTimeService {
  public TimeBean getRemainingTime(Date date);
  public Integer getRemainingHours(Date date);
  
public Integer getRemainingMinutes(Date date);
}

Ora c'è bisogno di creare un oggetto che fornisca il servizio vero e proprio che implementa questa interfaccia, come mostrato nella seguente classe Java:

package esempio;
import java.util.*;

//Implemenatazione del servizio RemainingTimeService
public class RemainingTimeServiceServerImpl implements RemainingTimeService {

  public TimeBean getRemainingTime(Date date) {
    Calendar calendar = Calendar.getInstance();
    int hours = 24 - calendar.get(Calendar.HOUR_OF_DAY), minutes = 0;
    if (calendar.get(Calendar.MINUTE) > 0) {
      hours -= 1;
      minutes = 60 - calendar.get(Calendar.MINUTE);
    }
    
    TimeBean timeBean = new TimeBean();
    timeBean.setHours(hours);
    timeBean.setMinutes(minutes);
    return timeBean;
  }

  public Integer getRemainingHours(Date date) {
    return new Integer(getRemainingTime(date).getHours());
  }

  public Integer getRemainingMinutes(Date date) {
    return new Integer(getRemainingTime(date).getMinutes());
  }
}

E' necessario a questo punto costruire un progetto Web service a partire proprio dal Java bean appena creato.
Si dovrà creare un file Enterprice Archive ( EAR) per effettuare il deployment del servizio Web sull'Application Server e disporre poi di tutti i file descrittori SOAP necessari appunto a descrivere il servizio tramite standard XML.
Ci sono molti toolkit che realizzano questo step mediante dei wizards, uno dei quali è per esempio il Web Services Development Toolkit (WSDK) per WebSphere.
Una volta che queste componenti sono state realizzate ed installata l'applicazione EAR sull'Application Server, il SOAP Server si prenderà cura di inoltrare tutte le richieste entranti. Infatti, per interagire con questo servizio, l'applicazione chiamante deve essere in grado di comunicare utilizzando messaggi SOAP. Sebbene questo può rappresentare una difficoltà in più, risulta essere però vantaggioso in quanto fornisce interfacce standard per una migliore interazione tra servizi, nascondendo i dettagli della loro implementazione.
Verrà ora descritto un oggetto client che implementa l'interfaccia RemainingTimeService e che utilizza le API SOAP per comunicare, sempre attraverso messaggi SOAP, con il server del servizio Web.
Si farà riferimento alle classi org.apache.soap ed in particolare a org.apache.soap.rpc, org.apache.soap.util.xml, org.apache.soap.encoding, org.apache.soap.soapenc.

package esempio;
import java.net.*;
import java.util.*;
import org.apache.soap.*;
import org.apache.soap.rpc.*;
import org.apache.soap.util.xml.*;
import org.apache.soap.encoding.*;
import org.apache.soap.encoding.soapenc.*;

public class RemainingTimeServiceClientImpl implements RemainingTimeService {

  // Registro per specificare gli user defined objects per la serializzazione
  private SOAPMappingRegistry smr = new SOAPMappingRegistry();

  // URN per indirizzare il servizio
  private String serviceURN = "urn:RemainingTimeService";
  private URL soapRouter = null;

  public RemainingTimeServiceClientImpl(String host)
         throws MalformedURLException {
    super();
    soapRouter =
new URL("http://" + host +
                 
"/RemainingTimeService/servlet/rpcrouter");

    mapSOAPClassTypes();
  }

  public TimeBean getRemainingTime(Date date) {
    Vector params = new Vector();
    params.addElement(new Parameter("date", Date.class, date, null));
    return (TimeBean)doCall("getRemainingTime", params);
  }

  public Integer getRemainingHours(Date date) {
    Vector params = new Vector();
    params.addElement(new Parameter("date", Date.class, date, null));
    return (Integer)doCall("getRemainingHours", params);
  }

  public Integer getRemainingMinutes(Date date) {
    Vector params = new Vector();
    params.addElement(new Parameter("date", Date.class, date, null));
    return (Integer)doCall("getRemainingMinutes", params);
  }

  // Crea la chiamata SOAP
  private Object doCall(String method, Vector params) {
    try {
      Call call = new Call();
      call.setSOAPMappingRegistry(smr);
      call.setTargetObjectURI(serviceURN);
      call.setMethodName(method);
      call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);
      call.setParams(params);

      // Recupera la risposta
      Response resp = call.invoke(soapRouter, "");
      if (resp.generatedFault()) {
        return null;
      }

      // Recupera il risultato
      Parameter result = resp.getReturnValue();
      return result == null ? null : result.getValue();
    }
    catch (SOAPException e) {
      return null;
    }
  }
  
   // Serializzazione
  private void mapSOAPClassTypes() {
    BeanSerializer beanSer = new BeanSerializer();
    smr.mapTypes(Constants.NS_URI_SOAP_ENC,new
    QName(serviceURN,TimeBean"),TimeBean.class,beanSer,beanSer);
  }
}

In questo esempio non si evince la natura dinamica dei Web services, infatti si presuppone che la locazione host del servizio deve essere nota a priori, tanto da essere passata come parametro per specificare il SOAP URL.
Dopo che l'oggetto lato-client è stato costruito, tutti i metodi di interfaccia sono pronti per essere invocati; questi richiamano quindi il metodo doCall per l'attuale comunicazione con il SOAP server.
Per esempio, nel metodo getRemainingTime, viene creato un vettore per mantenere traccia dei parametri ( in questo caso solo l'oggetto Date ).
Il vettore ed il nome del metodo vengono quindi passati al metodo doCall, all'interno del quale viene costruito un oggetto SOAP Call e settato con tutte le informazioni rilevanti necessarie per comunicare con il SOAP server, come per esempio il registro di serializzazione da usare, l'URN, il metodo con i parametri da invocare ed il SOAP encoding style. La chiamata è poi inizializzata con il SOAP router URL che era stato precedentemente costruito con l'host name fornito. Infine, viene fatto un controllo per eventuali eccezioni generate e restituito quindi il valore di risposta proveniente dal SOAP server.
Può essere buona pratica aggiungere a tutto ciò un object-oriented Factory Design Pattern per fornire un'astrazione del servizio. Per esempio, seguendo questa strada, si potrebbe pensare di sviluppare una semplice classe così fatta:

package esempio;
import java.net.*;

public class RemainingTimeServiceFactory {
  
public static RemainingTimeService getInstance(String hostname)
                 throws MalformedURLException {
    return new RemainingTimeServiceClientImpl(hostname);
  }
}

 

Portlet e Web Service
Modifichiamo ora il portlet richiamando il servizio appena descritto.
La modifica del codice del portlet per poter richiamare il Web service è molto semplice; è sufficiente infatti modificare il solo metodo doView della classe RemainingTimeController facendo uso delle opportune API, come mostrato nel seguente frammento di codice:

public void doView(PortletRequest request, PortletResponse response)
            throws PortletException, IOException {

  RemainingTimeService service = null;

  try {
    service = RemainingTimeServiceFactory.getInstance("localhost");
  }
  catch (Exception e) {
    throw new PortletException(e.getMessage());
  }

  // Inserisco il bean nella request per la JSP da usare
  request.setAttribute("timeBean", service.getRemainingTime(new Date()));

  // Richiama la View JSP per visualizzarla
  getPortletConfig().getContext().include(jspHTML, request, response);
}

 

Conclusioni
In questo documento si è cercato di dare una breve descrizione della nuova tecnologia dei portlets all'interno dello sviluppo di portali Web e di come essi possano facilmente interagire con i Web services, descrivendo alla fine anche un esempio completamente funzionale, seppur limitato.
E' stato possibile notare come l'architettura delle portlet applications sia in fondo una estensione dell'architettura Java Servlet. Ne deriva, quindi, che molti degli aspetti dello sviluppo dei portlets sono comuni a quelli delle tipiche applicazioni Web. Tuttavia, occorre dire che le funzioni uniche di un portale aggiungono complessità al modello di applicazione, quali la presenza di più portlets all'interno della stessa pagina Web, il controllo di flusso del portlet nella pagina Web, le restrizioni di visualizzazione nella interfaccia utente, la comunicazione inter-portlet.
Una considerazione particolare deve essere però data al disegno di una portlet application in generale, sia per poter usufruire delle caratteristiche tipiche di un portale, sia per evitare di diventare preda della sua complessità.

 

Bibliografia e risorse
[1] S.Hesmer, P.Fischer, T.Buckner, I.Schuster, "Portlet Development Guide: Second Edition", IBM, 2003
[2] Doug Philips, "Developing and Debugging Portlets Using the IBM Portal Toolkit Plug-in for WebSphere Studio Application Developer", IBM Developer Technical Support Center, 2002
[3] Daniel Kikuchi, "Portlet Development for WebSphere Portal Server 1.2 Tutorial, Part1", IBM WebSphere WebSpeed Team, 2001
[4] David B. Lection, "WebSphere Portal Server programming: Portlet application programming, part1", IBM, 2001
[5] David B. Lection, "WebSphere Portal Server programming: Portlet application programming, part2", IBM, 2001


Valerio Summo, laureato in Ingegneria Informatica, attualmente impegnato in un progetto di ricerca industriale e sviluppo precompetitivo riguardo alla realizzazione di sistemi innovativi basati sulle tecnologie della conoscenza, con utilizzo di tecniche di Data e Web Mining. Sviluppatore in Java, orientato ad applicazioni web J2EE, portali e Web services.

MokaByte® è un marchio registrato da MokaByte s.r.l. 
Java®, Jini® e tutti i nomi derivati sono marchi registrati da Sun Microsystems.
Tutti i diritti riservati. E' vietata la riproduzione anche parziale.
Per comunicazioni inviare una mail a info@mokabyte.it