Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

JSF2: Templating and Composite components

In questo articolo viene presentato l'approccio Templating and Composite components di JSF2
In questo articolo viene presentato l'approccio Templating and Composite components di JSF2
Link copiato negli appunti

Una delle caratteristiche più interessanti di Java Server Faces 2 (JSF2) è legata all'utilizzo dei templating e composite components, tramite i quali è semplice implementare delle users interfaces facili da modificare e da estendere.

Prendendo le mosse dall'articolo precedente (una applicazione per fornire informazioni meteo, basata sui servizi Yahoo), in questo articolo vedremo come una Web Application puo’ avvantaggiarsi dell'utilizzo di questi due componenti.

In JSF2 la parte di View -Facelets- è un templating framework basato in larga misura sui Tiles. JSF2, prevede inoltre anche un potente meccanismo chiamato composite components, costruito sulle caratteristiche del templating di Facelets, in modo tale da poter implementare dei componenti personalizzati senza codice Java e senza configurazioni XML.

Presenteremo questi due componenti attraverso due punti per capirne la filosofia:

  • Be composed
  • Think LEGOs

JSF2 Templating

Come abbiamo detto una delle potenzialità della nuova release è il sistema di templating. I templates incapsulano le funzionalità che sono comuni all’interno di una view di una web application, in modo tale da poter specificare quest’ultima una sola volta. Un template viene usato da più composition per creare viste multiple.

<h:head>
	<title>
		<ui:insert name="windowTitle">#{msgs.placesWindowTitle}</ui:insert>
	</title>
</h:head>
<h:body>
	<h:outputScript library="javascript" name="util.js" target="head"/>
	<h:outputStylesheet library="css" name="styles.css" target="body"/>	    
	<div class="pageHeading">
		<ui:insert name="heading">#{msgs.placesHeading}</ui:insert>
	</div> 
	<div class="menuAndContent">
		<div class="menuLeft">
			<ui:insert name="menuLeft"/>
		</div>    
		<div class="content" style="display: #{places.showContent}">
			<ui:insert name="content"/>
		</div> 
		<div class="menuRight">
			<ui:insert name="menuRight">
				<ui:include src="/sections/shared/sourceViewer.xhtml"/>
			</ui:insert>
		</div>
	</div>
</h:body>

Il modello di template precedente fornisce l’infrastruttura per tutte le viste seguenti dell’applicazione:

  • HTMLT <head>, <body> e <title>
  • Un titolo di default (che puo’ essere sovrascritto da una composition che usa il template)
  • CSS stylesheet
  • Alcune utility Javascript
  • Un layout nel tag <div> e nella corrispondente class del file CSS
  • Contenuti di default per l’heading (che possono essere sovrascritti)
  • Contenuti di default per il menu di destra (che possono essere sovrascritti)

L’inserimento di componenti all’interno di un template base viene effettuato tramite il tag <ui: insert>

Così come per il tag di insert il tag <ui:define> viene usato per definire una pagina standard di template per creare componenti aggiuntivi o fare dell’override di contenuti sulle pagine come mostrato di seguito:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	template="/templates/masterLayout.xhtml">
<ui:define name="content">
	<ui:include src="/sections/showSource/content.xhtml"/>
</ui:define>
<ui:define name="menuLeft">
	<ui:include src="/sections/showSource/menuLeft.xhtml"/>
</ui:define>
<ui:define name="menuRight">
	<ui:include src="/sections/showSource/menuRight.xhtml"/>
</ui:define>
</ui:composition>

La view specifica il proprio modello e ne definisce il contenuto. E’ da notare, dunque, come sia facile creare nuove viste, in quanto la maggior parte delle infrastrutture per comporre una view è incapsulata in un modello.

Un altro aspetto interessante nell’usare i template in JSF è che le view come quella vista in precedenza non cambiano molto nel tempo, per cui una buona parte del codice della view non richiede essenzialmente particolare (o alcuna) manutenzione.

