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
Qaundo 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 granché su 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.
Realizzare una 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 façade.
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".
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):
<ice:form id="form1" partialSubmit="true"> <ice:commandButton id="button1" value="Create"/> <ice:panelGrid columns="2" id="panelGrid1"> <ice:outputText id="outputTextPosition" value="posizione"/> <ice:inputText id="inputTextPosition"/> <ice:outputText id="outputTextLine" value="linea regina"/> <ice:inputText id="inputTextLine"/> <ice:outputText id="outputTextAge" value="apiario"/> <ice:inputText id="inputTextAge"/> <ice:outputText id="outputTextApiary" value="apiario"/> <ice:selectInputText rows="5" valueChangeListener="#{FamilyCreate.updateList}" > <f:selectItems value="#{FamilyCreate.list}"/> </ice:selectInputText> <ice:outputText value="Id"/> <ice:outputText id="id" value="#{FamilyCreate.currentApiary.id}"/> <ice:outputText value="Dimensione"/> <ice:outputText id="size" value="#{FamilyCreate.currentApiary.size}"/> <ice:outputText value="Nome"/> <ice:outputText id="name" value="#{FamilyCreate.currentApiary.name}"/> <ice:outputText value="Location:"/> <ice:outputText id="location" value="#{FamilyCreate.currentApiary.location}"/> </ice:panelGrid> </ice:form>
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).
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.
Conclusione
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/
