Usando Facelets para templating en JSF

Este post es una guía breve y concisa de cómo integrar Facelets a una aplicación JSF.

Facelets es un framework de templating que nos facilita la gestión de la estructura y el estilo de las JSP, lo cual tiene beneficios en cuanto a reutilización de código en la capa de presentación y por consecuencia eleva la mantenibilidad de esta capa.

Al usar Facelets nuestro proyecto se basará en una plantilla, que contendrá la estructura de la presentación (JSP) y las definiciones de estilo, en esta plantilla definimos zonas o áreas (como el header, menú, espacios comunes) y el motor de facelets se encargará de llenar esas áreas con el contenido apropiado, así por ejemplo no tendremos el header en todas las JSP y si después de un tiempo algo tiene que cambiar se hará solo en la plantilla en lugar de hacerlo en cada página.

Entremos en materia...

Descarga.

Facelets lo pueden descargar de aquí.

Dependencias.

Debemos agregar a nuestro proyecto los siguientes jars: jsf-facelets.jar, el-api.jar y el-impl.jar.
Cabe destacar que Facelets funciona con las especificaciones para JSF 1.1 y 1.2.

Integración al proyecto JSF.

Para que agregar el soporte de Facelets a nuestro proyecto, primero agregaremos un parámetro al web.xml:

          <context-param>
            <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
            <param-value>.xhtml</param-value>
          </context-param>

En este parámetro de JSF le estamos indicando que el sufijo por default de las páginas será .xhtml por cuestiones de que Facelets requiere marcado XML, este atributo podría ser también .jspx.

Como parámetro opcional, podemos agregar:

          <context-param>
            <param-name>facelets.DEVELOPMENT</param-name>
            <param-value>true</param-value>
          </context-param>

Este parámetro hará que Facelets sea más informativo en los logs, muy útil para desarrollo y/o debug.

Ahora le diremos a nuestra aplicación JSF que debe ocupar Facelets como ViewHandler, esto lo haremos dentro de <application> en el faces-config.xml.

          <application>
            <view-handler>
              com.sun.facelets.FaceletViewHandler
            </view-handler>    
          </application>

Creando el template.

Hacemos un template sencillo en HTML, aquí es donde es recomendable definir la estructura de nuestro sitio, columnas, módulos, áreas, tamaños, etc...

template.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
    <title>RNIIPA</title>
</head>
<body id="template">
    <h1>
        <ui:insert name="titulo">Aquí Facelets insertará el título.</ui:insert>
    </h1>
    <p>
        <ui:insert name="contenido">Aquí Facelets insertará el contenido.</ui:insert>
    </p>
</body>
</html>

Usando el template.

Una vez definido el template, ya solo tenemos que indicar en cada xhtml que hagamos que se debe utilizar este template. Por ejemplo:

userlogin.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html">
<body>

<ui:composition template="/template.xhtml">

Una vez que le indicamos el template, ya solo debemos definir el contenido
de las áreas que insertaremos, esto se hace con "ui:define", cualquier contenido
fuera de esta etiqueta no será tomado en cuenta, como sucederá con este párrafo.

  <ui:define name="titulo">
    javaMexico - Inicio de sesión
  </ui:define>

Este texto no será desplegado.

  <ui:define name="contenido">
    <h:form id="login">
      <h:outputLabel for="username" value="Usuario: "/>
      <h:inputText id="username" value="#{LoginBean.username}"/>
      <br/>
      <h:outputLabel for="password" value="Contraseña: "/>
      <h:inputText id="password" value="#{LoginBean.password}"/>
      <br/>
      <h:commandButton id="submit" action="success" value="Entrar" />
      <br/>
      <h:messages style="color: red; font-weight: bold;"/>
    </h:form>
  </ui:define>
 
</ui:composition>

</body>
</html>

Cuando solicitamos desde nuestra aplicación que sea mostrada esta página, por ejemplo desde http://localhost:8080/EjemploFacelets/userlogin.faces, Facelets entrará como ViewHandler e identificará que está asociada a un template, entonces unirá las partes y mostrará la página.

De ahora en adelante si algo cambia en la estructura de nuestras páginas ya solamente deberemos cambiar el template y por consecuencia todos las páginas que lo utilicen mostrarán el cambio.

Bienvenidos sus comentarios.

Saludos.

Javier Ramírez Jr - Benek
@_benek

Comentarios

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.
Imagen de Marce

Genial

Muy bueno benek justo me estoy integrando a usar JSF con CDI y realmente está interesante como lo explicas ayuda mucho :D

Un nuevo Framework

Este framework se integra a la lista de los 2101001 frameworks con los que se puede programar en Java (jsp) ja ja ja. No ya en serio.

Buena explicación, breve y clara @_benek. Siempre es bueno conocer algo nuevo.

JSF 2.0

Lo mejor si usas JSF 2.0 ya esta integrado Facelets

Imagen de Shadonwk

Yo apenas lo voy a aplicar,

Yo apenas lo voy a aplicar, espero todo salga de acuerdo al plan y ya les mostrare como se ve, saludos, gracias @_benek por el aporte

