UTILIZANDO JSTL EN APLICACIONES JSF
Introducción
Java Server Pages Standard Tag library (JSTL) es un
conjunto de librerías de etiquetas simples y estándares que encapsulan
funcionalidad habitualmente utilizada en aplicaciones Web. Soportan funciones
como iteraciones, procesamiento condicional, procesamiento XML,
internacionalización, etc. Su uso está extendido debido sobre todo a que se
integran en las páginas JSP de forma sencilla y limpia, además de proporcionar
la mayoría de funcionalidades necesarias en un JSP.
Por otra parte Java Server Faces (JSF) es un marco de
trabajo basado en el patrón MVC (Modelo-Vista-Controlador) cuya
característica novedosa con respecto a Struts, por ejemplo, es que la parte de Vista
se crea a partir de un conjunto de componentes reutilizables disponibles del
lado del servidor.
En este tutorial veremos algunos beneficios y también
problemas al intentar utilizar estas dos tecnologías combinadamente.
Herramientas
utilizadas
- Sistema
operativo: Windows XP Professional. - Servidor
Web: Apache TomCat 5.5.9 - Entorno
de desarrollo: Eclipse 3.1.1 con ExadelStudio-3[1].0.5
Preparamos el entorno
Vamos a seguir los siguientes pasos:
1.
Creamos
un nuevo proyecto JSF en Eclipse.
Para ello selecciono File>New>Proyect>JSF
Project
|
|
Los ficheros generados son los siguientes:
2.
Incorporamos
al proyecto todo lo necesario para trabajar con JSTL
Debemos conseguir las librerías y taglibs de JSTL; todo esto
lo podemos conseguir en:
http://jakarta.apache.org/taglibs/doc/standard-doc/intro.html
A día de hoy, la versión más actual se encuentra en el
fichero jakarta-taglibs-standard-20060227.zip; lo descomprimimos y
copiamos los ficheros jstl.jar y standard.jar al directorio lib
de nuestra aplicación. La librería jstl.jar ya la había incorporado
Exadel por defecto al crear el proyecto, pero por evitar problemas de
versiones, he machacado la que ya había.
Después, actualizamos el classpath del proyecto con las
nuevas librerías
Además de las librerías, es necesario incorporar a nuestro proyecto los taglib que serán
invocados en nuestras páginas JSF. El único que voy a utilizar para este
ejemplo es c.tld, así que lo copio al directorio WEB-INF de la
aplicación.
3. Creamos
la página index.jsp
Esta página redireccionará a la página gestionUsuarios.jsf
que crearemos más adelante:
<%@ taglib <!doctype <html> <head>AUTENTIA- <body> <jsp:forward </body> </html> |
4. Generando
el bean y las clases de apoyo
Creamos el bean UsuarioBean
cuya responsabilidad, por ahora, será la de proporcionar un listado estático de
usuarios. Para ello, sobre el paquete JavaSource seleccionamos New>Class y
creamos la clase:
Creamos las variables de instancia que necesitamos, y
preparamos un método que devuelve un listado de usuarios:
package com.autentia.pruebaJstl; import java.util.ArrayList; import java.util.List; /** * Bean encargado de la * @author AUTENTIA */ public class UsuarioBean implements { /** Login private String /** Password del private String /** Nombre completo private String /** Lista de private static //////////////////////// public { listaUsuarios } //////////////////////// //////////////////////// public String return login; } public void setLogin(String login) { this.login = login; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public List { if(listaUsuarios.size()==0) listaUsuarios=creaListaInicialUsuarios(); return } ////////////////////////FIN /** * Crea una lista estática de usuarios. */ private static List creaListaInicialUsuarios() { List lResultados = new ArrayList(); lResultados.add(new lResultados.add(new lResultados.add(new return } } |
Nos apoyamos en una clase que representa la entidad usuario:
package com.autentia.pruebaJstl; /** * Clase que representa un usuario * @author AUTENTIA */ public class Usuario implements Serializable { /** Login del usuario */ private String login; /** Password del usuario */ private String password; /** private /** public { this.login=login; this.nombre=nombre; this.password=password; } public return } public this.login } public return } public this.nombre } public return } public this.password = password; }
} |
5. Registramos
el bean en el fichero descriptor de JSF
en nuestro caso,
el ficheros descriptor se llama examples-config.xml:
<faces-config> <managed-bean> </description> </managed-bean> </faces-config> |
6. Creamos
los ficheros de recursos
Así los mensajes que aparezcan en nuestra aplicación se adaptan al
idioma del usuario que esté accediendo a la misma; en este tutotial sólo los
voy a generar en español e inglés; estos ficheros estarán en el paquete
com.autentia.pruebaJstl:
recursos_es |
recursos_en |
###### FICHEROS DE RECURSOS usuarios_bienvenido=Bienvenido!!! gestionUsuarios_generacion_jsf=Listado generado con JSF gestionUsuarios_generacion_jstl=Listado generado con JSTL gestionUsuarios_nombre=Nombre gestionUsuarios_login=Login |
###### BOUNDLES FILE usuarios_bienvenido=Welcome!!! |
Primera prueba. Mostrando la lista de usuarios con el
componente dataTable de JSF y con JSTL
Creamos la página gestionUsuarios.jsp y mostramos la lista de usuarios con JSF como
se muestra a continuación:
<%@ taglib <%@ taglib <%@ taglib <html> <head> <title>AUTENTIA <style> .tabla font-size: 12px; padding: 0; cellpading:0; cellspacing:0; color: #000000;width: 80%;} .cabecera_tabla font-size: 11px; color: #000000; background-color: #AFBDB6; font-weight:bold;padding: text-align: left;border: 1 .fila .columna_left .texto font-weight:bold; font-size: </style> </head> <body> <f:loadBundle <h:form <f:view> <center> <h:outputText styleClass=»texto» /> <t:dataTable id=»data» headerClass=»cabecera_tabla» footerClass=»cabecera_tabla» <h:column> <f:facet <h:outputText </f:facet> immediate=»true»> <h:outputText </h:column> <h:column> <h:outputText </t:dataTable> </center> </f:view> </h:form> </body> </html> |
Con:
<f:loadBundle basename=»com.autentia.pruebaJstl.recursos»
var=»mensajes»/>
cargamos el fichero de recursos y con t:dataTable
visualizamos la lista de usuarios que proporciona el método getListaUsuarios
del bean usuariosBean.
Probamos en el Tomcat lo que llevamos hecho
y perfecto…
Ahora intentamos hacer lo mismo
pero utilizando JSTL; para ello importamos el taglib correspondiente:
<%@ taglib <%@ taglib <%@ taglib <%@ taglib ….. |
Y creamos el listado:
…. <br><br> <center> <h:outputText <table class=»tabla»> <tr> <td <h:outputText </td> <td </td> </tr> <c:forEach <tr class=»fila»> <td <t:commandLink <c:out </t:commandLink> </td> <td </tr> </c:forEach> </table> </center> </f:view> </h:form> </body> </html> |
Como vemos, accedo al bean a través
de la sesión:
<c:forEach
items=»${sessionScope.usuarioBean.listaUsuarios}»
var=»usuario1″>
Cuando despliego en Tomcat me
encuentro el primer problema: parece que los commandLink no funcionan
con JSTL:
Esto es debido a que el <c:forEach>
es avaluado por el contenedor de JSP cada vez que se procesa la página; el
contenedor deja disponible en la página (Page scope) la variable
usuario1, pero el concepto de Page scope es específico de JSP, y no
existe en los entornos que maneja JSF. Este problema está documentado en la
especificación de JSF (sección 9.2.8).
Parece entonces que los taglibs de
JSTL sí pueden acceder a los beans JSF que dejamos en sesión, en el request o a
nivel de aplicación, pero no al contrario.
Segunda prueba. Creando/Editando un
usuario
La página de creación y edición de los datos de un usuario será la
misma, aunque en función del tipo de acción, habrá que hacer las siguientes
consideraciones:
●
Si
estamos creando un nuevo usuario, no tiene sentido que aparezca el botón de
eliminar al usuario
●
Si
estamos editando los datos del usuario, el campo login no puede modificarse.
Estas excepciones las voy a manejar con JSTL en este ejemplo, aunque con
JSF sería mucho más adecuado utilizar el atributo rendered que tienen todos los componentes precisamente para esto,
que se muestren o no.
Antes, en la página gestionUsuarios.jsp añado un enlace para
crear un nuevo usuario:
…. …. <f:view> <table class=»tabla»> <tr> <td align=»right»> <t:commandLink action=»#{usuarioBean.nuevoUsuario}» <h:outputText </t:commandLink> </td> <tr> </table> …. …. |
Y completo el bean usuarioBean para que cuando pinchemos en Nuevo
usuario o sobre uno de los usuarios existentes, nos lleve a la página de
edición:
… … /** private String mostrarBotonBorrar; /** private String loginEditable; … …. /** * Muestra el formulario de creación de un */ public String nuevoUsuario() { // Limpiamos los clear(); return «edicion_usuario»; }
/** * Limpia los campos del bean */ private { this.login=»»; this.nombre=»»; this.password=»»; this.mostrarBotonBorrar=»false»; this.loginEditable=»true»; }
/** * Recupera como parámetro el login del * del bean y redirige a la página de * @return la página de edición de usuarios */ public { String FacesContext Map // Recuperamos el login del usuario que deseamos String idUsuario Usuario usuario = obtenerUsuario(idUsuario); if(usuario!=null) { fill(usuario); this.mostrarBotonBorrar=»true»; this.loginEditable=»false»; donde = } return donde; }
|
/** * Itera sobre la lista de usuarios y * parámetro. */ private Usuario { Usuario us = null; List lista = for(int { Usuario if(obj.getLogin().equalsIgnoreCase(login)) { us break; } } return } /** * Rellena el bean a partir de los datos de * @param usuario */ private void fill(Usuario { this.login=usuario.getLogin(); this.nombre=usuario.getNombre(); } |
Ahora añado la navegabilidad en el fichero examples-config.xml:
<navigation-rule> </navigation-rule> |
Creamos la página de edición de un usuario, que llamaremos edicionUsuario.jsp…
<%@ taglib <%@ taglib <%@ taglib <%@ taglib <html> <head> <title>AUTENTIA – TUTORIAL <link rel=»stylesheet» </head> <body> <f:loadBundle <f:view> <h:form id=»usuarioBean» <!– Login –> <h:outputLabel <c:if test=»${sessionScope.usuarioBean.loginEditable==’true’}»> <h:inputText <f:validateLength </h:inputText> </c:if> <c:if test=»${sessionScope.usuarioBean.loginEditable==’false’}»> <h:outputText </c:if>
<!– Nombre <h:inputText <f:validateLength </h:inputText> <h:panelGroup> <h:commandButton <f:verbatim> </f:verbatim> <c:if test=»${sessionScope.usuarioBean.mostrarBotonBorrar==’true’}»> <h:commandButton </c:if> </h:panelGroup> </h:panelGrid> </h:form> </f:view> </body> </html> |
Este ejemplo parece que sí funciona. Si seleccionamos el botón Nuevo Usuario el sistema permitirá al
usuario introducir un nuevo login y no aparece el botón Borrar:
Y si seleccionamos un usuario del listado, aparecerán los datos
editados, no se podrá modificar el login y sí aparecerá el botón de borrar, qué bien:
Hola, quisiera hacer una consulta, estoy usando jsf 2, quisiera mostrar un datatable solo cuando una lista tiene registros, intento lo siguiente: 0}\\\»> pero me sale el sgte. error : test=\\\»${clienteController.listCliente.size == 0}\\\» For input string: \\\»size\\\». Cual sería la forma correcta de hacerlo? Gracias