Il concetto che sta dietro il template è semplice: è possibile definire un template unico che incapsula le funzionalità comuni tra più viste. Ogni vista è formata da una composition ed un template: quando JSF crea una view, carica il template della composition e quindi inserisce il contenuto definito dalla composition nel template.

Be Composite

I vantaggi di usare il Composed Method sono molteplici, vediamo come sfruttare questi vantaggi all’interno della nostra architettura in JSF.

JSF 2 incoraggia a comporre le nostre view partendo da frammenti di piccole porzioni di varie viste comuni. Come abbiamo detto, il templating incapsula comportamenti e funzionalità comuni, in modo tale da suddividere le varie view in parti più piccole.

JSF 2 mette a disposizione un tag <ui:include> che permette di scorporare una view in parti più piccole e facilmente mantenibili.

Per esempio la figura 1 mostra la il menu a sinistra della pagina di login dell’applicazione Place:

Figura 1. menu della pagina di login
(clic per ingrandire)


menu della pagina di login

Di seguito il file che definisce il contenuto del menù:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:ui="http://java.sun.com/jsf/facelets">
<div class="menuLeftText">
	#{msgs.welcomeGreeting}
	<div class="welcomeImage">
		<h:graphicImage library="images" name="cloudy.gif"/>
	</div>
</div>

Il markup del codice precedente è semplice, il che rende il file facile da leggere, comprendere, gestire ed estendere.

La figura 2 mostra il form di ricerca:

Figura 2. ricerca
(clic per ingrandire)


ricerca

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:util="http://java.sun.com/jsf/composite/components/util">
<div class="placesSearchForm">
	<div class="placesSearchFormHeading">#{msgs.findAPlace}</div>    
    <h:form prependId="false">
		<h:panelGrid columns="2">
		#{msgs.streetAddress}
        <h:inputText value="#{place.streetAddress}" size="15"/>
	    #{msgs.city}  <h:inputText value="#{place.city}"  size="10"/>
        #{msgs.state} <h:inputText value="#{place.state}" size="3"/>
        #{msgs.zip}   <h:inputText value="#{place.zip}"   size="5"/>
  	    <h:commandButton value="#{msgs.goButtonText}"
  	    	style="font-family:Palatino;font-style:italic"
  	    	action="#{place.fetch}"/>
	  </h:panelGrid>
    </h:form>
</div>
<util:icon image="#{resource['images:back.jpg']}"
	actionMethod="#{places.logout}"
    style="border: thin solid lightBlue"/>
</ui:composition>

Il codice precedente implementa una form ed usa una icon component (di cui parleremo a breve. Per ora basta sapere che si puo’ associare un immagine ad un metodo con la componenti icon). L'immagine di logout viene visualizzata nella parte inferiore della vista e rappresenta una icon component che implementa il metodo places.logout().