@FlexJRL
Saludos

Al usar este template veo que

Al usar este template veo que solo me ahorraria el indicar donde deseo que se coloque un área (como el header, menú, espacios comunes) ya que se lo hace previamente en el template con los h1,p,table,tr,td,etc....... pero veo que igual en todas las páginas deberia poner el contedio del área(menu,header,etc..), como en el ejemplo de "- userLogin.xhtml -" donde tendria que escribir :

<ui:define name="menu">
    javaMexico - menu de opciones
            .Opcion 1
            .Opcion 2...etc
  </ui:define>

en todas las páginas xxxx.html.
Pero lo que deseaba era tal vez simplemente en el peor de lo casos poner <ui:define name="menu" /> en cada página y no todo el contenido del área.
Digo en el peor de los casos porque supongo que al poner el Menú o Área en cada página iria al Servidor para llenarse lo cual tampoco desearía.

Ya que si,por ejemplo:
Tengo un Menú de Opciones que se llena con info de la DB(usando el managedBean,Hibernate,etc..)... desearia ir al Servidor una sola vez, pero asi como lo tienes en el ejemplo se aprecia que habria que ponerlo en todas las páginas lo que ocasionaría es que viaje al Servidor en cada refresh de página.

En el Mejor de los casos crees que nos prodrias ayudar con algo que de el mismo soporte del Uso de los Frames, pero usando JSF y Richfaces.

Saludos,De antemano muchas Gracias por el Aporte !!

PD.: No he investigado el tema del Template JSF solo me guie con tu aporte,tal vez falta nos indiques un ejemplo mas explicito.

Imagen de benek

Re: Al usar este template veo que

Negativo.

En <ui:define name="xxxx"> solamente va el contenido "móvil" por decirlo de algún modo. El menú que tú quieres hacer no lo necesitas definir en cada página, así que intégralo dentro de tu template, ahí lo pintas pero sin meterlo en algún <ui:insert name="xxxx"> y así te saldrá en cada página que se base en este template.

Imagen de AlexSnake

Jars??

Requieres de algún jar para que corra la aplicacion? por ejemplo si vas a ocupar JSTL necesitas el jar de este, si vas a ocupar el display tag library tambien requieres de su libreria, o puede correr en un proyecto web normal que solo cuente con las librerias basicas de J2EE???

Imagen de benek

Re: Jars??

Claro, como lo dice el post:

Dependencias.
Debemos agregar a nuestro proyecto los siguientes jars: jsf-facelets.jar, el-api.jar y el-impl.jar.

;-)

Imagen de AlexSnake

Huy no lo vi

Jejeje es cierto, no me di cuenta .

!!!!!!

entonces si seguimos tu ejemplo dentro del - template.xhtml - puedo poner <ui:define name="xxxx"> y dentro del mismo tendría que poner el Area(header,Menú de Opciones,etc..) mas o menos seria algo asi ??:

template.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:f="http://java.sun.com/jsf/core"
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
    <title>RNIIPA</title>
</head>
<body id="template">
    <h1>
        <ui:insert name="titulo">Aquí Facelets insertará el título.</ui:insert>
    </h1>
    <p>
        <ui:insert name="contenido">Aquí Facelets insertará el contenido.</ui:insert>
    </p>

<!-- xxxxxxxxxxxxxxxxxxxxxxx -->

<ui:define name="menu">
    javaMexico - menu de opciones
            .Opcion 1
            .Opcion 2...etc
  </ui:define>

<!-- xxxxxxxxxxxxxxxxxxxxxxx -->

</body>
</html>

Entonces en mis páginas por ejemplo : PaginaDeEjemplo.xhtml sencillamente pondria :

PaginaDeEjemplo.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
     xmlns:h="http://java.sun.com/jsf/html">
<body>

<ui:composition template="/template.xhtml">
<strong>

1.- Cargaria el Template con el  <h1> , <p> y el <ui:define name="menu">

</strong>
<strong>

2.- Código Propio de la PaginaDeEjemplo.xhtml
</strong>
</ui:composition>

</body>
</html>

Seria Algo asi ?? ....y esa fuese la idea, entonces solo tendria que poner en cada página <ui:composition template="/template.xhtml">....Pero al hacer que cada página se base en mi template, y al cargarse mi Menu gracias al template, ya no haria peticiones al servidor para cargar mi template al irme a otra página que tambien se basa en mi template????????????

Lo que quiero decir es que si mis páginas se van a basar en el template, donde tengo un menu que se llena con info. de la base de datos(que lo deberia hacer una sola vez) y al cambiar de página en página, en ese momento no estarian haciendo cada vez y cuando peticiones a la base datos para llenar el Menu que se encuentra dentro del template .. ???????

Gracias por la información, mil disculpas si fui muy extenso...jejejeje

De antemano Muchas Gracias por tu valiosa atención y pronta respuesta.

descarga

Buenas tardes de donde puedo descar esta utileria ya que me interesa y no me deja descargar nada.
Saludos

Imagen de javatlacati

java.net está algo oculto

Tal vez puedas hallarlo aquí