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

JSF2: Eliminazione XML di configurazione e accesso facile alle risorse

JSF2: Eliminazione XML di configurazione e accesso facile alle risorse. Il primo di una piccola serie di articoli di approfondimento sulle configurazioni JSF
JSF2: Eliminazione XML di configurazione e accesso facile alle risorse. Il primo di una piccola serie di articoli di approfondimento sulle configurazioni JSF
Link copiato negli appunti

Con l'introduzione della versione 2.0, JSF rende molto più facile l'implementazione di applicazioni web robuste ed Ajax Oriented.

In particolare in quest'articolo (primo di una piccola serie) ci mostrerà come utilizzare in maniera funzionale le annotation per in sostituzione degli XML di configurazione, semplificando la navigazione e fornendo un più facile accesso alle risorse.

L'obiettivo di questo e degli articoli successivi non sarà solo quello di mostrare le nuove funzionalità di JSF2, ma di scoprire come utilizzarle al meglio per ottenere dei risultati più efficienti. I punti fondamentali in questo primo articoli saranno:

  • Liberarsi della configuarione XML
  • Semplificare la navigazione
  • Usare Groovy
  • Trarre vantaggio dalla gestione delle risorse

La figura 1 mostra l'uso del Web Services di Yahoo! per convertire l'indirizzo passato in una mappa, con i livelli di zoom e le informazioni sul tempo:

Figura 1. webservices di Yahoo! per le mappe
(clic per ingrandire)


webservices di Yahoo! per le mappe

Per attivare la mappa viene inserito l'indirizzo nell'apposita form per poi passare i dati in entrata ai due servizi web: Yahoo Maps! e Yahoo Meteo. Il servizio ritorna 11 mappe indicando sia l'indirizzo spacificato in entrata che vari livelli di zoom. Entrambi i dati di ritorno dei servizi (sia immagini che codice) possono essere racchiusi all'interno di specifici tag di JSF <h:graphicImage> e <h:output Text>

Managed bean e presentazione dei dettagli sulla mappa.

L'applicazione avrà quattro managed Bean :

Managed bean name Class Scope
mapService com.clarity.MapService Application
weatherService com.clarity.WeatherService Application
places com.clarity.Places Session
place com.clarity.Place Request

L'applicazione mantiene una lista di Places in Sessione mantiene un oggetto Place in request. L'applicazione fornisce inoltre una serie di APIs per i managed Bean mapService e weatherService.

La tabella sottostante mostra il codice per l'oggetto places da inserire all'interno della nostra form di ricerca:

<h:form>
  <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="2"/>
    #{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>

Quando l'utente attiva il button Go ed effettua la submit alla form, JSF invoca il metodo associato al button: place.fetch(). Il metodo invia le informazioni dal Web services al metodo Place.add(), che crea una nuova istanza dell'oggetto Place inizializzata con i dati passati al metodo e salvati nella request.

public class Place {
	// ...
	private String[] mapUrls
	private String weather
	// ...
	public String fetch() {
		FacesContext fc = FacesContext.getCurrentInstance()
		ELResolver elResolver = fc.getApplication().getELResolver()
		// Get maps ...
		MapService ms = elResolver.getValue(fc.getELContext(), null, "mapService");
		mapUrls = ms.getMap(streetAddress, city, state);
		// Get weather ...
		WeatherService ws = elResolver.getValue(fc.getELContext(), null, "weatherService");
		weather = ws.getWeatherForZip(zip, true);
		// Get places ...
		Places places = elResolver.getValue(fc.getELContext(), null, "places");
		// Add new place to places ...
		places.addPlace(streetAddress, city, state, mapUrls, weather);
		return null;
	}
}

Place.fetch() usa le variabili resolver di JSF per cercare i managed bean mapService e weatherService, e usa questi due Managed Bean per fare lo store dei dati sulla Mappa e sul Tempo che vengono ritornati dal WebServices di Yahoo!

Da notare che il metodo ritorna null. Questo fa in modo che JSF faccia reload sulla stessa view che restituisce a display tutti i places nella user session, come mostrato dal listato seguente:

<ui:composition
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:f="http://java.sun.com/JSF/core"
	xmlns:h="http://java.sun.com/JSF/html"
	xmlns:ui="http://java.sun.com/JSF/facelets">