package com.clarity;
...
@ManagedBean()
@SessionScoped
public class Places {
  private ArrayList<Place> places = null;
  // ...
  private static SelectItem[] zoomLevelItems = {
  // ...
  public String logout() {
    FacesContext fc = FacesContext.getCurrentInstance();
    ELResolver elResolver = fc.getApplication().getELResolver();
    User user = (User)elResolver.getValue(fc.getELContext(), null, "user");
    user.setName("");
    user.setPassword("");
    setPlacesList(null);
    return "login";
  }
}

Smalltalk Composed Method pattern

Ritornando alla form precedente, volendo sfruttare al meglio il concetto di component potremmo suddividere il contenuto del file che rappresenta la form in due file più snelli che vengono richiamati da un altro file:

Form Place File

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets">
	<div class="placesSearchForm">
		<div class="placesSearchFormHeading">#{msgs.findAPlace}</div>
	    <ui:include src="addressForm.xhtml">
	    <ui:include src="logoutIcon.xhtml">
	</div>
</ui:composition>

addressForm.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:ui="http://java.sun.com/jsf/facelets">
    <h:form prependId="false">
    	<h:panelGrid columns="2">
	  		#{msgs.streetAddress}
	  		<h:inputText value="#{place.streetAddress}" size="15"/>
			#{msgs.city}  <h:inputText value="#{place.city}"  size="10"/>
			#{msgs.state} <h:inputText value="#{place.state}" size="3"/>
			#{msgs.zip}   <h:inputText value="#{place.zip}"   size="5"/>
			<h:commandButton value="#{msgs.goButtonText}"
	      		style="font-family:Palatino;font-style:italic"
				action="#{place.fetch}"/>
		</h:panelGrid>
	</h:form>
</ui:composition>

logouticon.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:util="http://java.sun.com/jsf/composite/components/util">
	<util:icon image="#{resource['images:back.jpg']}"
		actionMethod="#{places.logout}"
		style="border: thin solid lightBlue"/>
</ui:composition>

Quando si compone una view da più file di piccole dimensioni è buona norma applicare uno Smalltalk Composed Method pattern. Raccogliamo tutti i file che ci hanno permesso di creare la vista come segue:

Figura 3. struttura dei file che compongono le view
(clic per ingrandire)


struttura dei file che compongono le view

Le tre directory views, template e sections contengono la maggior parte dei file xhtml usati per l'applicazione Place. Poiché i file le directori views e template cambiano direttamente posso concentrarmi direttamente sulla directory sections. Ad esempio, se voglio cambiare l’icona del menu a sinistra della pagina di login so esattamente dove andare: la sezione sarà login/menuLeft.xhtml.

É possibile utilizzare qualsiasi struttura di directory per organizzare i file xhtml. Una struttura logica rende facile da individuare il codice che è necessario da modificare.

I Component sono un meccanismo di riutilizzo molto potente. A differenza di JSF1, JSF2 rende facile da implementare Component personalizzati.

Think LEGOs

La forza di JSF è stata sempre il suo modello a Componenti, anche se il potenziale non è stato realmente realizzato fino ad ora in quanto era difficile in JSF1 implementare componenti personalizzabili. Si doveva scrivere codice java, molti file di configurazione XML e si doveva conoscere perfettamente il ciclo di vita di JSF.

Con JSF2 è possibile realizzare componenti personalizzati:

  • In assenza di configurazione XML o altro.
  • In assenza di codice java
  • A cui gli sviluppatori possono collegare delle funzionalità
  • Hot-deploy una volta modificati

Implementare dei Custom Components

JSF2 combina Facelets templating, gestione delle risorse (discusso nella prima parte di questa serie di articoli) ed una semplice naming convention per l’implementazione dei composite components.

Composite components, come indica il nome, permette di creare componente da quelli gia esistenti.

Di seguito vediamo come vengono distribuiti i vari componenti in sotto directory all'interno di una directory principale di re source.

Per utilizzare i composite components si deve dichiarare un namespace e usarne i tags. Il namespace è sempre http://java.sun.com/jsf/composite più la directory in cui il componente risiede sotto la directory resources. Il nome del componente è quello del suo file xhtml senza la sua estensione.

Per utilizzare, dunque, il componente util:

Figura 4. componenti
(clic per ingrandire)


componenti

<html xmlns="http://www.w3.org/1999/xhtml"
	...
    xmlns:util="http://java.sun.com/jsf/composite/component/util">
    ...
    <util:login.../>
    ...
</html>

Oppure il componente login

<html xmlns="http://www.w3.org/1999/xhtml"
	...
	xmlns:util="http://java.sun.com/jsf/composite/components/util">
	...
	<util:icon.../>
	...
<html>

conclusioni

In questo articolo abbiamo visto come usare JSF2 per implementare interfacce utente che siano facili da mantenere ed estendere attraverso i temlplate ed i composite components. Nel prossimo articolo della serie vedremo come intergrare ed utilizzare Javascript all’interno di un composite components, come utilizzare il nuovo modello ad eventi di JSF2 e di come sfruttare del supporto integrato di JSF 2 per Ajax.

Ti consigliamo anche