PrettyFaces: come rendere una applicazione jsf seo friendly

Le applicazioni web sviluppate con jsf normalmente non vanno molto d’accordo con i motori di ricerca: i parametri passati in post e il fatto che gli url spesso non sono “parlanti” sicuramente non aiutano in questo senso. Per fortuna c’è PrettyFaces, una libreria di ottima realizzazione che ci aiuta nell’importante compito di creare un sito ottimizzato per i motori di ricerca.

Esempio con jsf

Vediamo come utilizzare questa libreria con un esempio concreto composto da due pagine, una con una lista di categorie e una con il dettaglio di una singola categoria. Vediamo una implementazione semplice semplice usando jsf, la pagina con la lista è questa:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
	<title>Lista categorie</title>
</h:head>
<body>
	<h:form>
		<h:panelGrid columns="1">
			<h:commandLink value="#{listaCategorie.categoria1}"
				action="#{dettaglioCategoria.load}">
				<f:setPropertyActionListener
					target="#{dettaglioCategoria.categoria}"
					value="#{listaCategorie.categoria1}" />
			</h:commandLink>
			<h:commandLink value="#{listaCategorie.categoria2}"
				action="#{dettaglioCategoria.load}">
				<f:setPropertyActionListener
					target="#{dettaglioCategoria.categoria}"
					value="#{listaCategorie.categoria2}" />
			</h:commandLink>
			<h:commandLink value="#{listaCategorie.categoria3}"
				action="#{dettaglioCategoria.load}">
				<f:setPropertyActionListener
					target="#{dettaglioCategoria.categoria}"
					value="#{listaCategorie.categoria3}" />
			</h:commandLink>
		</h:panelGrid>
	</h:form>
</body>
</html>

Anche il dettaglio è molto semplice:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
	<title>Dettaglio categoria</title>
</h:head>
<body>
	Categoria #{dettaglioCategoria.categoria}: #{dettaglioCategoria.dettaglio} 
</body>
</html>

L’unica cosa da sottolineare è il collegamento fra le due pagine, quando l’utente clicca sul commandLink parte un actionListener (grazie al tag f:setPropertyActionListener) e una action sul server che carica il dettaglio. Per abilitare la navigazione creiamo anche una navigation rule nel file faces-config.xml:

<navigation-rule>
	<from-view-id>/categorie.xhtml</from-view-id>
	<navigation-case>
		<from-outcome>goDettaglio</from-outcome>
		<to-view-id>/dettaglioCategoria.xhtml</to-view-id>
	</navigation-case>
</navigation-rule>

Seo con jsf, una tragedia…

Vediamo all’opera la nostra web app (sì, insomma queste due pagine :)). Per accedere alla lista dobbiamo puntare il nostro browser alla pagina categorie.jsf:

Url lista con jsf

Cliccando su un link si accede al dettaglio ma l’url purtroppo non cambia!

Dettaglio con jsf

Questo è un problema grosso vedendo le cose dal punto di vista seo, inoltre rende inutili i bookmark del browser. Per far cambiare l’url basta aggiungere il tag redirect alla navigation rule:

<navigation-rule>
	<from-view-id>/categorie.xhtml</from-view-id>
	<navigation-case>
		<from-outcome>goDettaglio</from-outcome>
		<to-view-id>/dettaglioCategoria.xhtml</to-view-id>
		<redirect></redirect>
	</navigation-case>
</navigation-rule>

Aggiungendo questo tag viene effettuato il redirect e quindi l’url diventa quello della pagina di dettaglio, ma le cose non migliorano di molto in quanto il parametro è passato in post; per questo tutte le categorie hanno lo stesso url e rimane impossibile creare un bookmark.

Aggiungiamo PrettyFaces

Per aggiungere PrettyFaces al nostro progetto jsf dobbiamo ovviamente scaricare il jar dal sito ufficiale. Una volta scaricato il jar deve essere aggiunto nel classpath runtime, per esempio copiamo questo file nella directory WEB-INF/lib del nostro progetto.

A questo punto dobbiamo aggiungere un filtro nel web.xml in modo che le chiamate alla web app siano intercettate da PrettyFaces:

<filter>
	<filter-name>Pretty Filter</filter-name>
	<filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
</filter>

<filter-mapping>
	<filter-name>Pretty Filter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>FORWARD</dispatcher>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>ERROR</dispatcher>
</filter-mapping>

