CERCA SITEMAP FEED RSS 1280
Ultimo aggiornamento: 30 Agosto 2009

Modello di navigazione in JavaServer Faces

In JSF la navigazione è un insieme di regole per scegliere la successiva pagina che deve essere visualizzata dopo un'azione (es. click su un link).

La navigazione può essere di due tipi:
  • statica se cliccando su un determinato bottone la pagina successiva da visualizzare è fissata.
  • dinamica se la successiva pagina che viene visualizzata dipende dal risultato dell’elaborazione sull’input utente.

Navigazione statica

Per implementare la navigazione statica è sufficiente indicare nell'attributo action del componente (ad esempio un commandButton) il valore logico che identifica univocamente la regola di navigazione definita nel file di configurazione da applicare.
  <h:commandButton label="Login" action="login"/>
Una regola di navigazione è definita dall’elemento navigation-rule ed ha la seguente forma:
 <navigation-rule>
   <from-view-id>/index.jsp</from-view-id>
   <navigation-case>
     <from-outcome>login</from-outcome>
     <to-view-id>/benvenuto.jsp</to-view-id>
   </navigation-case>
 </navigation-rule>
L’elemento from-view-id identifica la pagina alla quale applicare la regola (se non viene specificato la regola è applicabile a tutte le pagine), gli elementi navigation-case definiscono tutti i possibili casi che possono verificarsi.
Ogni elemento navigation-case contiene l’elemento from-outcome che specifica il valore logico cui corrisponde il caso di navigazione (il NavigationHandler cerca di effettuare un match fra tale valore e quello memorizzato nell’attributo action) e l’elemento to-view-id che indica la pagina di destinazione.
Se non viene effettuato alcun match la pagina corrente viene visualizzata nuovamente.
Nell’elemento from-view-id è possibile anche utilizzare il carattere jolly * per fare in modo che la regola sia applicabile a tutte le pagine per le quali si ha una corrispondenza con la parte che precede tale carattere.
  <navigation-rule>
    <from-view-id>/cartella/*</from-view-id>
    <navigation-case>
      ...
    </navigation-case>
  </navigation-rule>
Se si vuole effettuare un redirect è sufficiente inserire l’elemento <redirect/> all’interno dell’elemento navigation-case corrispondente.

Navigazione dinamica

Nella maggior parte dei casi la navigazione all’interno di una web application non è statica, la pagina successiva da mostrare all’utente dipende infatti dal risultato dell’elaborazione sull’input che questo fornisce.
Si pensi ad esempio ad un’operazione di login il cui esito (e quindi la pagina da visualizzare) dipende dalla correttezza delle credenziali fornite.
In questi casi occorre quindi implementare una forma di navigazione dinamica e prevedere dei metodi in grado di effettuare le elaborazioni necessarie al fine di stabilire la pagina da mostrare.
In questo caso l’attributo action del tag componente fa riferimento al metodo di un oggetto lato-server (detto backing bean) che non riceve alcun argomento e produce un valore logico di tipo String.
<h:commandButton label="Login" action="#{miobean.verificaDati}"/>
L’oggetto back-end potrebbe effettuare un confronto dei dati utente con quelli memorizzati e quindi restituire la stringa “successo” o “fallimento” a seconda dell’esito di tale confronto.
  String verificaDati()  
  {
    if (condizione)
      return “successo”;
    else
      return “fallimento”;
  }
Una volta prodotta la stringa logica il NavigationHandler provvede ad effettuarne il matching con le regole di navigazione definite nel file di configurazione dell’applicazione.
Se il metodo restituisce null allora viene visualizzata nuovamente la pagina corrente.
Nel caso in cui metodi diversi possono restituire lo stesso valore logico (perché ad esempio si vuole evitare di dover definire valori logici differenti fra loro), nasce il problema di dover essere in grado di risolvere tali ambiguità all’interno delle regole di navigazione.
Per fare ciò le specifiche JSF prevedono la definizione di un elemento from-action all’interno dell’elemento navigation-case che faccia riferimento al metodo che genera il valore logico al quale viene applicata la regola di navigazione.
Così ad esempio è possibile distinguere fra due metodi di due bean diversi che producono lo stesso valore logico “successo”:
<navigation-case>
  <from-action>#{miobean.verifica1}</from-action>
  <from-outcome>successo</from-outcome>
  <to-view-id>/successo1.jsp</to-view-id>
</navigation-case>
<navigation-case>
  <from-action>#{miobean.verifica2}</from-action>
  <from-outcome>successo</from-outcome>
  <to-view-id>/successo2.jsp</to-view-id>
</navigation-case>

Algoritmo di navigazione

L’algoritmo di navigazione si compone di due fasi, nella prima si individua la regola di navigazione da applicare, nella seconda si individua il navigation-case all’interno della regola di navigazione da prendere in considerazione.

Il NavigationHandler riceve in ingresso:
  • il valore logico contenuto nell’attributo action del tag o restituito dal metodo da questo referenziato
  • il view ID della view corrente
  • il contenuto dell’attributo action (ovvero il metodo referenziato dal tag componente)
Nella prima fase vengono effettuati i seguenti controlli:
  • se il valore logico è pari a null la pagina corrente viene ricaricata
  • altrimenti si cerca una regola di navigazione che corrisponde esattamente al view id, se tale regola esiste viene selezionata e si passa alla fase successiva
  • altrimenti si selezionano quelle regole che fanno uso del carattere jolly è e hanno una corrispondenza con il view id corrente e fra queste si seleziona quella che ha la corrispondenza più lunga
  • altrimenti se c’è una regola che non fa uso dell’elemento from-view-id questa viene selezionata
  • altrimenti viene ricaricata la pagina corrente.
Nella seconda fase:
  • se c’è un elemento navigation-case con una corrispondenza su entrambi gli elementi from-outcome e from-action, questo viene selezionato
  • altrimenti se c’è un match con from-outcome e from-action non definito questo viene selezionato
  • altrimenti se c’è un match con from-action e from-outcome non definito questo viene selezionato
  • altrimenti se c’è un navigation-case senza from-action e from-outcome allora questo viene selezionato
  • altrimenti la pagina corrente viene ricaricata