JSF 2.X
JSF 2.X
CURSO JEE 7.
JSF 2.X
22/06/2022
JSF Página |2
Contenido
JSF.................................................................................... 4
JSF: Tratamiento de la petición ...................................................................... 4
Login en JSF................................................................................................. 12
Idiomatización ............................................................................................... 23
ConverterDateTime ................................................................................. 28
ConverterNumber .................................................................................... 28
Validadores ................................................................................................... 30
Panel ........................................................................................................ 38
TabSet ..................................................................................................... 39
Acordeón ................................................................................................. 41
JSF Página |3
AceDialog................................................................................................ 41
NotificationPanel ..................................................................................... 43
Tooltip ..................................................................................................... 44
Menús ........................................................................................................... 45
MenuButton ............................................................................................. 48
JSF
JSF (Java Server Faces) es la única tecnología web recomendada por Oracle. Es
una tecnología Java al cien por cien, por lo tanto, todos los objetos son clases y en
general (especialmente las vistas) no tienen nada que ver con otros marcos web. La
programación consiste en clases de Java y archivos XML, de forma que el
funcionamiento de la apliación se controla mediante dichos ficheros XML. Como todo
desarrollo web ha tenido varias versiones, concretamente en la actualidad existen la 1.x
y la 2.x, no siendo necesariamente compatibles entre sí.
JSF es extensible (como cualquier tecnología base), es decir, que se pueden crear
componentes de JSF propios o hacer uso de librerías ya creadas:
• Mojarra1: implementación base de JSF.
• MyFaces: implementación de la comunidad Apache
• RichFaces: implementación de Jboss
• Primefaces: implementación de la comunidad
• IceFaces: implementación de la empresa Icesoft
1
El nombre proviene de un pez de cardumen, que es un pez pequeño de acuario. Esto se debe a
que en la comunidad de Java hay un interés especial por los peces.
JSF Página |5
JSF se diseñó desde un principio para que cumpliese las reglas más estrictas del
desacomplamiento. Así, los ManagedBean son clases puras, sin interfaces ni herencias.
Es decir, POJOS puros. Por lo tanto, para la comunicación entre los componentes y los
ManagedBean se emplean expresiones dinámicas, el componente conoce la expresión y
el ManagedBean conoce el resultado de dicha expresión. En principio dichas
expresiones se situarían en la vista (ficheros XHTML), pero para poder utilizarlas
dentro del ManagedBean se extraerá el motor de expresiones dinámicas de JSF y se
utilizará a conveniencia.
• View: es el más interesante, dado que es un contexto que va ligado a la vista, por
lo que la duración del ManagedBean es la misma que la de la vista. Mientras la
vista permanezca activa, el ManagedBean sigue existiendo
Tratamiento de eventos
El tratamiento de eventos que hace JSF es el modelo de delegación, es decir,
algún objeto (un componente de JSF) genera un evento (emisor) y delega el tratamiento
en un tercero (receptor), no habiendo retroalimentación. A diferencia de Swing, donde
los receptores implementan una interfaz para el tratamiento del evento, en JSF se
emplean las expresiones dinámicas.
JSF P á g i n a | 12
Login en JSF
Se crea un nuevo proyecto Web y se añaden los Project Facets de Hibernate,
Spring y JSF. Una vez creado, se cambia el welcome-file-list a la página de inicio
deseada:
<!-- MECANISMO DE ARRANQUE EN PRIMERA PETICION -->
<welcome-file-list>
<welcome-file>xhtml/login.xhtml</welcome-file>
</welcome-file-list>
IGestion_Usuarios.class).consultar_PorNombre(
getNombre_usuario());
//Se establece la recarga de la vista en caso de error
String salida = "";
if(usuario != null) {
if(usuario.getPassword().equals(getClave_usuario())) {
//Credenciales correctas
salida = "correcto";
}else {
//Error en la clave
}
}else {
//Error de nombre
}
return salida;
JSF P á g i n a | 14
Por lo tanto, se crea una nueva regla de navegación para el caso en la que los
datos introducidos por el usuario sean correctos:
<navigation-rule>
<from-view-id>/xhtml/login.xhtml</from-view-id>
<navigation-case>
<from-outcome>correcto</from-outcome>
<to-view-id>/xhtml/despues_login.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Como su propio nombre indica, el concepto es que sumario sea un resumen del
contenido del mensaje, mientras que detalle debería ser una explicación más detallada
de éste.
El mensaje debe estar dentro del contexto de JSF, dado que debe estar accesible
para que la vista pueda leer la información del mismo. Para poder resolver esto, se
emplea la clase FaceContext, que es uno de los contextos (el más básico y principal)
propios de JSF. Cada vista tiene su propio objeto FaceContext. Es una clase abstracta,
por lo que no hay posibilidad de instanciarse un objeto con el constructor, sino que tiene
un método de instancia estático denominado getCurrentInstance (). Éste método
devuelve el objeto FaceContext de cada vista.
FaceContext permite acceder a los contextos de JEE (petición, session, etc) y
también a los de JSF. Uno de los métodos que tiene FaceContext es addMessage, el
cual permite añadir el mensaje al contexto de JSF3.
2
Una de las comprobaciones que se realizan cuando se tiene el Project Studio en development es
si se han utilizado todos los mensajes.
3
A efectos prácticos, para ocultar todos los pasos necesarios para recoger y manejar datos, en la
documentación de JSF se recomienda encapsular el proceso dentro de una clase auxiliar, tal y como se
hará en el proyecto.
JSF P á g i n a | 16
Por lo tanto, se crea una clase auxiliar que recoja todo este proceso y que
simplifique el código en las clases que lo necesiten, ya que simplemente con llamar a un
método de dicha clase auxiliar se obtiene el resultado deseado. El contenido de la clase
auxiliar es el siguiente:
public class Acceso_Contextos implements INiveles_FacesContext {
FacesContext.getCurrentInstance().addMessage(identificador,
new FacesMessage(nivel, mensaje_sumario,
mensaje_detalle));
}
sumario = rb.getString(clave_sumario);
}
// ESTABLECEMOS EL NIVEL POR DEFECTO, SI ES
NECESARIO
if (nivel == null) {
nivel = INFO;
}
// GENERAMOS EL MENSAJE
FacesContext.getCurrentInstance().addMessage(identificador,
new FacesMessage(nivel, sumario,
detalle));
} catch (Exception e) {
System.out.println("NO EXISTE PROPERTIES DEFINIDO.
REVISAR ATRIBUTO DE SESION IDIOMA_ELEGIDO");
}
}
.getCurrentInstance().getExternalContext().getRequest();
return peticion;
}
ApplicationContext application =
WebApplicationContextUtils
.getWebApplicationContext(Acceso_Contextos.getAplicacion());
return application;
}
4
No se debe confundir con la etiqueta <h:messages>, que muestra todos los mensajes
producidos. Por defecto muestra el sumario y oculta el detalle.
JSF P á g i n a | 19
todos los recursos estáticos estar dentro de una carpeta denominada resources y con
subcarpetas por categoría (resources --> css).
Un detalle importante a tener en cuenta es que se debe cambiar el número de
columnas de 2 a 3 para que se incluya una asociada a los mensajes, dado que sino, al
haber dos columnas únicamente el mensaje de error aparecería en la siguiente fila. En la
Tabla 1 y Tabla 2 se muestra un ejemplo:
Tabla 1. Tabla con dos columnas
Para realizar la carga de recursos, en este caso de los estilos, se emplea dentro
del head la etiqueta <h:outputStylesheet> indicándole la ruta relativa (dado que toma
automáticamente como directorio principal la carpeta resources ya comentada), tal y
como se muestra a continuación:
<h:outputStylesheet id="carga_tema" name="css/estilos.css"/>
El contenido de la página de estilos es el siguiente:
.estilo_warn {
color: maroon;
}
.estilo_info {
color: blue;
}
.estilo_fatal {
color: silver;
}
.estilo_error {
color: red;
}
Así, cuando se llama en los mensajes de error a los class del archivo css
denominados estilo_info y estilo_warn, se muestran los mensajes formateados en base a
dicho estilo. Así, la página login.xhtml queda:
<h:head>
<title>JSF 2.2 Page</title>
JSF P á g i n a | 20
Agrupación de temas
Al igual que realizaba Spring, se puede realizar una agrupación de temas para
proporcionar recursos específicos a cada navegador. Desde el punto de vista de JSF, la
agrupación de temas consiste en una carpeta que contiene todos los recursos asociados
al tema. Para indicarle el tema, se añade el atributo library a la etiqueta
<h:outputStylesheet>.
<h:outputStylesheet id="carga_tema" name="css/estilos.css"
library="defecto" />
nombre_navegador = "Chrome";
int_navegador = new Integer(navegador[7]);
reconocido = true;
}
// TRATAMIENTO PARA LOS CASOS EN QUE NO SE CONOZCA EL NAVEGADOR
if (!reconocido) {
nombre_navegador = "No reconocido";
int_navegador = new Integer(navegador[8]);
}
// COLOCAMOS EN LA SESION LA IDENTIFICACION DEL NAVEGADOR PARA
SU
// POSTERIOR USO, TANTO EN LETRA COMO EN VALOR NUMERICO
http_peticion.getSession().setAttribute("navegador",
int_navegador);
http_peticion.getSession().setAttribute("nombre_navegador",
nombre_navegador);
// TRAZA DEL PROCESO
if (log.isTraceEnabled()) {
log.trace("identificador navegador en letra..:" +
nombre_navegador);
log.trace("identificador navegador en numero..:"
+ int_navegador.intValue());
}
// CONTINUA LA PETICION COMO CORRESPONDA
cadena_peticion.doFilter(peticion, respuesta);
}
<filter-mapping>
<filter-name>filtro_navegador</filter-name>
<url-pattern>/xhtml/login.xhtml</url-pattern>
</filter-mapping>
}
if (tipo_navegador.intValue() == IFiltro_Navegador.EXPLORER_9) {
tema_jsf = "explorer";
}
if (tipo_navegador.intValue() == IFiltro_Navegador.EXPLORER_10)
{
tema_jsf = "explorer";
}
if (tipo_navegador.intValue() == IFiltro_Navegador.CHROME) {
tema_jsf = "chrome";
}
if (tipo_navegador.intValue() == IFiltro_Navegador.MOZILLA) {
tema_jsf = "mozilla";
}
if (tipo_navegador.intValue() == IFiltro_Navegador.DESCONOCIDO)
{
tema_jsf = "defecto";
}
return tema_jsf;
}
Idiomatización
Como siempre, se crea un paquete dentro del proyecto con los archivos
properties correspondientes. En primer lugar, se le debe indicar a la vista que se va a
utilizar idiomatización. Para ello, se establece el properties desde el que se va a leer a
partir de la etiqueta <f:loadBundle>, que se encarga de la creación del ResourceBundle.
<f:loadBundle basename="#{sessionScope.idioma_seleccionado}"
var="idioma" />
5
Además, se debe crear la ruta de carpetas necesaria para cada navegador, es decir, defecto,
explorer, chrome y mozilla.
JSF P á g i n a | 24
6
Dentro de la carpeta xhtml/ejemplos se muestran ejemplos de algunos de los componentes
básicos de JSF.
JSF P á g i n a | 25
value="#{seleccion_bean.pais_seleccionado}">
<f:selectItem id="sin_seleccion" itemValue="0"
itemLabel="Seleccione un pais" />
<f:selectItems id="modelo_paises"
value="#{seleccion_bean.lista_paises}" />
</h:selectOneMenu>
</h:panelGrid>
Con esto ya quedarían listados los paises para que el usuario escoja. Una vez que
el usuario haya seleccionado alguna selección, se deberán mostrar las provincias
asociadas a dicho país. Esto se realiza a partir de una petición via Ajax. El evento que se
va a tratar es un evento de cambio de valor, por lo que se deberá añadir la propiedad
valueChangeListener en el <h:selectOneMenu>.
JSF P á g i n a | 26
<h:selectOneMenu id="lista_paises"
value="#{seleccion_bean.pais_seleccionado}"
valueChangeListener="#{seleccion_bean.carga_Provincias}">
lista_municipios.clear();
if (pais_seleccionado.equals("73")) {
// España - modificacion del texto inicial del combo
texto_provincia = "Seleccione una provincia";
// Consultamos la informacion a la fuente de datos
List<Provincias> lista =
Acceso_ApplicationContext.getBean(
IGestion_Provincias.class).consultar_Todas();
// Creamos dinamicamente el contenido de la lista
for (Provincias provincia : lista) {
opcion = new SelectItem();
opcion.setLabel(provincia.getProvincia());
opcion.setValue(provincia.getCodigoProvincia());
lista_provincias.add(opcion);
}
} else {
// Cualquier otro pais - reinicamos las listas de
provincias y
// municipios a valores iniciales
texto_provincia = "Seleccione un pais";
//texto_municipio = "Seleccione una provincia";
}
}
Conversiones y validaciones
Una conversión, como siempre, se puede realizar a la entrada (cuando llega la
petición del usuario), como en la salida (cuando se pinta la respuesta a dicha petición).
Por tanto, un conversor se le puede colocar a un componente de entrada <h:inputText>
como a uno de salida <h:outputText>.
Conversores
Los conversores pueden ser de dos tipos: previamente creados e incluidos en JSF
y conversores propios. Dentro de los conversores propios de JSF se encuentran:
ConverterDateTime
<f:converterDateTime>: sirve para convertir texto a objetos Date. No es otra
cosa que un SimpleDateFormat. Dentro de sus atributos se encuentra por ejemplo type,
que puede tomar los valores:
• Date: solamente admite datos de la fecha de
• Time: al contrario que date, solamente admite la parte horaria (horas, minutos,
segundos, milisegundos, etc.) de la fecha.
• Both: es una combinación de los anteriores, admitiendo cualquier componente de
la fecha.
Otro atributo es Locale, con el que se le indica el objeto Locale que va a definir
el formato de la fecha. La clase Locale está definida en el API I18N7 y se encarga de
controlar todo lo referente a información de fecha, procesos monetarios, etc. Alguno de
los datos que proporciona el Locale son el país y la zona horaria. Esto implica que si no
se le indica nada, el converterDateTime emplea los valores que contenga el Locale
definido en el I18N, por lo que será necesario indicar un Locale con formato propio para
poder mostrar la hora en el formato deseado.
Un tercer atributo de converterDateTime es el denominado pattern, que permite
definir un patrón personalizado para mostrar la hora y fecha en base a las letras que
proporciona la clase SimpleDateFormat. Así, a modo de ejemplo, MM significa el
número del mes, MMM es una abreviatura del mes y MMMM o más se corresponde con
el nombre del mes completo.
ConverterNumber
7
I18N hace referencia a Internationalization y el número 18 son las diferentes letras que se
emplean en la internacionalización.
JSF P á g i n a | 29
Conversor Propio
Para indicar un conversor propio, se debe hacer uso de la etiqueta
<f:converter>, incluyendo en el atributo converter-id el nombre del conversor, que
deberá haber sido definido en el fichero de configuración de JSF. Para definirlo en este
fichero, se emplea la etiqueta <converter>, a la que se le añade el identificador
<converter-id> y la clase asociada al mismo <converter-class>.
La clase asociada al conversor tiene que implementar la interfaz Converter, que
define dos métodos: uno para la conversión de entrada (getAsObject(FacesContext,
UIComponent,String)) y otro para la conversión de salida
(getAsString(FacesContext,UIComponent,String)).
Los componentes de JSF siguen los mismos patrones de diseño que los
componentes de Swing, en el que cada componente hijo va especializando el
componente. UIComponente es el padre común de todos los componentes de JSF y es, a
su vez, el componente del parámetro que se va a convertir.
Para gestionar las excepciones asociadas a la conversión errónea, se emplea la
sentencia throw, lanzando una excepción de la clase ConverterException, que reciber
por parámetro un FacesMessage con la información asociado al fallo en la conversión.
8
Percent tiene una característica importante, y es que al guardar un número escrito lo divide
entre 100 (100 --> 1) y al mostrarlo lo multiplica por 100 (1 --> 100), por lo que es importante tenerlo en
cuenta en los cálculos.
9
Los double, al ser coma flotante debe repartir los digitos antes y después de la coma, por eso se
denomina coma flotante.
JSF P á g i n a | 30
Validadores
Al igual que ocurre con los conversores, existen tanto validadores definidos
como la posibilidad de crear validadores propios. Los validadores solamente tienen
sentido a la entrada.
Validadores de rango
Algunos de los validadores definidos son validateLongRange,
validateDoubleRange, validateLength, que sirven para validar el rango de números
enteros, de números decimales y la longitud de una cadena de caracteres.
Éstos validadores tienen el atributo maximum/minimun, que permite definir el
número mínimo y máximo en los dos primeros y el mínimo y máximo número de
caracteres en el tercero.
Validador Personalizado
Al igual que ocurre con los conversores, se puede crear un validador
personalizado, en este caso mediante la etiqueta <validator>, que también tendrá un
atributo validator-id para asociarlo con el validador definido en el fichero de
configuración de JSF.
Para incluir el validador en el fichero faces-config.xml se emplea la etiqueta
<validator>, que a su vez hace uso de <validator-id> para indicar el nombre del
JSF P á g i n a | 31
</h:inputText>
<h:message for="numero_usuario" />
<h:outputText id="eti_fechaalta"
value="#{idioma['conversion.fechaalta.eti']}"
/>
<!-- CONVERSION A FECHA -->
<h:inputText id="fecha_alta"
value="#{usuario_bean.fecha_alta}"
converterMessage="#{idioma
['conversion.error.conversion.fecha']}">
<f:convertDateTime type="date"
pattern="dd/MM/yyyy" />
</h:inputText>
<h:message for="fecha_alta" />
<h:outputText id="eti_fechabaja"
value="#{idioma['conversion.fechabaja.eti']}"
/>
<!-- CONVERSION A FECHA -->
<!-- VALIDAMOS LAS FECHAS ENTRE SI,VALIDADOR PERSONALIZADO
-->
<h:inputText id="fecha_baja"
value="#{usuario_bean.fecha_baja}"
converterMessage="#{idioma
['conversion.error.conversion.fecha']}">
<f:convertDateTime type="date"
pattern="dd/MM/yyyy" />
<f:validator
validatorId="validar_rangofechas" />
</h:inputText>
<h:message for="fecha_baja" />
<h:outputText id="eti_email" value="Email" />
<!-- VALIDACION CON EXPRESION REGULAR-->
<h:inputText id="email"
value="#{usuario_bean.email}"
required="false" validatorMessage="No es un
formato correo valido">
<f:validateRegex
pattern="(^[_a-z0-9-]+(\.[_a-z0-9-
]+)*@[a-z0- 9-]+(\.[a-z0-9-]+)*(\.[a-
z]{2,3})$)*" />
</h:inputText>
<h:message for="email" />
</h:panelGrid>
<!-- BOTON DE SUMIT PARA REALIZAR LAS CONVERSIONES/VALIDACIONES
-->
<h:commandButton id="boton"
value="#{idioma['conversion.botonconfirmar.eti']}"
actionListener="#{usuario_bean.boton_Evento}" />
</h:form>
</h:body>
vea los caracteres (codificados) que escribe. De otra forma, aunque escriba no tendría
un feedback de que está introduciendo caracteres (como ocurre en sistemas de Linux).
También se ha declarado un nuevo managedbean, denominado usuario_bean
que deberá ser creado para poder hacer uso de él. Esta clase simplemente debe tener las
propiedades nombre_usuario, clave_usuario e idioma (todas String), las propiedades
fecha_alta y fecha_baja (de tipo Date) y la propiedad numero_usuario (Integer), así
como sus respectivos accesores para JSF y un método para gestionar el evento (cuyo
contenido simplemente es un sysout).
Para declararlo se añade en el fichero faces-config.xml lo siguiente:
<!-- CONVERSIONES Y VALIDACIONES -->
<managed-bean>
<description>Proceso de administracion de usuarios</description>
<managed-bean-name>usuario_bean</managed-bean-name>
<managed-bean-
class>com.atrium.managedbean.Usuario_Bean</managed-bean- class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
.findComponent("formu_conversionvalidacion:fecha_alta");
// Se saca el objeto date del componente
Date fecha_alta = (Date) ((HtmlInputText) componente_fechaalta)
.getValue();
// Se comparan las fechas
if (fecha_alta != null && fecha_baja != null
&& fecha_alta.after(fecha_baja)) {
JSF P á g i n a | 34
10
Están establecidos dentro de los componentes denominados MOBI
11
Una de las ventajas de JQuery, además de la compatibilidad, es que tiene una muy buena
documentación.
JSF P á g i n a | 36
Uno de los componentes más interesantes (que también está en JSF aunque
menos extenso) es el DataTable, que es un componente de rejilla, tal y como se muestra
en la Fig. 2.
Componentes
Se crea una nueva carpeta dentro del proyecto denominada xhtml, donde se
guardan las páginas a emplear, que se crean a partir de los XHTML Advanced
Templates, pero esta vez seleccionando como plantilla la de IceFaces 3 y nombrándola
como ejemplo_contenedores.xhtml.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
JSF P á g i n a | 38
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:fn="http://java.sun.com/jsp/jstl/functions"
xmlns:icecore="http://www.icefaces.org/icefaces/core"
xmlns:ace="http://www.icefaces.org/icefaces/components"
xmlns:ice="http://www.icesoft.com/icefaces/component">
<h:head>
<title>ICEfaces</title>
</h:head>
<h:body>
</h:body>
</html>
Panel
El primer componente que se añade, dentro de un formulario, es el ace:panel,
que es un contenedor que ofrece una funcionalidad extendida sobre el PanelGrid de
JSF, permitiendo entre otras opciones ocultar el panel, incluir título en la barra de título,
minimizarlo, etc.
<ace:panel id="prueba_panel" header="Titulo ventana"
styleClass="capa_ventana" footer="pie ventana"
closable="true"
toggleable="true" toggleSpeed="250">
Como en JSF, cualquier propiedad puede tener un valor fijo o un valor variable,
asignado mediante una expresión dinámica. A continuación se le añade un outputText,
para que el panel tenga un contenido. Otra característica de los componentes de
IceFaces es que tienen eventos, dos en el caso de acePanel:
<h:outputText id="eti_prueba" value="Hola, texto para prueba de panel"
/>
<!-- EVENTOS DEL ACE:PANEL -->
<ace:ajax event="close"
listener="#{contenedor_bean.evento_CierrePanel}" render="@all"
/>
<ace:ajax event="toggle"
listener="#{contenedor_bean.evento_RepliegePanel}" render="@all"
/>
JSF P á g i n a | 39
Estos eventos se corresponden con las acciones por parte del usuario del cierre
de la ventana (evento close) o bien el repliegue de la ventana (evento toggle). Como se
puede observar, se hace uso de un managedBean denominado contenedor_bean, por lo
que es necesario declararlo en el faces-config.xml.
<managed-bean>
<managed-bean-name>contenedor_bean</managed-bean-name>
<managed-bean-
class>com.atrium.managedbean.Contenedores_Bean</managed- bean-class>
<managed-bean-scope>view</managed-bean-scope>
</managed-bean>
TabSet
A continuación se añade un nuevo panel contenedor, un panel de pestañas. Este
es un contenedor de contenedores y se define mediante la etiqueta <ace:tabSet>,
mientras que cada una de las pestañas viene definida por <ace:tabPane>.
<ace:tabSet id="prueba_panelpestañas" clientSide="true"
showEffect="slide" showEffectLength="1500"
tabChangeListener="#{contenedor_bean.evento_CambioPestaña}">
<ace:tabPane id="p1" label="Pestaña 1">
<h:outputText id="eti_p1" value="Contenido p1" />
</ace:tabPane>
<ace:tabPane id="p2" label="Pestaña 2">
<h:outputText id="eti_p2" value="Contenido p2" />
</ace:tabPane>
<!-- DEFINICION DEL EVENTO CUANDO SE TRABAJA EN EL CLIENTE -->
<ace:ajax event="clientSideTabChange" execute="@this"
listener="#{contenedor_bean.evento_CambioPestañaCliente}"
/>
</ace:tabSet>
JSF P á g i n a | 40
Acordeón
Este componente es una variante del tabSet, donde en función de la pestaña
escogida se extiende su contenido, siempre en columna (es especialmente utilizado en
aplicaciones móviles).
Para definirlo se hace uso de la etiqueta <ace:accordion>, incluyendo los
paneles internos mediante <ace:accordionPane>.
<ace:accordion id="prueba_acordeon"
paneChangeListener="#{contenedor_bean.evento_CambioAcordeon}">
<ace:accordionPane id="ac1" title="Acordeon 1">
<h:outputText id="eti_ac1" value="Contenido acordeon 1" />
</ace:accordionPane>
<ace:accordionPane id="ac2" title="Acordeon 2">
<h:outputText id="eti_ac2" value="Contenido acordeon 2" />
</ace:accordionPane>
</ace:accordion>
AceDialog
Este componente, de cara a lo que visualiza el cliente, es parecido al componente
Panel, con la salvedad de que puede comportarse como una ventana modal12. Por lo
tanto, es habitualmente empleada para mostrar mensajes de lectura obligada.
<ace:dialog id="prueba_ventanamodal" header="Ventana modal"
hideEffect="explode" showEffect="explode" modal="true"
position="center" visible="true" draggable="true">
<h:outputText id="modal" value="Contenido ventana mensajes" />
</ace:dialog>
Permite tener dos efectos diferentes, uno para el momento en el que se muestra y
otro para el momento en el que se oculta. Mediante la opción modal se convierte en una
ventana modal, con la opción draggable se permite al usuario arrastrar la ventana por la
12
Una ventana modal es una ventana emergente que bloquea el contenido de fondo mientras no
se cierre.
JSF P á g i n a | 42
public Contenedores_Bean() {
dialogo_visible = true;
}
.
.
.
//Evento de cierre de ventana modal
public void evento_CierreDialogo(CloseEvent evento) {
System.out.println("Soy el evento de cierre de la ventana
modal");
dialogo_visible = false;
}
NotificationPanel
Un panel de notificación es un panel emergente que, a diferencia del dialog, no
es movible y no es modal. A nivel de posicionamiento sólo puede estar situado en la
parte superior o inferior de la página. Se suele emplear para mostrar publicidad, aunque
como todo contenedor, puede ser empleado para mostrar cualquier tipo de contenido.
Como ocurre en el dialog, se puede indicar el tipo de efecto y la duración del mismo. Se
declara mediante la etiqueta <ace:notificationPanel>.
<ace:notificationPanel id="prueba_panelnotificaciones" visible="true"
position="bottom" effect="slide" effectSpeed="slow">
<h:outputText id="notificacion" value="Contenido panel
noticiacion."
title="texto tooltip texto panel notificacion" />
<!-- SUBCOMPONENTE DE CIERRE -->
<f:facet name="close">
<div class="ui-icon ui-icon-closethick"></div>
</f:facet>
<!-- EVENTOS DEL NOTIFICATION PANEL -->
<ace:ajax event="close" execute="@this" render="@form"
listener="#{contenedor_bean.evento_CerrarPanelNotificacion}" />
<ace:ajax event="display" execute="@this" render="@form"
listener="#{contenedor_bean.evento_MostrarPanelNotificacion}" />
</ace:notificationPanel>
<f:facet name="close">
<div class="ui-icon ui-icon-closethick"></div>
</f:facet>
Además, se declara en el atributo class el estilo (de IceFaces) para que el botón
tenga la forma de un botón de cierre. En cuanto al tratamiento de eventos, se tiene el
mismo problema que en casos anteriores, ya que el cierre del panel se produce en el
cliente. Por tanto, será necesario realizar una petición Ajax para actualizar el parámetro
en el servidor, tanto en el caso de que se cierre como en el caso de que se muestre.
En el managed bean será necesario crear una propiedad boolean denominada
notification_visible que en el constructor se inicialice a true, con sus respectivos
métodos accesores. También será necesario sustituir el atributo visible por una
expresión dinámica que tome el valor de la propiedad anteriormente mencionada, tal y
como se muestra a continuación.
<ace:notificationPanel id="prueba_panelnotificaciones"
visible="#{contenedor_bean.notification_visible}"
position="bottom"
effect="slide" effectSpeed="slow">
<h:outputText id="notificacion" value="Contenido panel
noticiacion."
title="texto tooltip texto panel notificacion" />
<!-- SUBCOMPONENTE DE CIERRE -->
<f:facet name="close">
<div class="ui-icon ui-icon-closethick"></div>
</f:facet>
<!-- EVENTOS DEL NOTIFICATION PANEL -->
<ace:ajax event="close" execute="@this" render="@form"
listener="#{contenedor_bean.evento_CerrarPanelNotificacion}" />
<ace:ajax event="display" execute="@this" render="@form"
listener="#{contenedor_bean.evento_MostrarPanelNotificacion}" />
</ace:notificationPanel>
Se deberán crear los métodos para atender a los eventos de cerrar el panel
(evento_CerrarPanelNotificacion) y de abrirlo (evento_MostrarPanelNotificacion).
Tooltip
Este componente permite que cuando se mantenga el ratón encima de un
componente durante un periodo de tiempo (por defecto dos segundos), se muestra un
panel superpuesto sobre el componente con el contenido deseado (por ejemplo un texto
de ayuda sobre el uso del componente). Para declararlo se emplea la etiqueta
<ace:tooltip>.
<ace:tooltip id="prueba_tooltip" for="eti_p1"
JSF P á g i n a | 45
speechBubble="true" position="topLeft">
<h:outputText id="texto_tooltip" value="Texto prueba tooltip" />
<!-- EVENTO DEL TOOLTIP -->
<ace:ajax event="display"
listener="#{contenedor_bean.evento_MostrarToolTip}" />
</ace:tooltip>
Menús
Para mostrar un ejemplo de los menús que proporciona IceFaces, se crea una
nueva página XHTML denominada ejemplo_menus.xhtml, incluyendo dentro de ésta un
formulario que será el que contenga los componentes de menú.
Los menús siempre están formados por dos partes: el contenedor que contiene la
estructura de los elementos y los propios elementos que son seleccionables por el
usuario. En otras palabras, existe un menú y un submenú.
Menu y MenuBar
El menú es un organizador en vertical, que se define mediante la etiqueta
<ace:menu>, siendo por contraposición el <ace:menuBar> un menú que se muestra en
horizontal. Para el caso del vertical, se muestra a modo de ejemplo el siguiente código:
<ace:menu id="menu_vertical">
<ace:submenu id="sub1" label="Submenu 1">
<ace:menuItem id="op11" value="Opcion 11"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op12" value="Opcion 12"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
</ace:submenu>
<ace:submenu id="sub2" label="Submenu 2">
<ace:menuItem id="op21" value="Opcion 21"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op22" value="Opcion 22"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
JSF P á g i n a | 46
13
El ActionEvent es de tipo javax.faces.event.ActionEvent, no se debe confundir on el de swing.
JSF P á g i n a | 47
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op12mc" value="Opcion 12"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
</ace:submenu>
</ace:menuColumn>
<ace:menuColumn id="segunda_columna">
<ace:submenu id="sub2mc" label="Submenu 2">
<ace:menuItem id="op21mc" value="Opcion 21"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
JSF P á g i n a | 48
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op23mc" value="Opcion 23"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
</ace:submenu>
</ace:menuColumn>
</ace:multiColumnSubmenu>
</ace:menuBar>
Como siempre, se hace uso de las peticiones AJAX para informar al servidor de
las opciones seleccionadas. Al igual que ocurre con los otros menús, dispone de una
propiedad denominada autoSubMenuDisplay que permite que los submenús se muestren
de forma automática al pasar el ratón por encima.
MenuButton
Es un menú muy parecido a los desplegables, con la salvedad de que para que se
muestre (si se emplea un submenú) se debe hacer click con el ratón encima del botón.
En el caso de no emplear submenús, al pinchar en el botón se genera un evento también
de tipo ActionEvent.
<ace:menuButton id="menu_boton" value="Menu boton">
<ace:menuItem id="op21mb" value="Opcion 21"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op22mb" value="Opcion 22"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
<ace:menuItem id="op23mb" value="Opcion 23"
actionListener="#{prueba_menu.evento_Menu}">
<ace:ajax event="activate" />
</ace:menuItem>
</ace:menuButton>
<h:form id="formu_seleccion">
<h:panelGrid columns="4">
<!-- COMPONENTES DE SELECCION UNICA -->
<h:selectBooleanCheckbox>
<!-- SE MUESTRA UN UNICO CHECKBOX A ELEGIR --
>
</h:selectBooleanCheckbox>
<h:selectOneListbox>
<!-- SE MUESTRAN MULTIPLES OPCIONES -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectOneListbox>
<h:selectOneRadio>
<!-- SE MUESTRAN MULTIPLES RADIO BUTTONS -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectOneRadio>
<h:selectOneMenu>
<!-- SE MUESTRA EL COMBO -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectOneMenu>
</h:panelGrid>
<h:panelGrid columns="3">
<!-- COMPONENTES DE SELECCION MULTIPLE -->
<h:selectManyMenu>
<!-- SE MUESTRA UN COMBO -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectManyMenu>
<h:selectManyCheckbox>
<!-- SE MUESTRAN MUCHOS CHECKBOX -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectManyCheckbox>
<h:selectManyListbox>
<!-- SE MUESTRA UNA LISTA -->
<!-- CONTENIDO ESTATICO -->
<f:selectItem />
<!-- CONTENIDO DINAMICO -->
<f:selectItems />
</h:selectManyListbox>
</h:panelGrid>
</h:form>
</h:body>
JSF 2.X.
Dentro del entorno tecnológico de JEE 7 la parte del servidor
Contenido.
❖ Servlet.
❖ Filtros.
❖ Escuchadores.
❖ Configuración de aplicaciones web.
❖ Nuevas APIs de JEE 6.