<h:form>
	<!-- Iterate over the list of places -->
	<ui:repeat value="#{places.placesList}" var="place">
		<div class="placeHeading">
			<h:panelGrid columns="1">
			<!-- Address at the top -->
			<h:panelGroup>
				<div style="padding-left: 5px;">
					<i><h:outputText value="#{place.streetAddress}"/></i>,
					<h:outputText value="#{place.city}"/>
					<h:outputText value="#{place.state}"/>
					<hr/>
	            </div>
	        </h:panelGroup>
	        <!-- zoom level prompt and drop down -->
	        <h:panelGrid columns="2">
		        <!-- prompt -->
		        <div style="padding-right: 10px;margin-bottom: 10px;font-size:14px">
		        	#{msgs.zoomPrompt}
		        </div>
		        <!-- dropdown -->
				<h:selectOneMenu onchange="submit()"
					value="#{place.zoomIndex}"
					valueChangeListener="#{place.zoomChanged}"
					style="font-size:13px;font-family:Palatino">
					<f:selectItems value="#{places.zoomLevelItems}"/>
				</h:selectOneMenu>
			</h:panelGrid>
			<!-- The map -->
			<h:graphicImage url="#{place.mapUrl}" style="border: thin solid gray"/>
			</h:panelGrid>
			<!-- The weather -->
			<div class="placeMap">
				<div style="margin-top: 10px;width:250px;">
					<h:outputText style="font-size: 12px;" value="#{place.weather}" escape="false"/>
			    </div>
			</div>
      </div>
   </ui:repeat>
</h:form>
</ui:composition>

<ui:repeat> effettua una loop su placesList dell'oggetto places, e per ogni oggetto della lista lì output sarà:

Figura 2. dettagli sul tempo per ogni oggetto place sulla mappa Yahoo!
(clic per ingrandire)


dettagli sul tempo per ogni oggetto place sulla mappa Yahoo!

o zoom sarà ogni volta sempre più dettagliato in base alla scelta del livello dalla combo box.

Questa operazione viene eseguita chiamando una funzione javascript di submit() che permetterà di cambiare il livello. Come risultato di questa sumbission, JSF chiamerà il listner associando il valore scelto dal menù.

public void zoomChanged(ValueChangeEvent e) {
	String value = e.getComponent().getValue();
	zoomIndex = (new Integer(value)).intValue();
}

zoomChanged assegna il valore del livello di zoom all'attributo dell'Oggetto Place chiamto zoomIndex. Poiché la navigazione non ha nessun effettu sui cambi di stato sul server, ma riguarda semplicemente la pagina corrente, JSF fa un reload della stessa pagina aggiornando l'immagine su cui è stata effettuala l'operazione di zoom:
<h:graphicImage url="#{place.mapUrl}..."/>.

public String getMapUrl() {
	return mapUrls == null ? "" : mapUrls[zoomIndex]
}

No XML Configuration

La configurazione dei file xml all'interno di un applicazione web è stato sempre un processo molto soggetto a facili errori, che progressivamente puo' presentare sensibili difficoltà di rilevamento degli errori in fase di debug.

Come possiamo vedere nel pezzo di codice che segue, abbiamo bisogno di molte linee di codice per la dichiarazione di un managed bean (facendo riferimento a JSF1)

<managed-bean>
	<managed-bean-class>com.clarity.MapService</managed-bean-class>
	<managed-bean-name>mapService</managed-bean-name>
	<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
	<managed-bean-class>com.clarity.WeatherService</managed-bean-class>
	<managed-bean-name>weatherService</managed-bean-name>
	<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
	<managed-bean-class>com.clarity.Places</managed-bean-class>
	<managed-bean-name>places</managed-bean-name>
	<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
	<managed-bean-class>com.clarity.Place</managed-bean-class>
	<managed-bean-name>place</managed-bean-name>
	<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

Con JSF 2 scompare l'XML per far posto alle annotations

@ManagedBean(eager=true)
public class MapService {
	// ...
}
@ManagedBean(eager=true)
public class WeatherService {
	// ...
}
@ManagedBean()
@SessionScoped
public class Places {
	// ...
}
@ManagedBean()
@RequestScoped
public class Place {
	// ...
}