Per configurare PrettyFaces creiamo un file chiamato pretty-config.xml nella directory WEB-INF. Nel nostro caso questo file conterrà il seguente codice:

<pretty-config xmlns="http://ocpsoft.com/prettyfaces/3.3.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://ocpsoft.com/prettyfaces/3.3.0 
	http://ocpsoft.com/xml/ns/prettyfaces/ocpsoft-pretty-faces-3.3.0.xsd">

	<url-mapping id="lista">
		<pattern value="/categorie" />
		<view-id value="/categoriePretty.jsf" />
	</url-mapping>

	<url-mapping id="goDettaglioPretty">
		<pattern value="/categoria/#{categoria: dettaglioCategoria.categoria}" />
		<view-id value="/dettaglioCategoria.jsf" />
		<action>#{dettaglioCategoria.load}</action>
	</url-mapping>
</pretty-config>

Il primo tag url-mapping definisce l’url della pagina con la lista, grazie a questa configurazione possiamo accedere a tale pagina senza specificare .jsf in fondo all’url:

Lista con PrettyFaces

Per adesso è cambiato poco, il cambiamento grosso c’è nella pagina di dettaglio. Infatti nel secondo url-mapping definiamo che nell’url del dettaglio sarà presente il nome della categoria e che questo nome sarà settato automaticamente nel campo dettaglioCategoria.categoria. Tutto questo è definito all’interno del tag pattern in cui possiamo usare una expression jsf. Nel tag action definiamo anche la action jsf da eseguire prima del caricamento della pagina. In pratica abbiamo definito qui le stesse cose che nell’esempio senza PrettyFaces dovevano essere definite direttamente nei commandLink.

Vediamo adesso come modificare la pagina della lista delle categorie per sfruttare PrettyFaces. Usiamo un h:link (disponibile a partire da jsf2) al posto di un h:commandButton per passare i parametri in get invece che in post. Se state usando jsf 1.1 o 1.2 potete usare il tag h:outputLink o anche pretty:link definito nella taglib di PrettyFaces. L’attributo outcome indica l’id del tag url-mapping:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core">
<h:head>
	<title>Lista categorie</title>
</h:head>
<body>
	<h:panelGrid columns="1">
		<h:link value="#{listaCategorie.categoria1}"
			outcome="pretty:goDettaglioPretty">
			<f:param name="categoria" value="#{listaCategorie.categoria1}" />
		</h:link>
		<h:link value="#{listaCategorie.categoria2}"
			outcome="pretty:goDettaglioPretty">
			<f:param name="categoria" value="#{listaCategorie.categoria2}" />
		</h:link>
		<h:link value="#{listaCategorie.categoria3}"
			outcome="pretty:goDettaglioPretty">
			<f:param name="categoria" value="#{listaCategorie.categoria3}" />
		</h:link>
	</h:panelGrid>
</body>
</html>

Il risultato finale è quello che ci aspettiamo, cliccando su un link l’url della pagina di dettaglio contiene il nome della categoria cliccata:

Dettaglio con PrettyFaces

Conclusioni

L’url della pagina di dettaglio che abbiamo appena visto è facilmente leggibile, può essere aggiunto in un bookmark e può essere indicizzato facilmente dai motori di ricerca! Il fatto che l’url possa essere dinamico e possa contenere keyword dipendenti dal contenuto aiuta molto l’indicizzazione. Per un sito che deve sfruttare a pieno Google e gli altri motori di ricerca per aumentare le visite usare url come questo è fondamentale.

La navigazione di PrettyFaces è facile da usare, ma molto potente, può essere usata anche come alternativa alla navigazione standard di jsf. Inoltre introduce una indirezione in più, nelle varie pagine mettiamo un riferimento a un id e non alla pagina di destinazione. Ciò ci consente di cambiare gli url cambiando semplicemente un file di configurazione e senza dover rinominare le varie pagine.

Si chiude qui questa breve panoramica di PrettyFaces: abbiamo visto solo le feature principali, ma se siete interessati potete consultate la documentazione ufficiale per maggiori dettagli.

Fabio Collini

Software Architect con esperienza su piattaforma J2EE e attualmente focalizzato principalmente in progetti di sviluppo di applicazioni Android. Attualmente sono in Nana Bianca dove mi occupo dello sviluppo di alcune app Android. Coautore della seconda edizione di Android Programmazione Avanzata e docente di corsi di sviluppo su piattaforma Android. Follow me on Twitter - LinkedIn profile