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:
Per attivare la mappa viene inserito l'indirizzo nell'apposita form per poi passare i dati in entrata ai due servizi web: Yahoo Maps!
Yahoo Meteo
JSF
<h:graphicImage>
<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
managed Bean
mapService
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
JSF
place.fetch()
Place.add()
Place
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()
JSF
mapService
weatherService
Managed Bean
Yahoo!
Da notare che il metodo ritorna null
JSF
<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>
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()
JSF
public void zoomChanged(ValueChangeEvent e) {
String value = e.getComponent().getValue();
zoomIndex = (new Integer(value)).intValue();
}
zoomChanged
zoomIndex
JSF
<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
@ManagedProperty annotation
JSF 2
managed bean annotations
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:
All'interno del codice accediamo ad ogni singola risorsa attraverso I singoli tag che JSF
<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
Alcune volte si ha anche l'esigenza di accedere ad una risorsa usando il l'Express Language di JSF JSF
<h:graphicImage value="#{resource['images:cloudy.gif']}"/>
La sintassi è la seguente: resource['LIBRARY:NAME']
<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
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 |
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 |