Nell‘ambito del lungo cammino fin qui intrapreso, abbiamo mostrato cosa sia necessario fare per “agganciare” i vari layer di business logic a quello di presentation fatto in JSF. In questa puntata e nella prossima proseguiamo il ragionamento andando a vedere come sia possibile integrare tecnologie più moderne basate sul modello AJAX al fine di migliorare il livello di interattività utente-sistema.
Introduzione
Come più e più volte detto, lo spirito che ha animato tutte le puntate di questa serie non ha come obiettivo quello di entrare nello specifico di ogni tecnologia proposta, ma piuttosto di mostrare come usare un certo modello architetturale e tecnologico al fine di illustrare pregi e difetti di una scelta rispetto a un’altra.
In questo senso, Beelog, l’applicazione che abbiamo fatto finta di realizzare in tutti questi mesi dovrebbe essere vista come una specie di laboratorio o reference implementation delle soluzioni più indicate a risolvere i vari problemi che si presentano di volte in volta.
Abbiamo raggiunto un primo punto di chiusura (in gergo una milestone) ossia, dopo tanto parlare, finalmente abbiamo capito (o almeno l’intenzione era quella) come collegare i vari layer di logica a una interfaccia web moderna. La scelta fatta in quella occasione fu di mostrare come progettare e realizzare l’interfaccia web con Java Server Faces, che in questo momento è la tecnologia di punta proposta da Sun per lo sviluppo del layer web.
Come però spesso è accaduto in altri ambiti, le tecnologie e i framework nati dalla comunità open o da produttori esterni hanno influenzato il mercato e pilotato trend e mode, tanto che poi Sun stessa ha deciso di inglobare nelle versioni più recenti delle specifiche tali soluzioni o di proporne di analoghe. È il caso di Spring (- > EJB3) o di Hibernate (-> JPA).
Tecnologie per applicazioni “ricche”
Nel mondo della programmazione web (tradizionalmente uno dei più febbrili e dinamici) la novità più importante che ha scosso la rigidità del modello sia dal punto di vista della implementazione che del risultato finale relativo alla interazione utente-sistema è stata portata dalla nascita di AJAX e delle varie tecnologie annesse.
AJAX è una tecnologia tanto semplice quanto efficacie che permette di migliorare l’usabilità del sistema grazie a un uso sapiente e trasparente di invocazioni asincrone fra il browser e il sistema. Con AJAX quindi diminuiscono drasticamente i tempi di attesa per poter visualizzare un cambiamento di stato della pagina tanto che di fatto l’applicazione finisce per assomigliare moltissimo a una applicazione stile client-server sviluppata in VB o Delphi.
Inizialmente sviluppare applicazioni AJAX era un compito per pochi smanettoni spesso snobbati o addirittura messi all’indice dai “puri” della programmazione OOP; con il tempo, più o meno tutti hanno dovuto ammettere che il risultato finale era talmente efficacie e i tempi di sviluppo talmente ridotti, che si poteva chiudere un occhio se non si disponeva di tutti quei vincoli facenti parte dei capisaldi della programmazione OOP.
A parte le considerazioni sui costi/benefici che hanno ridotto a più miti consigli i puristi della programmazione, è comunque innegabile che programmare direttamente in JS semplice è scomodo e per certi versi rischioso (non si hanno le comodità di un linguaggio fortemente tipato come Java e la rigorosità di un compilatore severo come il javac).
Per questo motivo l’evoluzione tecnologica ha proseguito ulteriormente nella ricerca di nuove soluzioni partendo comunque dall’idea che avere un pezzo dell’applicazione dentro il browser (ovvero direttamente sul client) è ormai un requisito imprescindibile. Per questo le nuove soluzioni sono tutte volte nella direzione di offrire strumenti e tecniche di programmazione basate sul concetto di spostare sul client un pezzo dell’applicazione (come in JS) e di utilizzare una comunicazione asincrona fra server e browser (come in AJAX). Fattore comune a molte di queste tecnologie è la volontà di nascondere il più possibile i dettagli legati al JS magari utilizzando direttamente Java o altri linguaggi di altro livello.
In tale scenario le tecnologie che possiamo brevemente elencare sono le seguenti:
Librerie JS come JQuery EXT-JS, DOJO
Questi strumenti stanno avendo una grande diffusione nel mondo della programmazione web specialmente in quei casi in cui lo staff di programmazione viene dal mondo HTML, dynamic HTML e JavaScript puro. Normalmente si identificano questi gruppi come la “nuova guardia” dove non c’è stato il tempo o la voglia di approfondire tutte le “noiosissime” questioni legate alla OOP e alla programmazione per pattern. Per chi conosce bene il mondo HTML/JS, questi strumenti hanno il vantaggio di richiedere un tempo di apprendimento molto breve, ma sono carenti per quanto riguarda il type check, e i controlli in compilazione.
JSF-ICEFaces
Rappresenta lo stato dell’arte attuale del mondo “Java Standard ufficiale” (per quanto questo termine possa non valere più come un tempo). Non ancora integrate ufficialmente in JSF è ormai notizia pubblica che la prossima release di JSF utilizzerà il framework ICEFaces come nuovo set di componenti grafici. Non si tratta semplicemente di una sostituzione del set di widget precedente (Woodstock) dato che questi nuovi componenti grafici portano in dono la possibilità di integrare chiamate asincrone AJAX a tutti gli effetti. Il risultato finale è molto accattivante e con poco sforzo si ottengono risultati certamente interessanti. Il modello di base è sempre quello di JSF che da più parti è criticato per pesantezza e verbosità del codice.
GWT
Rappresenta forse la novità più interessante e di rottura rispetto alle altre, dato che fonde la visione classica della scrittura del codice Java back-end, alla potenzialità di codice AJAX puro client-side. L’applicativo viene scritto in Java e poi in fase di compilazione viene tradotto automaticamente in JS senza che il programmatore se ne renda conto minimamente. Un progetto GWT viene normalmente suddiviso in parte di back-end (quello che verrà invocato in maniera asincrona sul server) e front-end (quello che verrà tradotto in Javascript/AJAX e che verrà inviato al client); si tratta in ogni caso di codice Java e il programmatore non deve gestire nulla di questa dicotomia, ne in fase di organizzazione del progetto ne di deploy/installazione. Da molti è considerata una tecnologie rivoluzionaria e molto promettente: il fatto di avere alle spalle Google offre notevoli garanzie di adozione e di evoluzione futura
Web framework come ZK, Wicket e altri
Sono tutte soluzioni molto promettenti, tecnicamente competitive, che tentano di risolvere in vario modo le limitazioni di JSF e di sfruttare i benefici della programmazione asincrona. Il principale problema di strumenti come questi è la mancanza di uno “sponsor” degno di questo nome alle spalle che ne possa garantire la divulgazione. Tecnicamente sono molto apprezzati da quei gruppi di lavoro che li adottano.
Flex
Qui un grosso sponsor alle spalle c’è (Adobe), anche se il nome stesso inizialmente aveva suscitato dubbi per la mancanza di una reputazione forte in ambito enterprise. La casa americana famosa per essere leader nella produzione di strumenti grafici, è riuscita a sgretolare i pregiudizi partendo dal successo e dalla diffusione di Flash, creando una sua soluzione alternativa a Java, JS e AJAX, ma con un livello di interattività altrettanto alta e di robustezza degna dei competitori. Lo strumento proprietario (anche se si sta aprendo al mondo open source), di fatto permette di realizzare tramite script (qui arrivano le maggiori critiche dato che la parte client richiede di usare l’ennesimo nuovo strumento) applicativi che poi sono compilati ed eseguiti all’interno del plugin Flash onnipresente ormai in ogni tipo di browser. La possibilità di integrare il tutto con una controparte Java server-side sta traghettando questo strumento web dal mondo dei grafici al panorama enterprise.
JavaFX
In questo settore, Sun da diverso tempo sta cercando di lanciare questa tecnologia che però ha come obiettivo principale quello della multimedialità e della grafica web. Potremmo dire che si pone come antagonista di Flash, anche se in molti dicono che è ancora troppo immaturo per poter rappresentare una minaccia.
Dato che non sarebbe possibile in questa sede analizzare ogni singolo aspetto di ogni singola tecnologia (ma su MokaByte abbiamo in passato e anche in questo periodo attivato numerose serie di articoli dedicati agli specifici argomenti) limiteremo l’attenzione a quelle due o tre tecnologie che ci sembrano le migliori per motivi tecnici oppure ci sembrano quelle destinate al maggior successo a breve per altri motivi (azienda che le promuove, appeal della tecnologia, accettazione da parte della comunità). La nostra scelta per il momento ricade su ICEFaces e su GWT, ma cercheremo presto di completare anche il paragone con Flex.
Al solito l’obiettivo non sarà quello di spiegare come programmare in Flex o GWT, ma piuttosto far vedere macroscopicamente pregi e difetti di questi strumenti nel caso cui si vogliano utilizzare per realizzare il front-layer di una applicazione Java EE.
ICEFaces
Quando fu ideato Java Server Faces, i progettisti Sun lavorarono con il preciso intento di renderlo il più possibile versatile e ampliabile secondo le esigenze del momento. Rispetto alle tecnologie del passato (in pratica JSF può essere considerato il succesore di Struts) portava un nuovo schema di gestione del flusso dei dati (il famoso flusso dei sei passi) e un set di componenti grafici da usare in modo visuale in fase di sivluppo.
Prendendo spunto da quanto di buono e di innovativo AJAX ha portato sul palcoscenico, i creatori di ICEFaces sono partiti da questo schema e hanno apportato alcune piccole modifiche al flusso dati, fornendo al contempo un set completamente rivisto di componenti: è stato quindi sostituito il render kit in modo che al browser non arrivi semplice HTML ma HTML con JS per permettere l’invocazione asincrona tipica di AJAX. Tale sostituzione viene eseguita come traduzione della response fatta sull’ultimo passo del workflow e non impatta granche’ sul resto dell’architettura JSF. Per ottenere tale risultato è stato sostitutito il render kit ed è stato aggiunto un nuovo set di componenti grafici. Lato server è stato inserito un meccanismo che permette di gestire le chiamate asincrone, modificando il motore del MVC della applicazione.
Figura 1 – Gestione del flusso dei dati in una applicazione ICEFaces.
Realizzare un’applicazione JSF che utilizzi ICEFaces si riduce quindi a eseguire alcune modifiche di base al “core” della applicazione web JSF e a usare alcuni componenti grafici particolari.
Per quanto concerne il legame con gli altri layer, vale tutto quello visto in precedenza in questa serie di articoli: per utilizzare i servizi dello strato di back-end (p.e.: invocare un session bean per poter ricavare i dati contenuti nello strato di persistenza) sarà sufficiente invocare i metodi esposti dallo strato di business logic direttamente dal codice del backing bean: da quanto abbiamo visto nella puntata dedicata ai pattern, si potrebbe usare nel backing bean un business delegate che parli con il corrispettivo session facade.
Un esempio
L’esempio che andiamo ad analizzare è quanto mai semplice e sicuramente non sufficiente per offrire una valutazione completa e accurata delle molte funzionalità di ICEFaces. Fra i molti pregi e caratteristiche che possono essere presentate, abbiamo deciso di focalizzare l’attenzione su un paio di funzionalità rese possibili grazie alla integrazione di ICEFaces con AJAX. Stiamo parlando della possibilità di eseguire submit parziali dei dati di un form al fine di validare ed elaborare solo alcune informazioni immesse, oppure di pre-impostare alcuni campi in funzione dei valori immessi in altri. Queste due funzioni permettono di realizzare form di inserimento/modifica con una interattività sicuramente maggiore rispetto a quelli realizzati in HTML/HTTP request-response.
L’esempio che andiamo a mostrare rappresenta un caso molto semplice di questo scenario: sempre prendendo spunto dagli articoli precedenti, si immagini di dover inserire i dati relativi a un apiario per apportare delle modifiche ai dati: il form di inserimento potrebbe essere il quello rappresentato in figura 2, dove il campo apiario serve per permettere all’operatore di inserire la sigla dell’apiario di cui si vuole andare ad eseguire una modifica. Il campo è di tipo testuale (inputtext) ma la selezione è con suggerimento, dato che l’utente può scegliere da un elenco di apiari pre-inseriti nel sistema. Il campo testo si trasforma quindi in un menù a tendina contenente la lista degli apiari presenti; tale lista verrà dinamicamente pre-caricata in base a quanto inserito dall’utente nel campo testo. L’effetto è chiaramente mostrato in figura 2 dove si evidenzia che se l’utente inserisce la lettera “A” sono mostrati in elenco tutti gli apiari il cui nome iniziano per “A”.
Figura 2 – Form di inserimento dati con precaricamento del campo apiario.
Per ottenere questo risultato per prima cosa è necessario associare all’oggetto databound selectInputText una lista che verrà prodotta dal backing bean della pagina JSF (notare che sebbene si usi ICEFaces, il modello architetturale di JSF resta valido) il quale pubblica la lista tramite il metodo updateList(); fino a questo punto non vi è nulla di profondamente differente rispetto a JSF statndard; la diversità risiede nella possibilità di poter effettuare il calcolo di tale lista (ovvero invocare il metodo updateList()) per ogni cambiamento del valore del campo testo (ovvero per ogni lettera immessa dall’utente):
Il metodo updateList() in un’applicazione reale dovrebbe simulare l’accesso al sistema di back end per il caricamento dei dati tramite business logic; nel nostro caso limitiamo l’attenzione alla chiamata a un ipotetico Business Delegate il cui compito è quello di nascondere la logica di interfacciamento con layer sottostanti:
public void updateList(ValueChangeEvent event) { // si simula la chiamata al db tramite un business delegate // che in questo caso non fa altro che creare una lista // di apiaryVO // l'elenco dei ApiaryVO sono poi travasati in una lista di // SelectItem e assegnati alla variabile del backing bean matchesList // che verrà usata come datamodel della lista in pagina JSF String searchWord = (String) event.getNewValue(); this.setMatchesList(this.embeddListToSelectItem(beelogBD.getApiaryListByName(searchWord))); // ricava il componente ad autocompletamento // dall'evento che ha scatenato la modifica automatica if (event.getComponent() instanceof SelectInputText) { SelectInputText autoComplete = (SelectInputText) event.getComponent(); // Se utente ha selezionato un elemento della lista a tendina // si prende questo elemento come quello selezionato if (autoComplete.getSelectedItem() != null) { // si imposta il valore dell'apiario correntemente selezionato // nella variabile currentApiary // prendendo il valore scelto dall'utetnte dal menu a tendina setCurrentApiary((ApiaryVO) autoComplete.getSelectedItem().getValue()); } } } // metodo che travasa una lista di ApiaryVO come arrivano dal // datamodel, in una lsta di oggetti SelectItem idonei per essere // utilizzati come datamodel per il componente visuale lista di ICEFaces private List embeddListToSelectItem(List apiaryList) { ArrayList ret = new ArrayList(); for (int i = 0; i < apiaryList.size(); i++) { ApiaryVO apiaryVO = (ApiaryVO) apiaryList.get(i); SelectItem selectItem = new SelectItem(apiaryVO, apiaryVO.getName()); ret.add(selectItem); } return ret; }
Riconsiderando per un momento i campi nella parte finale del form si potrà notare come, dopo che un utente abbia scelto un apiario dal campo testo-tendina, siano valorizzati automaticamente e senza la necessità di ricaricamento della pagina, grazie al valore dell’apiario scelto dall’utente al campo precedente (in questo caso per semplicità sono campi a sola lettura ma con poco lavoro potrebbero essere sostituti con campi di inserimento valorizzati, funzione certo molto utile).
Figura 3 – I campi finali del form, in questo caso sono semplicemente visualizzati in sola lettura, vengono precaricati automaticamente nel momento in cui l’utente sceglie un apiario dal campo a tendina precedente.
Questo effetto in JSF semplice non si potrebbe ottenere se non tramite l’invio della request al server e dopo l’aggiornamento del datamodel contenuto nel backing bean, la visualizzare dei nuovi dati associati ai vari componenti grafici.
In questo caso invece sfruttiamo una novità introdotta da ICEFaces che consente di eseguire submit parziali di un form HTML.
Entrambe le funzioni, qui solamente accennate (precaricamento e submit parziale), possono essere maggiormente approfondite grazie alla copiosa documentazione e agli efficaci tutorial che si trovano sul sito di ICEFaces (vedi [ICE]) o a corredo del materiale scaricabile.
Per quanto concerne invece l’esempio nello specifico, pur nella sua disarmante semplicità, ci mostra in realtà due aspetti molto importanti: il primo è che, per usare ICEFaces, non è necessario stravolgere il modello di base di JSF, cosa che ha l’innegabile vantaggio di non richiedere di dover imparare una nuova tecnologia da zero o semplicemente di dover gettar via quanto fatto fino ad oggi con JSF. La seconda conseguenza importante è legata a come ICEFaces introduce il modello asincrono di AJAX all’interno di una applicazione che formalmente è ancora una applicazione JSF: il plug avviene semplicemente cambiando il set di componenti da usare (nuova palette di widget grafici) e apportando qualche piccola modifica al file di configurazione. Il risultato finale è sicuramente molto intrigante.
Conclusioni
Dopo aver visto brevemente quali sono i benefici derivanti dall’introduzione di ICEFaces in una applicazione JSF, la domanda che sorge spontanea è la seguente: dopo aver imparato le tecniche di base per progettare e realizare gli strati sottostanti (business logic e persistence layer) e dopo aver visto come usare JSF per realizzare la parte web, dando per scontato che il futuro si sta muovendo verso applicazioni e tecnologie RIA, è conveniente e sensato investire del tempo per introdurre ICEFaces nelle nostre applicazioni?
La mia risposta (sicuramente di parte) è che ICEFaces non stravolge il modello JSF (e questo è un bene e un male) quindi non aspettiamoci che porti rivoluzioni innovative significative, per cui non credo si possa dire che possa rappresentare un grande passo in avanti. Si tratta sempre di realizzare applicazioni HTML lato server con una dose massiccia di XHTML (le pagine stesse), compito non agevole ne’ accattivante.
Se in azienda il patrimonio tecnologico, umano e di prodotti è fortemente legato a JSF, allora il passaggio a ICEFaces porterà indubbi vantaggi senza la necessità di dover compiere investimenti cospicui.
Ma se si desidera passare a qualcosa di veramente innovativo che cambi per sempre il modo di fare applicazioni web, fornendo all’utente qualcosa di più interattivo (anche se dal punto di vista del risultato finale le varie tecnologie si equivalgono più o meno) allora il consiglio è quello di passare a tecnologie diverse e più moderne, come GWT o Flex. Nei prossimi articoli avremo modo di approfondire questi aspetti.
Riferimenti
[ICE] ICEFaces home page
http://www.icefaces.org/main/home/