Si possono anche manipolare le proprietà del ManagedBean con il @ManagedProperty annotation. La tabella che segue mostra tutte le proprietà in JSF 2 dei managed bean annotations:

Managed-bean annotation Description Attributes
@ManagedBean Registra l'istanza di una classe come managed bean e lo inserisce nello scope specificato. eager, name
@ManagedProperty Consente di gestire le proprietà del a managed bean. L' annotation deve essere messa rpima della dichiarazione delll'attributo della classe.
Il nome dell'attributo specifica il nome della proprietà. Il vamore puo' essere o una stringa o un espressione JSF come #{...}
value, name
@ApplicationScoped Salva il managed bean nell' application scope.
@SessionScoped Salva il managed bean nel session scope.
@RequestScoped Salva il managed bean nel request scope.
@ViewScoped Salva il managed bean nella view scope.
@NoneScoped Specifica che un managed bean non ha scope.
@CustomScoped Salva il managed bean nella custom scope.
Un custom scope non è altro che una mappa che è accessibili alle pagine dell'autore. Con questa proprietà si puo' controllare l'accessibilita, programmaticamente, del bean nella custom scope.
value

Semplificazione della Navigazione

Un'altra differenza tra la prima versione di JSF e quella attuale è nella dichiarazione delle regole di navigazione. In JSF1 la navigazione era specificata in file xml come questi:

<navigation-rule>
	<navigation-case>
		<from-view-id>/pages/login.xhtml</from-view-id>
		<outcome>places</outcome>
		<to-view-id>/pages/places.xhtml</to-view-id>
	</navigation-case>
</navigation-rule>

Mentre con JSF 2 non abbiamo bisogno più di configurare una navigazione da una pagina all'altra in un file xml di configurazione. Questo viene fatto direttamente all'interno del nostro file xhtml associando l'action al botton specifico che richiama l'azione ed il passaggio da una pagina all'altra.

<h:commandButton id="loginButton" value="#{msgs.loginButtonText}" action="places"/>
<h:commandButton id="loginButton" value="#{msgs.loginButtonText}" action="/pages/places"/>
<h:commandButton id="loginButton" value="#{msgs.loginButtonText}" action="places?faces-redirect=true"/>

Gestione delle Risorse

JSF 2 fornisce un meccanismo standard per la definizione e l'accesso alle risorse. Ogni risorsa viene divisa in base alla tipologia (xhtml, css, jpeg, etc ..) le quali vengono inserite in una folder principale (resources). La figura di seguito esplica il discorso poc'anzi fatto:

Figura 3. risorse dell'applicazione
(clic per ingrandire)


risorse dell'applicazione

All'interno del codice accediamo ad ogni singola risorsa attraverso I singoli tag che JSF 2 ci mette a disposizione come: <h:outputScript> e <h:outputStylesheet>.

<html
	xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/JSF/facelets"
	xmlns:h="http://java.sun.com/JSF/html">
	<h:head>// ...</h:head>
	<h:body>
		<h:outputStylesheet library="css" name="styles.css" target="body"/>
		<h:outputScript library="javascript" name="util.js" target="head"/>
		// ...
	</h:body>
</html>

Le risorse in JSF 2 sono ri-allocabili, quindi è possibile specificare la posizione nella pagina in cui si desidera posizionare la risorsa specificata.

Alcune volte si ha anche l'esigenza di accedere ad una risorsa usando il l'Express Language di JSF (JSF EL) come mostrato qui di seguito:

<h:graphicImage value="#{resource['images:cloudy.gif']}"/>

La sintassi è la seguente: resource['LIBRARY:NAME'] dove LIBRARY e NAME corrispondono alla librery ed all name del tag. (Nella versione standard avremmo scritto in questo modo: <h:graphicImage library="images" name="cloudy.gif"/>)

Conclusioni.

In questo articolo abbiamo dato una breve occhiata ad alcune delle caratteristiche nuove in JSF quali i managed bean annotation, la navigazione semplificata ed il supporto per la gestione delle risorse. Altre caratteristiche verranno esaminate (quali Facelets, JSF 2's composite components, e built-in support for Ajax) per dare darvi una completa panoramica su quali sono i miglioramenti in questa nuova versione del frame work.

Ti consigliamo anche