SlideShare a Scribd company logo
1 of 148
 Actualmente la mayoría de las aplicaciones
se distribuyen por Internet.
 Casi todos los accesos clientes se hacen a
través de Web.
 Cada vez hay mas clientes específicos con
dispositivos y pantallas diferentes.
 El modelo de programación Web actual está
basado en documentos no basados en
pantallas de interacción.
 JSF logra la unión entre los cliente Web actuales y el
modelo tradicional de componentes.
 Logra separar la renderización del componente.
 Logra desplazar la interacción del usuario con el
programa al modelo tradicional de eventos.
 JSF es la evolución estándar de Struts, por los
mismos que realizaron Struts.
 Es un estándar claro y potente para poder hacer
aplicaciones visuales mas potentes.
 Nos da Renderización, árbol de componentes
visuales, validadores, conversores y eventos y
javabeans.
 Nos aporta un ciclo de vida claro estándar.
 Nos permite configurar y definir externamente el
flujo de pantallas, la navegación.
 Nos permite modificar o incorporar componentes
básicos propios en la arquitectura.
◦ Por ejemplo un ciclo de vida propio
 Aporta tags para funcionar sobre jsps.
 Se podría usar JSF en otros entornos diferentes a
jsp.
 Tenemos una librería estándar de JSF-Html para
crear aplicaciones web.
 Nos da un nivel de información independiente de
estar en un contenedor web-servlets o un
contenedor basado en portlets.
 Retrasa la renderización hasta el último momento
para poder renderizar con toda la información bien
preparada.
 Nos permite crear componentes propios para
reutilizar.
 JSF tiene un Servlet como entrada de las llamadas a
su arquitectura.
 Se necesita configurar un servlet de JSF para
enlazar con el contenedor Web.
 Se basa en un fichero de configuración, por
defecto faces-config.xml
 ¿Qué gestionamos en el faces-config?
◦ Componentes (Edit/ Label/ ComboBox).
◦ Validadores.
◦ Conversores.
◦ Beans (Java Beans).
◦ Navegación
◦ Aspectos avanzados...
 Debemos registrar el servlet.
◦ javaxfaces.webapp.FacesServlet
 Tenemos que hacer el servlet-mapping de las
uris que vamos a tratar con JSF.
◦ Normalmente de tipo
 /facesl*
 *.faces
 *.jsf
 Se pueden configurar los siguientes parámetros
globales (context-param):
◦ javax.faces.CONFIG_FILES indicando una lista relativa a
nuestro contexto donde están los archivos de configuración
de JSF. Por defecto carga /WEB-lNF/faces-config.xml.
◦ javax.faces.DEFAULT_SUFFIX indica el sufijo por defecto de
recursos conteniendo componentes JSF, por defecto . jsp.
◦ javax.faces.LIFECYCLE_lD instancia de LifeCycle a usar por
JSF por defecto LifecycleFactory.DEFAULT_LIFECYCLE.
◦ javax.faces.STATE_SAVING_METHOD La localización donde
se va a guardar la información de estado:
 server o client.
 Por defecto server en el HttpSession
 La etiqueta principal es <faces-config>.
 Podemos tener mas de un archivo de
configuración.
 Podemos configurar:
◦ Java beans.
◦ Registrar validadores propios.
◦ Registrar conversores propios.
◦ Configurar reglas de navegación.
◦ Registrar Renders.
◦ Registrar componentes propios.
 Partimos de piloto 0.0, entorno de trabajo
basado en Maven2 y generado mediante el
arquetipo para MyFaces.
 Lo modificamos para que:
◦ Aparezca una nueva página welcome.jsp con un
mensaje de “Hola Mundo”
◦ Index.jsp redirija mediante
response.sendRedirect(...) a welcome.jsf ¿?
 Probamos la aplicación. ¿Qué ha ocurrido?
 Welcome.jsf no es aún una vista válida JSF.
 En JSF todas las vistas deben estar contenidas
en un elemento f:view:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<f:view>
...
</f:view>
 ¿Por qué? Encapsular la JSF en el componente
vista.
 Permite declarar los beans que van a ir
instanciando automáticamente y en el scope que
se van a a encontrar.
 Configurar propiedades de los beans.
 Poner el valor de una propiedad de un bean al
resultado de la evaluación de un método value-
binding.
 Scopes:
◦ request.
◦ Session.
◦ application.
◦ none.
 El bean es inicializado cada vez que es referenciada y no se
guarda en ningún scope.
<managed-bean>
<managed-bean-name>NA</managed-bean-name>
<managed-bean-class>model.ImageArea</managed -bean-
class>
<managed-bean-scope>application</managed-bean-
scope>
<managed-property>
<property-name>shape</property-name>
<value>poly</value>
</managed-property>
……………………..
…………………………
</managed-bean-name>
</managed-bean>
 Vamos a inyectar nuestro primer bean en JSF:
◦ En primer lugar, creamos la clase
es.uniovi.si.UsuarioBean con una propiedad nombre
◦ Lo declaramos en el faces-config.xml como bean
usuario, inicializando su propiedad nombre con la
cadena “Invitado”.
<managed-bean>
<managed-bean-name>usuario</managed-bean-name>
<managed-bean-class>es.uniovi.si.UsuarioBean</managed-bean-
class>
<managed-property>
<property-name>nombre</property-name>
<value>invitado</value>
</managed-property>
</managed-bean>
 Creamos una nueva vista entrada.jsp y, dentro,
mostramos la propiedad nombre del bean usuario
mediante el componente de salida:
Hola <h:outputText value="#{usuario.nombre}"/>,
bienvenido a mi sitio web.<br>
 Probar a acceder mediante piloto/entrada.jsf
¿Funciona?
 Acceder ahora mediante piloto/entrada.jsp ¿Y
ahora?
 Quitar ahora f:view y probar con entrada.jsf.
¿Funciona?
Resuelto en piloto 1.0.
 Realiza una acción al ser activado.
 Propiedades básicas:
◦ Action String o method-binding al método que
devuelve ese String. EL String es usado por el
NavigationHandier para determinar la pagina
siguiente de acceso.
◦ actionListener para escuchar los eventos de
acción
 Dos tipos de etiquetas básicas
◦ commanButton representa un botón
<h:commandButton ../>
◦ commandLink representa un elemento de acción en
formato link (con <a></a>) .
 La etiqueta ha de contener una etiqueta outputText
para representar donde el usuario clickea para generar
el evento
 Representa los campos de entrada.
 En el renderizador de Html tenemos varios tags
◦ inputHidden representa un campo hidden
◦ inputSecret representa a un campo password
◦ inputText
◦ inputTextArea
 Suelen tener asociados elementos en las siguientes
propiedades
◦ Converter Identifica el conversor de datos a utilizar.
◦ Validatos method-binding a la validación.
◦ valueChangeListener method-binding para escuchar los
cambios de valor
 Cuando apliquemos JSF, tenemos que
ceñirnos a sus reglas y utilizar sus etiquetas
en lugar de las etiquetas estándar HTML.
 Éstas implementan más lógica por detrás que
nosotros no vemos pero que nos ahorra
trabajo.
 Ejemplo de formulario en JSF:
<h:form>
<h:inputText value="#{usuario.login}"/>
<h:commandButton value="Login" action=“¿?"/>
</h:form>
 Editamos welcome.jsp y añadimos lo
siguiente:
<h:form>
<h:inputText value="#{usuario.nombre}"/>
<h:commandButton value="Enviar"
action=“entrada.jsf"/>
</h:form>
Accedemos a la aplicación y pulsamos el
botón... ¿Qué ocurre?
Examinamos el código fuente. ¿Adonde apunta
el formulario? ¿Por qué?
 En JSF, TODAS las peticiones van a la propia
página. Entonces. ¿Dónde está el truco?
 El servlet mapping hace que el controlador
caputure TODAS las peticiones que
concuerden con la extensión *.jsf
 Lo que debemos poner en el campo action de
un componente de comando (nótese que no
es a nivel de formulario) es la acción que se
desea disparar
 ¿Cómo se navega entonces? Estableciendo el
mapa de navegación en el controlador.
 Permite configurar cual será la siguiente pagina después de
pulsar un boton o link.
 Cada regla define como navegar desde una página hacia otro
conjunto de páginas.
 La siguiente pagina depende del método action sobre el que
se haya pinchado y la salida lógica que de la etiqueta
referenciada.
 Salidas típicas:
◦ success:
 todo ocurrió correctamente.
◦ Failure:
 hubo algo mal, ir a una página de error.
◦ Logon:
 el usuario necesita logearse primero, IR a pagina de logon
◦ No result:
 la búsqueda no encontró nada. Ir a la pagina de búsqueda de nuevo
 From-view-id
◦ Indica la página origen de la request.
 From-action
◦ indica el action del que procede y que da su valor.
 From-outcome
◦ Representa el evento que dispara la transición.
 To-view-id
◦ indica el id de la vista a la que pasamos
<navigation-rule>
<from-view-id>/logonjsp</from-view-id>
<navigation-case>
<from-action>#{LogonForm.logon}</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/storefrontjsp</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{LogonForm.logon}</from-action>
<from-outcome>failure</from-outcome>
<to-view-id>/logon.jsp</to-view-id>
</navigation-case>
</navigation-rue>
 Vamos a establecer una regla de navegación
en el faces-config.xml que determine que
cuando se dispara la acción login desde la
página welcome.jsp el controlador nos debe
redirigir a entrada.jsf:
<navigation-rule>
<from-view-id>/welcome.jsp</from-view-id>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/entrada.jsf</to-view-id>
</navigation-case>
</navigation-rule>
 Recordad modificar el formulario para que
ejecute la acción login. ¿Funciona?
 Problema: El bean aparece siempre con el
mismo valor. ¿Por qué?:
 El scope por defecto de los beans es page, y
nosotros no hemos establecido ninguno
diferente. Editar el faces-config.xml y forzar
que el bean-scope sea request.
 Volver a probar la aplicación.
Resuelto en piloto 2.0
 Con #{expresion languaje} podemos
referirnos a los métodos, propiedades y
elementos
<managed-bean>
<managed-bean-name>customer</managed-bean-name>
<managed-bean-class>CustomerBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>areaCode</property-name>
<value>#{initParam.defaultAreaCode}</value>
</managed-property>
…………….
</managed-bean>
 Es un Map de Collections, se puede especificar
la clase que hace de llave
<managed-bean>
<managed-property>
<property-name>prices</property-name>
<map-entries>
<map-entry>
<key>My Early Years: Growing Up *7</key>
<value>30.75</value>
</map-entry>
<map-entry>
<key>Web Servers for Fun and Profit</key>
<value>40.75</value>
</map-entry>
</map-entries>
</managed-property>
</managed-bean>
<managed-bean>
…….
<managed-property>
<property-name>books</property-name>
< list-entries >
<value-class>java.lang.String</value-class>
<value>Web Servers for Fun and Profit</value>
<value>#{myBooks. bookld [3]}</value>
<null-value/>
</ list-entries >
</managed-property>
</managed-bean>
 ¿Cómo hacemos que nuestras vistas
interactúen con el modelo?
 Sabemos como forzar a que JSF invoque un
método get o set sobre un bean, luego
¿Implementando lógica en los accessors? No,
sería desnaturalizar el método.
 Alternativa: Navegación dinámica
 En el ejemplo que hemos visto, el botón de
commando dispara una acción que, tal y como
hemos configurado, nos redirige de
terminantemente a otra vista.
 En las aplicaciones reales, la redirección dependerá
del resultado de la interacción con el modelo.
Ejemplo hago login y:
◦ Si es correcto, paso a la página de entrada
◦ Si no, vuelvo a la página de login y muestro un error.
 Para esto necesito:
◦ Elementos donde implementar la lógica decide la
navegación
◦ La posibilidad de establecer las diferentes transiciones en
base al resultado.
 Para implementar navegación dinámica,
debemos utilizar en el elemento de comando
que hace submit una expresión de método.
 Ejemplo:
<h:commandButton label="Login"
action="#{loginController.verifyUser}"/>
 En este caso, al pulsar el botón se invocará el
método verifyUser del bean dado de alta como
loginController.
 ¿Cómo se determina el destino tras ejecutar
un método de bean?
 Desde el bean:
if (...)
return "success";
else
return “login-error";
 El bean dispara acciones en base a las cuales
se determinará cual será la siguiente vista.
<navigation-rule>
<navigation-case>
<from-action>#{loginController.verifyUser}
</from-action>
<from-outcome>success</from-outcome>
<to-view-id>/consultaLibros.faces</to-view-id>
</navigation-case>
<navigation-case>
<from-action>#{loginController.verifyUser}
</from-action>
<from-outcome>login-error</from-outcome>
<to-view-id>/login.faces</to-view-id>
</navigation-case>
</navigation-rule>
 Vamos a implementar e inyectar un bean que
se encarge de nuestro futuro proceso de
login. Para eso:
◦ Añadimos una propiedad password al bean usuario
y completamos el formulario de la página welcome
para que se recoja la contraseña.
◦ Creamos es.uniovi.si.LoginAction tal que:
 Contenga una propiedad de tipo UsuarioBean
 Tenga un método login que:
 Si usuario=contraseña=admin entonces dispare “success”
 Si no, dispare login-error.
◦ Establecemos la navegación en el faces-config.xml
◦ ¿Funciona? ¿Qué ocurre?
<managed-bean>
<managed-bean-name>customer</managed-bean-name>
<managed-bean-class>com .mycompany.mybeans.CustomerBean</managed-bean-class>
<managed-bean-scope> request </managed-bean-scope>
<managed-property>
<property-name>mailingAddress</property-name>
<value>#{addressBean}</value>
</managed-property>
<managed-property>
<property-name>streetAddress</propertyname>
<value>#{addressBean}</value>
</managed-property>
<managed-property>
<property-name>custom erType</property-name>
<value>New</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>addressBean</managed-bean-name>
<managed-bean-class>com .mycompany.mybeans.AddressBean</managed-bean-class>
<managed-bean-scope> none </managed-bean-scope>
<managed-property>
<property-name>street</property-name>
<null-value/>
<managed-property>
</managed-bean>
 Inyectar el bean usuario en el bean
loginAction en el faces-config.xml
 Probar la aplicación.
Resuelto en piloto 3.0
 Modificar la versión anterior para añadir un
contador que, basándose en el contexto de la
aplicación, cuente cuantos logins se realizan
en la aplicación contando todos los de los
usuarios.
 ¿Desde donde lo hacemos? ¿En qué clase lo
inyectamos?
 Visualizar el resultado del contador en la
página final.
 Hasta ahora hemos visto y usado algunos de
los elementos que nos aporta JSF, como los
formularios, los comandos, etc.
 Los elementos de JSF se clasifican en:
◦ Componentes JSP
◦ Objetos Implícitos
 JSF basa sus vistas en un árbol de nodos visuales.
 Los nodos tienen asociados un renderizador que
crea su visualización.
 Entre llamada y llamada se recrea el árbol de
objetos en el lado servidor.
 Hay un conjunto estándar de componentes base.
 Tenemos una implementación de HTML que
implementa de diversa manera estos componentes
base.
 Vamos a ver los componentes base con su reflejo
sobre los componentes Html.
 Podemos usar el EL para asociar métodos y propiedades a los
elementos #{.. .}.
 Con el Expresion Languaje de JSF tenemos una serie de objetos
implícitos en el contenedor web estándar:
◦ applicationScope
◦ cookie
◦ facesContext
◦ header
◦ headerValues
◦ initParam.
◦ param
◦ paramValues
◦ requestScope
◦ sessionScope
◦ view
 Indica el UIComponent que es raíz del árbol para esta llamada
 Los componentes han de tener un
constructor vacío para poder instanciarse.
 Todo componente visual tiene una
representación como objeto en el servidor
en una jerarquía nodal.
 El renderizador se encargara de generar su
representación visual según convenga.
 El paquete visual principal es
javax.facescomponent.
 Todo elemento visual forma parte de un árbol
nodal de elementos.
 El elemento base de la jerarquía es UIComponent.
 El elemento funcional base que hereda de
UIComponent es UIComponentBase.
 El elemento raíz de un árbol es UIViewRoot.
 Todo componente debe especificar constantes
indicando el tipo bajo el cual el componente es
registrado y la familia para seleccionar el render
adecuado.
◦ COMPONENT_TYPE, Component_FAMILY
 Propiedades nodales
◦ getParent.
◦ getChildren.
◦ getChildrenCount.
◦ getViewNode
 Nos permite acceder al nodo principal del árbol
◦ Buscar componentes hijo.
◦ Cada componente tiene un Id, bien impuesto o
bien generado.
 Nos permite acceder al FacesContext al que
pertenece el componente.
 Todo componente pertenece a una familia y
un renderType, la conjunción de ambos
determina el render a utilizar.
 Casi cada componente UI va a tener una
etiqueta asociada.
◦ getAttibutes nos permite acceder a las
propiedades y atributos del componente
 Al crear componentes tenemos que implementar la
codificación y decodificación de la información.
 Decode:
◦ Leemos el dato del request y propagamos su valor.
 Encode:
◦ EncodeBegin
◦ EncodeChildren
◦ EncodeEnd
◦ Durante la fase de renderización los datos se pasan al lenguaje
de marcado.
◦ En caso de no necesitar tener en cuenta los componentes hijo
solo implementaremos en encodeEnd.
 Es el nodo raíz de un árbol de componentes
visuales.
 Nos permite poner el locale del árbol.
 Hereda de UIBaseComponent.
 Tiene asociado un RenderKit:
◦ Es una familia de renders.
◦ Cada render en el RenderKit esta designado por
tipo y familia que renderiza.
◦ Su etiqueta es f:view y su único atributo opcional
es locale
 Actualmente hay dos librerías de etiquetas
básicas:
<%@ taglib uri=http://java.sun.com/jsf/core prefix=”f” %>
<%@ taglib uri= uri=http://java.sun.com/jsf/html prefix=”h” %>
 Los componentes han de estar metidos dentro del un único
nodo raiz <f:view>
 Cuando se realiza un <jsp:import> o <c:include> todos
elementos incorporadas han de meterse en un <f: subview>
◦ <f:subview>
 <c:include ...>
◦ </f:subview>
 Cualquier texto de plantilla incluido por el include o el import,
actualmente debe meterse dentro de una etiqueta <f:
verbatim>
 Cada elemento va a tener los atributos del componente mas los
añadidos por el render.
◦ Con el render de HTML podemos ver que el Componente UIData
tiene una implementaron (por extensión) HTMLDataTable que
contiene los atributos configurables relativos a Html y específicos
del Render
 Propiedades usuales:
◦ Id del componente, si no se lo ponemos es generado
automáticamente.
◦ lmmediate: si esta a true indica que los eventos, validaciones
y conversiones se realizan en la fase de apply request en vez
de en una fase posterior.
◦ Rendered indica si el componente ha de ser renderizado.
◦ Style especifica el cascading style sheet para la etiqueta.
◦ styleClass especifica el class del CSS (cascading style sheet).
◦ Value indica el valor del componente, como literal o enlazado
con una propiedad del modelo de información.
◦ Binding identifica una propiedad de un bean y asocia la
instancia UI del componente a esa propiedad (set.. .(UI.. A)).
◦ Todos los atributos excepto id y var permiten la asociación
de value-binding con el Expresion Lenguaje de Java Server
Faces.
 #{objeto.propiedad}
 Representa un form de entrada.
 Engloba a todos los componentes que
muestran o recogen información.
◦ <h:form>. ..</h:form>
 Representa una tabla de información.
 <h:dataTable..>...
 Tiene UIColumns dentro.
 Soporta estar enlazado con una colección
de objetos sobre la que itera.
 El atributo value indica la colección sobre la
que iterar.
 El atributo var indica la variable sobre la
que se va a ir guardando el objeto de datos
en cada iteración.
 Tipos de datos soportados:
◦ Listas y arrays de beans.
◦ Una sóla bean.
◦ Un javax.sql.ResultSet y
javax.servlet.jsp.jstl.sql.ResultSet.
◦ javax.sql.RowSet.
◦ Javaxfaces.model.DataModel
 Todos los tipos de datos soportados tienen
un Wrapper a DataModel, la implementación
encapsula nuestro objeto en el wrapper
correspondiente.
 First indica la primera fila a ser mostrada.
 Rows indica el número de filas a mostrar.
 Existen varias propiedades que pueden indicar
listas de estilos para los diferentes elementos:
◦ columnClasses
◦ footerClass
◦ headerClass
◦ rowClass
◦ StyleClass
 Representa una columna de información en un
UIData
 Cada columna puede tener uno o varios facet que
indicarían las cabeceras y pies de las columnas
◦ Si se quiere poner mas de un componente dentro de una
facet se ha de usar un panelgroup para embeberlos ya que
facet solo soporta tener un componente hijo.
◦ Un facet se usa para representar un componente que es
independiente de la relación padre-hijo en el árbol de
elementos.
◦ En el caso de las columnas las cabeceras y pies sólo se
pintan una vez, no en cada bucle.
 <h:column>
<h:dataTable value="#{gestionLibrosService.libros}"
var="libro">
<h:column>
<f:facet name="header">
<h:outputText value="Título" />
</f:facet>
<h:outputText value="#{libro.titulo}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Autor" />
</f:facet>
<h:outputText value="#{libro.autor}"/>
...
</h:dataTable>
 Modificar la versión 3.0 del piloto y:
◦ Crear una clase LibroBean con las propiedades
autor, título, descripción y precio.
◦ Crear una clase Libreria que contenga un Vector de
LibroBeans almacenados en una propiedad catalogo
◦ Declarar una librería con al menos 3 libros
diferentes y denominarla liberia
◦ Modificar la página entrada.jsp para que muestre el
catálogo de la librería usando un tag h:dataTable.
¿Qué scope tendrán que tener los libros? ¿Y la
librería?
Resuelto en piloto 4.0
 Cada llamada que lleva a un JSF tree pasa por una
serie de fases determinadas que crean su ciclo de
vida.
 Existen tres tipos de escenarios posibles:
◦ Una petición sin JSF genera una respuesta con JSF.
◦ Una petición con JSF genera un respuesta con JSF.
◦ Una petición con JSF genera una respuesta sin JSF.
 A su vez la aplicación también puede recibir
peticiones sin JSF que generen respuestas sin JSF
 Toda llamada o request tiene asociado un
FaceContext y al hilo de llamada.
 El FaceContext solo debe existir durante la request
hasta que se llame a su método release.
 No se le debe referenciar por un objeto que tenga
una vida mas larga que la request .
 Contiene toda la información relativa al estado en
la request y la renderización de la respuesta.
 Encapsula el elemento raíz visual ViewRoot.
 Encapsula los posibles mensajes.
 Nos permite acceder al Singleton de Application.
 Encapsula ResponseWriter -salida de cáracteres- y
ResponseStream —salida binaria-. Como flujos de
escritura para los renderizadores.
 Nos permite acceder a ExternalContext:
◦ Nos da acceso al entorno independientemente de estar en
un contenedor de servlets o de portlets.
◦ Accedemos a todo el entorno de información que
tendríamos como servlet.
 El servidor recibe una llamada y recompone los objetos de la
vista en el servidor.
 Examina si FacesContext tiene un UIViewRoot en caso de
tenerlo:
◦ Le asigna el locale correspondiente (internacionalización).
◦ Para cada valor en el árbol mira si tiene un valuebinding
asociado a binding y si lo tiene llama a setValue() pasando la
instancia en donde se encontró.
◦ No se realizan mas acciones.
 Se crea el viewID de la URI y de los valores de prefijo:
◦ ViewHandler.DEFAULT_SUFFIX_NAME
 Llaman a viewHandler.restoreView() pasando la
instancia FacesContext asociada a la llamada y el
viewID, consiguiendo el UIViewRoot como
respuesta:
◦ En caso de devolver null no había vista asociada por lo que
se crea una y se pasa al renderResponse:
 se llama a ViewHandler.createView() y a
FacesContext .renderResponse()
◦ Si la petición no contiene parámetros de llamada ni datos
en POST se llama a renderResponse
 Se almacena el UIViewRoot en el
FacesContext.
 Se determina el valuebinding para cada
atributo binding y se llama al setValue.
 Al final de esta fase tenemos recuperado el
viewRoot que había y si acaso se ha creado
uno nuevo.
 Da la oportunidad a los componentes a
actualizar sus valores a los valores que
llegan de la request.
 Se llama al método processDecodes() de
todos los componentes del árbol
UIViewRoot.
 Los componentes que implementan
ActionSource que reconocen que fueron
activados encolan su evento.
◦ Estos eventos son notificados al final de esta fase
 Los componentes que implementan
EditableValueHolder que tienen la
propiedad immediate a true realizan la
conversión y validación. lncluyendo el
potencial lanzamiento del evento
ValueChange.
◦ Normalmente immediate esta a false esto ocurre
posteriormente en la fase de Process Validations
 Todo error producirá un mensaje que se encolara
en el FaceContext, y el componente que la lanza
será marcado como invalido.
 En cualquier momento si nuestra lógica en los
decode, o en los eventos llama a
responseComplete en FacesContext. Se termina
inmediatamente el procesado del request.
 Si se llama a renderResponse en el FacesContext se
transfiere el control a la fase de Render Response.
 En caso contrario pasamos a la fase de Process
Validations
 Se procesan las validaciones llamando a
processValidators.
 Cualquier fallo en la validación mete un
mensaje de error en el FacesContext.
◦ Y la propiedad valid del componente se pone a
false.
 En cualquier validador puede llamar a
responseComplete o a renderResponse de
FacesContext.
 Llegados a esta fase se asume que los contenidos
son sintácticamente y semánticamente correctos.
 Se asume que el valor local de los componentes ha
sido actualizado.
 Es el momento de actualizar los datos del modelo
de la aplicación.
 Esto se produce recursivamente llamando a
UlComponent.processUpdates.
 La actualización dentro de un componente se
realiza llamando al método updateModel.
 Durante la actualización los eventos son
encolados hasta la finalización de la fase
donde se procesan.
 Al finalizar esta fase los valores del modelo
de datos han sido actualizados y los valores
de los componentes han sido vaciados.
 Cualquiera de nuestros métodos podría
llamar a responseComplete o a
renderResponse.
 Si se alcanza esta fase se asume que la
actualización del modelo ha sido
completada.
 Se llama al método processApplication de
UIViewRoot.
 Se llama a todos los eventos encolados con
phaseId.INVOKE_APPLICATION.
 Excepcionalmente se podría llegar a
cambiar el actionListener por defecto con
setActionListener
 Hace que la respuesta sea renderizada al cliente.
 Hace que el estado de la respuesta sea guardado
para ser procesado en llamadas sucesivas.
 Cuando un componente de árbol es seleccionado
para renderizarse se llama a su método de
encodexxx().
 Para los elementos que implementan ValueHolder
se ha de producir su conversión.
 Antes de completarse el estado de la vista ha de
ser guardado usando los métodos de la clase
StateManager.
◦ Esta información ha de estar disponible para que Restore
View pueda acceder a ella en sucesivas llamadas.
 Son beans que no responden a entidades,
sino a agrupaciones que datos que por
motivos prácticos, nos puede interesar
procesar juntos, a nivel no de valores sino de
componentes.
 Es imprescindible para validaciones en las
que se han de comprobar relaciones entre
componentes.
 Ejemplo: Representación de formularios
 Si queremos hacer un backing bean para un
formulario de cambio de usuario en sesión que
muestra y recibe información al mismo tiempo, por
ejemplo:
Public class ChangeSessionForm
{
UIInput newUser;
UIOutput oldUser;
//getters and setters...
}
...
En la JSP:
<h:outputText binding="#{changeSessionForm.oldUser}"/>
Lo que le pasa JSF al formulario al hacer binding no
es el valor del componente, sino su referencia.
 Vamos a alterar el proceso de login para
utilizar es.uniovi.si.backing.LoginForm como
backing bean. Para ello:
◦ Declaramos dos propiedades UIInput (login y
password)
◦ Declaramos el bean como loginForm y se lo
inyectamos al LoginAction
◦ Hacemos el enlazado entre los campos del
formulario y modificamos adecuadamente la clase
LoginAction para que partir de ahora recupere los
valores del formulario.
Resuelto en piloto 5.0
 Los elementos de formulario que muestran
elementos entre los que seleccionar (combo,
radio, listas, etc) comparten modo de
funcionamiento.
 La entrada de datos debe ser una colección
de elementos SelectItem.
 Ej:
◦ New SelectItem(“010”,”The Matrix”);
 ¿Cómo se conecta con el formulario?
 Etiqueta h:selectBooleanCheckbox
 Representa un estado booleano
 Tres renderizaciones básicas
◦ selectManycheckbox
 Muestra una lista de checkboxes
 Value indica el set de elementos seleccionados
actualmente.
 Layout indica como se han de poner los checkbox
pageDirection/lineDirection.
 Contiene etiquetas selectItem o selectItems
representando a los elementos.
◦ selectManyListBox
◦ selectManyMenu
 Permite seleccionar solo un elemento:
◦ selectOneRadio
◦ selectOneMenu
◦ selectOneListbox
 Su contenido son colecciones de Selectltem o
Selectltems
 Nos permiten anidar elementos en los select
 f:SelectItem
 Un UISelectItems representa a una colección de
SelectItem o de SelectItemGroup.
 SelectItems permite tomar los datos de Arrays, Map
y Collection de elementos tipo SelectItem o
SelectItemGroup
◦ Javax.faces.modelSelectItem.
◦ Todo Item tiene un Label y un value.
 Ej: para cargar un combo...
◦ Bean pruebaForm:
Private UIInput propiedadDestino;
public Collection getOpciones()
{
opciones = new ArrayList();
opciones SelectItem(“01”,“Opción 1"));
opciones SelectItem(“02",“Opción 2"));
return opciones;
}
◦ En la jsp:
<h:selectOneMenu binding="#{pruebaForm.propiedadDestino}">
<f:selectItems value="#{pruebaForm.opciones}"/>
</h:selectOneMenu>
 Vamos a añadir al formulario de login un
combo con el idioma preferido por el usuario.
Para ello:
◦ Añadimos una propiedad idioma de tipo IUInput al
LoginForm, y un método getIdiomas que retorne
una colección de SelectItems con:
 “es”,”Español”
 “en”,”English”
◦ Lo enlazamos y mostramos lo recibido en el
LoginForm al pulsar el botón.
(Resuelto en piloto 6.0)
 Completar piloto 6.0 para:
◦ Añadir un formulario en entrada.jsp con:
 Un combo donde se muestre la lista de libros
 Un editBox donde se introduzca la cantidad del libro
seleccionado
◦ Un backing bean CarritoForm con un método add
para gestionar el carrito de la compra
◦ Un CarritoBean que resida en sesión y que
encapsule una HashMap. Tendrá que tener un
método public List<Entry> getProductos() que
retorne una lista de objetos entry obtenidos
mediante el método entrySet de la HashMap.
◦ Una página vercarrito que muestre el estado del
carrito de la compra mediante una tabla, con un
enlace a la página anterior:
<h:form>
<h:commandLink action="success">Volver</h:commandLink>
</h:form>
Resuelto en piloto 7.0
En cualquier aplicación es conveniente evitar tener las cadenas
de texto hardcodeadas en el código fuente de las pantallas o
páginas.
Los resource bundles sirven para seleccionar el mensaje de
error en función de la clave, buscándolo en los resource
bundle cargados. En el faces-config:
<application>
<resource-bundle>
<base-name>messages</base-name>
<var>msgs</var>
</resource-bundle>
</application>
Luego los referenciamos mediante EL. Ejemplo:
<h:outputText value="#{msgs.welcome}"/>
El fichero messages.properties:
welcome=Benvenido a mi página web!!!!
 Sobre piloto 7.0...
 Creamos messages.properties.
 Lo configuramos como fichero de recursos
con el prefijo msgs.
 Extraer los mensajes de al menos una de las
vistas, por ejemplo, welcome.jsp.
 Probar la aplicación.
Resuelto en piloto 8.0
 JSF aprovecha la externalización de cadenas de
texto para implementar la internacionalización de
etiquetas.
 En la request viaja el idioma preferido del
navegador, representado por el parámetro LOCALE.
 El locale responde a un código estandarizado
(es,en,fr, etc).
 Para internacionalizar la aplicación: un fichero de
recursos por locale:
◦ messages.properties
◦ Messages_en.properties
◦ Messages_fr.properties
◦ ...
 Internacionalizar la aplicación para el inglés.
Para ello:
◦ Creamos un fichero messages_en.properties
copiando el messages.properties.
◦ Traducimos las cadenas de texto al inglés
◦ Para probarlo, establecemos en el navegador el
inglés como idioma por defecto.
 Actualmente se recomienda que el usuario
pueda seleccionar explícitamente el idioma
por encima de lo que diga el parámetro de
idioma preferido del navegador.
 JSF permite establecer el locale de varias
formas diferentes:
1. Estableciéndolo directamente en el faces-
config.xml, el criterio idioma del navegador
prevalece sobre ésto.:
<faces-config>
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>de</supported-locale>
</locale-config>
</application>
</faces-config>
2. Establecerlo como parámetro de la etiqueta
f:view:
<f:view locale="de">
Ventaja, podemos establecerlo dinámicamente
<f:view locale="#{user.locale}"/>
3. Establecerlo por programa
UIViewRoot object:
UIViewRoot viewRoot =
FacesContext.getCurrentInstance().getViewRoot();
viewRoot.setLocale(new Locale("de"));
 Modificar la aplicación para que el criterio del
idioma que estamos seleccionando al hacer
login cambie el locale de la aplicación.
 Para verlo reflejado, internacionalizar alguna
de las páginas posteriores al proceso de
login.
 ¿Dónde recogemos el locale?
Resuelto en piloto 9.0
 JSF aporta una colección de conversores
predefinidos para tipos de datos estádar.
 Converter es el interfaz capaz de hacer
transformaciones string-objeto y objeto-string.
◦ public java.langObject
getAsObject(javax.faces.context.FacesContext context,
javax.faces.com ponent. UlComponent component,
java.lang.String value)
◦ public java.Iang.String
getAsString(javax.faces.context. FacesContext context,
javax.faces.component. UlComponent component,
java.lang.Object value)
 Podemos asociar un conversor a un lnput/Output.
 El atributo converter indica la clase java que
implementa ese interface.
 También se puede anidar dentro de una etiqueta
con f:converter.
◦ Su atributo converteride indica el id del conversor a usar.
 Tenemos conversores automáticos para los
tipos básicos:
◦ BigDecimalConverter
◦ BigIntegerConverter
◦ ByteConverter
◦ CharacterConverter
◦ DateTimeConverter
◦ DoubleConverter
◦ FloatConverter
◦ IntegerConverter
◦ LongConverter
◦ NumberConverter
◦ ShortConverter
 f:dateTimeConverter permite hacer conversiones de
fecha:
◦ datestyle: indica el formato: default, short, medium, long y
full.
◦ locale: indica el Locale, por defecto FacesContext.getLocale.
◦ pattern: indica el patrón de fecha (dd/MM/yy por ejemplo)
◦ timeStyle: define el formato de hora
◦ timeZone:
◦ type: indica si el string va a contener una fecha, hora o
ambos
 F:numberConverter permite controlar
conversiones de numero
◦ currencyCode, currencySymbol, pattern, locale,
minIntegerDigits, maxIntegerDigits,
minFractionDigits, maxFractionDigits.
◦ groupingUsed: boolean indica si la cadena de
salida tiene separadores de agrupamiento.
◦ integerOnly: boolean indica si se va a parsear la
parte entera del valor.
◦ Type: indica si el valor a parsear y formatear es
número, moneda o porcentaje
 El funcionamiento cuando hay un conversor
es el siguiente:
◦ El usuario envía los datos
◦ Se vuelvan al árbol de componentes
◦ Se invocan los conversores
◦ En caso de error,
 Se añaden los mensajes de error a la lista global de
mensajes
 Se vuelve a mostrar la página original y, en caso de
que exista una etiqueta h:messages, se muestran los
errores.
 Ejemplos:
<h:outputText value="#{payment.date}">
<f:convertDateTime/>
</h:outputText>
<h:outputText value="#{payment.amount}">
<f:convertNumber type="currency"/>
</h:outputText>
<h:inputText value="#{payment.amount}">
<f:convertNumber minFractionDigits="2"/>
</h:inputText>
 ¿Cómo muestro los errores de
conversión/validación?
Si quiero mostrarlos todos juntos:
<h:messages/>
Si quiero mostrar los específicos de un campo:
<h:inputText id=“unidades" label=“Unidades"
binding="#{bean.unidades}">
<f:convertNumber integerOnly="true"/>
</h:inputText>
<h:message for=“unidades"/>
 Basarse en el ejemplo anterior para aplicar un
conversor para la cantidad de productos que
se añaden al carrito y mostrar los errores
asociados al cambo justo debajo del mismo.
 Probarlo metiendo caracteres en el campo.
¿Funciona? ¿Cómo sale el mensaje?
Resuelto en piloto 10.0.
 Lo habitual será personalizar los mensajes de
error que disparan los validadores, entre
otras cosas, para internacionalizar la
aplicación
 Para ello, en los message-bundles
sobrescribimos los mensajes predefinidos
haciendo referencia a los códigos de
identificación de cada mensaje.
 Ejemplo:
Código mensaje
javax.faces.converter.Integer
Converter. INTEGER
{2}: "{0}" must be a number
consisting of one or more
digits.
javax.faces.converter.Integer
Converter.INTEGER_detail
{2}: "{0}" must be a number
between -2147483648 and
2147483647. Example: {1}
javax.faces.converter.DoubleC
onverter.DOUBLE
{2}: "{0}" must be a number
consisting of one or more
digits.
javax.faces.converter.DoubleC
onverter.DOUBLE_detail
{2}: "{0}" must be a number
between 4.9E-324 and
1.7976931348623157E308.Exampl
e: {1}
javax.faces.converter.Boolean
Converter.BOOLEAN_detail
{1}: "{0}" must be 'true' or
'false'. Any value other than
'true' will evaluate to
 JSF permite validar el contenido de
diferentes datos.
 Podemos usar el atributo validator para
apuntar al método de una bean que realiza
validación.
 Los validadores se pueden registrar en las
clases que implementan
EditableValueHolder.
 En caso de no cumplirse la validación han
de lanzar ValidatorException coteniendo un
FacesMassage con el error.
 La clase DoubleRangeValidator con tag
f:validateDoubleRange:
◦ Valida un valor que puede ser convertido a coma flotante.
◦ Mira que este entre dos valores dados, minimum-
maximum.
 La clase LengthValidator con tag f:validateLength.
 Mira que la longitud de la cadena este entre un mínimo y un
máximo
 La clase LongRangeValidator con tag
f:validateLongRange
 Para valores que se puedan convertir a long.
 Mira que este entre dos valores dados.
 Parámetros:
 Para comprobar que un dato está presente,
no hace falta ningún validador anidado, basta
con establecer el atributo required a true.
<h:inputText id="card" value="#{payment.card}"
required="true”requiredMessage="#{msgs.campoRequerido}">
<f:validateLength minimum="13"/>
</h:inputText>
Taller práctico
Modificar el piloto anterior para que además se
requiera el campo cantidad.
 Modificar la welcome.jsp para que:
◦ Los campos login y password sean obligatorios.
◦ La password tenga al menos 3 caracteres
◦ Se visualicen mensajes personalizados e
internacionalizados.
 Resuelto en piloto11.0
 A partir del piloto anterior:
◦ Definir un bean Usuarios (y declararlo como usuario) que
contenga un ArrayList con un UsuarioBean por cada usuario
que queramos en la aplicación.
◦ Modificar el proceso de login para que el proceso se realice
contra los usuarios del bean Usuarios.
◦ Crear una página registro.jsp y un backingbean
RegistroForm con un método registro que reciba login y
password y añada el nuevo usuario al bean usuarios.
◦ Enlazar desde welcome.jsp a registro.jsp con:
<h:outputLink value="registro.jsf">
<f:verbatim>Nuevo usuario</f:verbatim>
</h:outputLink>
Resuelto en piloto 12.0
 En entornos de desarrollo de tipo
cliente/servidor estamos acostumbrados a
poder asociar eventos de tipo onClick o
onChange a los componentes visuales de la
pantalla.
 En Web, dado que trabajamos sobre Http...
¿Se puede hacer esto?
 JSF, al igual que otras plataformas como .NET
simula esto encapsulando el evento en una
request que es enviada al servidor sin llegar a
disparar la acción del formulario.
 JSF soporta tres tipos de eventos:
◦ Value change events
 Disparados por elementos UIInput cuando el valor que
contienen cambia.
◦ Action events
 Los disparan los elementos UICommand cuando el
botón o enlace asociado es activado.
◦ Phase Events
 Son disparados rutinariamente por el ciclo de vida JSF.
 Pensados para elementos dependientes en los
formularios. Ej: Combo de paises + combo
provincias.
<h:selectOneMenu value="#{form.country}" onchange="submit()"
valueChangeListener="#{form.countryChanged}">
<f:selectItems value="#{form.countryNames}"/>
</h:selectOneMenu>
 Esto dispara el método form.countryNames que se
espera recibir un evento...
public void countryChanged(ValueChangeEvent event) {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(new Locale( (String)
event.getNewValue()));
}
Método Descripción
UIComponent
getComponent()
Retorna una referencia al objeto que
disparó el evento.
Object getNewValue() Retorna el nuevo valor
Object getOldValue() Retorna el valor antiguo
Los heredados de FacesEvent...
void queue() Encola el evento para que sea disparado
al final del ciclo de vida actual
PhaseId getPhaseId() Devuelve el id de la fase en la que nos
encontramos.
void setPhaseId(PhaseId) Marca el evento con el identificador de
la fase en la que fue añadido a la cola.
 Modificar el piloto para que el combo del
idioma que se muestra en la página welcome
tenga asociado un manejador de evento
idiomaCambiado en loginForm de forma que
cambie el idioma de la aplicación. Para ello:
◦ Asociamos el evento al componente y al manejador
de evento en la jsp.
◦ Implementamos el manejador en loginForm de
forma que establezca el nuevo idioma obteniendo
la referencia al ViewRoot por medio de FacesConfig.
Resuelto en piloto 13.0
 Modificar entrada.jsp para que cuando
cambie el combo del formulario, a su derecha
se muestre el valor del libro seleccionado.
 Para ello:
◦ Asociamos el evento onValueChange a un método
productoSeleccionado del CarritoForm
◦ Creamos un objeto UIOutput en la jsp que tome el
valor de un campo de tipo Integer del CarritoForm.
Resuelto en piloto 14.0
 Son disparados por los objetos UICommand
cuando se activa el componente
 Se invocan durante la fase Invoke Application
<h:commandLink actionListener="#{bean.linkActivated}">
...
</h:commandLink>
 Cuando se activa el componente, el
formulario se envía y el controlador dispara
los eventos.
 Entonces... ¿En qué se diferencian de los
actions?
 Actions:
◦ Diseñados para la lógica de negocio.
◦ Deciden sobre la navegabilidad del sistema
 Action listeners:
◦ Orientados a ejecutar lógica de presentación.
◦ No pueden decidir qué mensaje se envía al controlador.
 Los dos tipos de elementos trabajan
coordinadamente cuando el Action requiere
información del interfaz de usuario.
 Ejemplo: Una imagen enlazada que dependiendo de
la zona pulsada, generará una redirección u otra.
 Enlace en la JSP:
<h:commandButton image="mountrushmore.jpg"
actionListener="#{rushmore.listen}"
action="#{rushmore.act}"/>
En el backing bean...
private String outcome;
private Rectangle washingtonRect = new Rectangle(70,30,40,40);
private Rectangle jeffersonRect = new Rectangle(115,45,40,40);
public void listen(ActionEvent e) {
FacesContext context = FacesContext.getCurrentInstance();
String clientId = e.getComponent().getClientId(context);
Map requestParams = context.getExternalContext().getRequestParameterMap();
int x = new Integer((String) requestParams.get(clientId + ".x")).intValue();
int y = new Integer((String) requestParams.get(clientId + ".y")).intValue();
outcome = null;
if (washingtonRect.contains(new Point(x,y)))
outcome = "washington";
...
public String act()
{
return outcome;
}
 En primer lugar, creamos un nuevo método
public void listen(ActionEvent e) en el
CarritoForm que muestre un mensaje por
pantalla demostrando que ha sido invocado.
 Lo asociamos al botón de submit del
formulario de la página entrada.jsp.
¿Cuál se dispara primero?
 Extender la versión anterior para:
◦ Desligar al botón de submit del listener
◦ Crear un enlace activo (h:commandLink) que:
 no tenga atributo action
 Esté asociado al listener que hemos creado
 Se represente con la cadena de texto Incrementa
◦ Modificar el método listen para que cada vez que se
ejecuta, además de mostrar el mensaje:
 Tome el string del UIInput cantidad
 Cree un entero y le sume uno
 Estableza de nuevo el valor calculado en el
componente cantidad.
Resuelto en piloto 15.0
 Hasta ahora hemos asociado los listeners por
medio de los atributos de los elementos
HTML.
 Esto mismo se puede realizar utilizando dos
etiquetas:
◦ f:actionListener
◦ f:valueChangeListener
 Ventajas sobre la alternativa anterior: Puede
asociar varios listeners diferentes al mismo
elemento.
 Diferencias en la aplicación:
◦ Versión con el atributo
<h:selectOneMenu value="#{form.country}" onchange="submit()"
valueChangeListener="#{form.countryChanged}">
<f:selectItems value="#{form.countryNames}"/>
</h:selectOneMenu>
◦ Versión con f:valueChangeListener:
<h:selectOneMenu value="#{form.country}" onchange="submit()">
<f:valueChangeListener type="com.corejsf.CountryListener"/>
<f:selectItems value="#{form.countryNames}"/>
</h:selectOneMenu>
No es una method
expression sino una
clase!
 La clase listener para los eventos de cambio
de valor tiene que implementar una
determinada interfaz: ValueChangeListener
public class CountryListener implements ValueChangeListener {
public void processValueChange(ValueChangeEvent event)
{
...
}
}
 El controlador invoca el método
processValueChange tras cada cambio.
 Similar a la anterior:
<f:actionListener type=" com.corejsf. RushmoreListener "/>
 Y la clase, implementando la interfaz
ActionListener:
public class RushmoreListener implements ActionListener {
public void processAction(ValueChangeEvent event)
{
...
}
}
 Crear una clase LibroCambiadoListener que
implemente la interfaz ValueChangeListener
 Implementar su método processValueChange
para que saque un mensaje.
 Asociarla a la etiqueta del combo de la págin
entrada.jsp. Ojo! Hay que quitar el atributo
que la liga al otro listener, son dos
alternativas incompatibles!
Resuelto en piloto 16.0
 Problema: En casos como el combo de
cambio de idioma, se nos están disparando
los validadores que conviven dentro del
mismo formulario. ¿Porqué?
Se disparan los
validadores y
conversores
Se procesan los
eventos
 Si marcamos un componente como
inmediato:
<h:selectOneMenu binding="#{loginForm.idioma}" onchange="submit()”
valueChangeListener="#{loginAction.idiomaCambiado}" immediate="true">
 Problema:
◦ El ciclo de vida sigue si rumbo normal tras la validación y
procesado de eventos de los componentes inmediatos
 Solución:
◦ Cortamos el flujo desde el listener y forzamos la renderización de
la respuesta (el atajo en el gráfico anterior)
context.renderResponse();
Taller práctico
 Hacerlo sobre la versión actual del piloto para el cambio de
idioma en el login
¿Comandos inmediatos?
 En el caso de los comandos, también podemos hacerlos
inmediatos, pero no hacer falta forzar el renderizado porque
al terminar van directos a dicha fase.
 Supongamos que queremos hacer la
internacionalización con dos banderas, una por
idioma, haciendo que ambas sean commandLinks:
<h:commandLink action="#{localeChanger.englishAction}" immediate="true">
<h:graphicImage value="/british_flag.gif"/>
</h:commandLink>
 En el servidor:
public class ChangeLocaleBean {
public String germanAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(Locale.GERMAN);
return null;
}
public String englishAction() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(Locale.ENGLISH);
return null;
}
}
 Problema:
◦ Estamos definiendo métodos que son
prácticamente iguales –repetimos lógica- y que en
orientación a objetos podría ser uno solo
parametrizado.
 Solución:
◦ Envío de información desde la interfaz al usuario.
◦ Métodos:
 f:param
 f:setPropertyActionListener
 f:attribute
 Nos permite adjuntarle un parámetro a un
componente.
 Se comporta diferentemente dependiendo del
tipo de componente:
◦ Si lo usamos en un h:outputText, los distintos
parámetros se usan para rellenar las variables ({0} is
bigger than{1}) que se encuentren en el valor del
componente.
◦ Si lo usamos en un UICommand, los parámetros se
añaden como un parámetro de la request.
 Para el ejemplo anterior:
<h:commandLink immediate="true” action="#{localeChanger.changeLocale}">
<f:param name="languageCode" value="de"/>
<h:graphicImage value="/german_flag.gif" style="border: 0px"/>
</h:commandLink>
 En el servidor:
public String changeLocale() {
FacesContext context = FacesContext.getCurrentInstance();
String languageCode = getLanguageCode(context);
context.getViewRoot().setLocale(new Locale(languageCode));
return null;
}
private String getLanguageCode(FacesContext context) {
Map<String,String> params=context.getExternalContext().getRequestParameterMap();
return params.get("languageCode");
}
 Crear en LoginForm un nuevo método
idiomaCambiado() que recupere el parámetro
nuevoIdioma de la request y establezca el
nuevo Locale
 Añadir dos etiquetas de comando, una por
idioma, a la entrada.jsp, estableciendo como
atributo action (no actionListener!) e
inmediato = true;
Resuelto en trabajo 17.0
 Similar, pero en lugar de añadirlo a la request, se
añade como atributo al componente, por lo que
tenemos que usar action listeners (reciben el
componente en el evento!)
<h:commandLink immediate="true” actionListener="#{localeChanger.changeLocale}">
<f:attribute name="languageCode" value="de"/>
<h:graphicImage value="/german_flag.gif" style="border: 0px"/>
</h:commandLink>
 En el servidor
public void changeLocale(ActionEvent event) {
UIComponent component = event.getComponent();
String languageCode = getLanguageCode(component);
FacesContext.getCurrentInstance().getViewRoot().setLocale(new
Locale(languageCode));
}
private String getLanguageCode(UIComponent component) {
Map<String, Object> attrs = component.getAttributes();
return (String) attrs.get("languageCode");
}
 Desde JSF 1.2, establece una propiedad
directamente en nuestro backing bean...
<h:commandLink immediate="true” action="#{localeChanger.changeLocale}">
<f:setPropertyActionListener target="#{localeChanger.languageCode}” value="de"/>
<h:graphicImage value="/german_flag.gif" style="border: 0px"/>
</h:commandLink>
 En el servidor...
public class ChangeLocaleBean {
private String languageCode;
public String changeLocale() {
FacesContext context = FacesContext.getCurrentInstance();
context.getViewRoot().setLocale(new Locale(languageCode));
return null;
}
public void setLanguageCode(String newValue) {
languageCode = newValue;
}
}
<converter>
<description>Converter for credit card numbers that
normalizes the input to a standard format</description>
<converter-id>CreditCardConverter</converter-id>
<converter-class> converters Cred itCardConverter
</converter-class>
</converter>
<render-kit>
<renderer>
<component-family>Area</component-family>
<renderer-type>DemoArea</rendere-type>
<renderer-class>renderers.AreaRenderer</renderer-class>
<attribute>
<attribute-name>onmouseout</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
<attribute>
<attribute-name>onmouseover</attribute-name>
<attribute-class>java.lang String</attribute-class>
</attribute>
<attribute>
<attribute-name>styleClass</attribute-name>
<attribute-class>java.lang.String</attribute-class>
</attribute>
</renderer>
 Podemos registrar componentes visuales propios
<component>
<component-type>DemoArea</component-type>
<component-class>components.AreaComponent</component-class>
<property>
<property-name>alt</property-name>
<property-class>java.lang.String</property-class>
</property>
<property>
<property-name>coords</property-.name>
<property-class>java.lang.String</property-class>
</property>
<property>
<property-name>shape</property-name>
<property-class>java.lang.String</property-class>
</property>
<component-extension>
<component-family>Area</component-family>
<renderer-type>DemoArea</renderer-type>
</component-extension>
</component>
 Muestra una imagen.
 Propiedades de un, alt (texto alternativo,
normalmente mostrado al pasar el ratón por
encima) y demás relativas al uso común en
html (en la renderización típica Html).
 <h:graphiclmage…./>
 Indica un dato de salida
 Con el Renderizador de Html tenemos
◦ outputLabel
 Su atributo ‘for’ apunta a un id de un campo de entrada
con el que se encuentra asociada la etiqueta
◦ outputLink
 Necesita una etiqueta verbatim que muestra el texto que
el usuario clickea para lanzar el link
◦ outputFormat que muestra un mensaje
 Permite la utilización de java.text.MessageFormat.
 Value indica la frase a parametrizar normalmente de un
ResourceBoundle.
 Tiene etiquetas de tipo <f:param value...> para indicar
los parámetros del mensaje.
◦ outputText que muestra un texto de una línea

More Related Content

Viewers also liked

09b jsf (1)
09b jsf (1)09b jsf (1)
09b jsf (1)
UTN
 
Etiquetas básicas jsf
Etiquetas básicas jsfEtiquetas básicas jsf
Etiquetas básicas jsf
lauritat_9
 
Fundamentos de administracion_oracle_10g
Fundamentos de administracion_oracle_10gFundamentos de administracion_oracle_10g
Fundamentos de administracion_oracle_10g
Wal
 

Viewers also liked (20)

09b jsf (1)
09b jsf (1)09b jsf (1)
09b jsf (1)
 
Manual Jsf
Manual JsfManual Jsf
Manual Jsf
 
Etiquetas básicas jsf
Etiquetas básicas jsfEtiquetas básicas jsf
Etiquetas básicas jsf
 
Javaserver Faces (jsf)
Javaserver Faces (jsf)Javaserver Faces (jsf)
Javaserver Faces (jsf)
 
Ejercicio basico jsf’s
Ejercicio basico jsf’sEjercicio basico jsf’s
Ejercicio basico jsf’s
 
Facelets
FaceletsFacelets
Facelets
 
Curso JSF - Conceptos Basicos
Curso JSF - Conceptos BasicosCurso JSF - Conceptos Basicos
Curso JSF - Conceptos Basicos
 
Fundamentos de administracion_oracle_10g
Fundamentos de administracion_oracle_10gFundamentos de administracion_oracle_10g
Fundamentos de administracion_oracle_10g
 
Jsf jpa-y-hibernate-capitulo-02
Jsf jpa-y-hibernate-capitulo-02Jsf jpa-y-hibernate-capitulo-02
Jsf jpa-y-hibernate-capitulo-02
 
Manula Oracle 2
Manula Oracle 2Manula Oracle 2
Manula Oracle 2
 
Manualoracle 1
Manualoracle 1Manualoracle 1
Manualoracle 1
 
Oracle
OracleOracle
Oracle
 
Intro jsf
Intro jsfIntro jsf
Intro jsf
 
Java server faces
Java server facesJava server faces
Java server faces
 
Jsf jpa-y-hibernate-capitulo-01
Jsf jpa-y-hibernate-capitulo-01Jsf jpa-y-hibernate-capitulo-01
Jsf jpa-y-hibernate-capitulo-01
 
avanttic - webinar: Oracle Seguridad-Desarrollo Software (18-06-2015)
avanttic - webinar: Oracle Seguridad-Desarrollo Software (18-06-2015)avanttic - webinar: Oracle Seguridad-Desarrollo Software (18-06-2015)
avanttic - webinar: Oracle Seguridad-Desarrollo Software (18-06-2015)
 
Tutorial Jsf
Tutorial JsfTutorial Jsf
Tutorial Jsf
 
JBossAS: Desarrollo con Java Server Faces
JBossAS: Desarrollo con Java Server FacesJBossAS: Desarrollo con Java Server Faces
JBossAS: Desarrollo con Java Server Faces
 
Oracle Coherence (by Leonardo Torres Altez)
Oracle Coherence (by Leonardo Torres Altez)Oracle Coherence (by Leonardo Torres Altez)
Oracle Coherence (by Leonardo Torres Altez)
 
Fundamentos de Programación. Unidad I
Fundamentos de Programación. Unidad IFundamentos de Programación. Unidad I
Fundamentos de Programación. Unidad I
 

Similar to 06. jsf (java server faces) (1)

Jsf Java Server Faces
Jsf   Java Server FacesJsf   Java Server Faces
Jsf Java Server Faces
cok12v
 
Apache click
Apache clickApache click
Apache click
ntomasto
 

Similar to 06. jsf (java server faces) (1) (20)

Spring Mvc Final
Spring Mvc FinalSpring Mvc Final
Spring Mvc Final
 
Jsf Java Server Faces
Jsf   Java Server FacesJsf   Java Server Faces
Jsf Java Server Faces
 
10.desarrollowebconjava
10.desarrollowebconjava10.desarrollowebconjava
10.desarrollowebconjava
 
Manual Basico De Struts
Manual Basico De StrutsManual Basico De Struts
Manual Basico De Struts
 
[ES] Conectividad de java a base de datos(jdbc)
[ES] Conectividad de java a base  de datos(jdbc)[ES] Conectividad de java a base  de datos(jdbc)
[ES] Conectividad de java a base de datos(jdbc)
 
JSP
JSPJSP
JSP
 
Jsf
JsfJsf
Jsf
 
SEMINARIO: Servicios REST. Bases de la tecnología y soporte con Spring MVC
SEMINARIO: Servicios REST. Bases de la tecnología y soporte con Spring MVCSEMINARIO: Servicios REST. Bases de la tecnología y soporte con Spring MVC
SEMINARIO: Servicios REST. Bases de la tecnología y soporte con Spring MVC
 
Arquitectura java web
Arquitectura java webArquitectura java web
Arquitectura java web
 
Java Web - JSF
Java Web - JSFJava Web - JSF
Java Web - JSF
 
01 introducción
01 introducción01 introducción
01 introducción
 
Curso Java Avanzado 6 Struts
Curso Java Avanzado   6 StrutsCurso Java Avanzado   6 Struts
Curso Java Avanzado 6 Struts
 
15a. Reunion de SpringHispano.org y grails.org.mx
15a. Reunion de SpringHispano.org y grails.org.mx15a. Reunion de SpringHispano.org y grails.org.mx
15a. Reunion de SpringHispano.org y grails.org.mx
 
Primefaces
PrimefacesPrimefaces
Primefaces
 
GWT - Una introducción
GWT - Una introducciónGWT - Una introducción
GWT - Una introducción
 
Apache click
Apache clickApache click
Apache click
 
Herramientas de trabajo (3)
Herramientas de trabajo (3)Herramientas de trabajo (3)
Herramientas de trabajo (3)
 
JqueryMobile
JqueryMobile JqueryMobile
JqueryMobile
 
Aplicación abc. asp net mvc 3
Aplicación abc. asp net mvc 3Aplicación abc. asp net mvc 3
Aplicación abc. asp net mvc 3
 
Curso Jsp
Curso JspCurso Jsp
Curso Jsp
 

More from Michael Mieles Caballero

More from Michael Mieles Caballero (8)

Analisis de accidentes de transito vehicular y sus consecuencias
Analisis de accidentes de transito vehicular y sus consecuenciasAnalisis de accidentes de transito vehicular y sus consecuencias
Analisis de accidentes de transito vehicular y sus consecuencias
 
Diseño de la red lista para ser comprobada12.15
Diseño de la red lista para ser comprobada12.15Diseño de la red lista para ser comprobada12.15
Diseño de la red lista para ser comprobada12.15
 
Lenguaje estructurado en forma sintáctica ascendente
Lenguaje estructurado en forma sintáctica ascendenteLenguaje estructurado en forma sintáctica ascendente
Lenguaje estructurado en forma sintáctica ascendente
 
Política de como monitorear un centro de computo universitario
Política de como monitorear un centro de computo universitarioPolítica de como monitorear un centro de computo universitario
Política de como monitorear un centro de computo universitario
 
Plan de continuidad de negocio
Plan de continuidad de negocioPlan de continuidad de negocio
Plan de continuidad de negocio
 
12 dependency injection
12 dependency injection12 dependency injection
12 dependency injection
 
11 asp.net web api
11 asp.net web api11 asp.net web api
11 asp.net web api
 
9 routing
9 routing9 routing
9 routing
 

06. jsf (java server faces) (1)

  • 1.
  • 2.  Actualmente la mayoría de las aplicaciones se distribuyen por Internet.  Casi todos los accesos clientes se hacen a través de Web.  Cada vez hay mas clientes específicos con dispositivos y pantallas diferentes.  El modelo de programación Web actual está basado en documentos no basados en pantallas de interacción.
  • 3.  JSF logra la unión entre los cliente Web actuales y el modelo tradicional de componentes.  Logra separar la renderización del componente.  Logra desplazar la interacción del usuario con el programa al modelo tradicional de eventos.  JSF es la evolución estándar de Struts, por los mismos que realizaron Struts.  Es un estándar claro y potente para poder hacer aplicaciones visuales mas potentes.
  • 4.  Nos da Renderización, árbol de componentes visuales, validadores, conversores y eventos y javabeans.  Nos aporta un ciclo de vida claro estándar.  Nos permite configurar y definir externamente el flujo de pantallas, la navegación.  Nos permite modificar o incorporar componentes básicos propios en la arquitectura. ◦ Por ejemplo un ciclo de vida propio
  • 5.  Aporta tags para funcionar sobre jsps.  Se podría usar JSF en otros entornos diferentes a jsp.  Tenemos una librería estándar de JSF-Html para crear aplicaciones web.  Nos da un nivel de información independiente de estar en un contenedor web-servlets o un contenedor basado en portlets.  Retrasa la renderización hasta el último momento para poder renderizar con toda la información bien preparada.  Nos permite crear componentes propios para reutilizar.  JSF tiene un Servlet como entrada de las llamadas a su arquitectura.
  • 6.  Se necesita configurar un servlet de JSF para enlazar con el contenedor Web.  Se basa en un fichero de configuración, por defecto faces-config.xml  ¿Qué gestionamos en el faces-config? ◦ Componentes (Edit/ Label/ ComboBox). ◦ Validadores. ◦ Conversores. ◦ Beans (Java Beans). ◦ Navegación ◦ Aspectos avanzados...
  • 7.  Debemos registrar el servlet. ◦ javaxfaces.webapp.FacesServlet  Tenemos que hacer el servlet-mapping de las uris que vamos a tratar con JSF. ◦ Normalmente de tipo  /facesl*  *.faces  *.jsf
  • 8.  Se pueden configurar los siguientes parámetros globales (context-param): ◦ javax.faces.CONFIG_FILES indicando una lista relativa a nuestro contexto donde están los archivos de configuración de JSF. Por defecto carga /WEB-lNF/faces-config.xml. ◦ javax.faces.DEFAULT_SUFFIX indica el sufijo por defecto de recursos conteniendo componentes JSF, por defecto . jsp. ◦ javax.faces.LIFECYCLE_lD instancia de LifeCycle a usar por JSF por defecto LifecycleFactory.DEFAULT_LIFECYCLE. ◦ javax.faces.STATE_SAVING_METHOD La localización donde se va a guardar la información de estado:  server o client.  Por defecto server en el HttpSession
  • 9.  La etiqueta principal es <faces-config>.  Podemos tener mas de un archivo de configuración.  Podemos configurar: ◦ Java beans. ◦ Registrar validadores propios. ◦ Registrar conversores propios. ◦ Configurar reglas de navegación. ◦ Registrar Renders. ◦ Registrar componentes propios.
  • 10.  Partimos de piloto 0.0, entorno de trabajo basado en Maven2 y generado mediante el arquetipo para MyFaces.  Lo modificamos para que: ◦ Aparezca una nueva página welcome.jsp con un mensaje de “Hola Mundo” ◦ Index.jsp redirija mediante response.sendRedirect(...) a welcome.jsf ¿?  Probamos la aplicación. ¿Qué ha ocurrido?
  • 11.  Welcome.jsf no es aún una vista válida JSF.  En JSF todas las vistas deben estar contenidas en un elemento f:view: <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> <f:view> ... </f:view>  ¿Por qué? Encapsular la JSF en el componente vista.
  • 12.  Permite declarar los beans que van a ir instanciando automáticamente y en el scope que se van a a encontrar.  Configurar propiedades de los beans.  Poner el valor de una propiedad de un bean al resultado de la evaluación de un método value- binding.  Scopes: ◦ request. ◦ Session. ◦ application. ◦ none.  El bean es inicializado cada vez que es referenciada y no se guarda en ningún scope.
  • 14.  Vamos a inyectar nuestro primer bean en JSF: ◦ En primer lugar, creamos la clase es.uniovi.si.UsuarioBean con una propiedad nombre ◦ Lo declaramos en el faces-config.xml como bean usuario, inicializando su propiedad nombre con la cadena “Invitado”. <managed-bean> <managed-bean-name>usuario</managed-bean-name> <managed-bean-class>es.uniovi.si.UsuarioBean</managed-bean- class> <managed-property> <property-name>nombre</property-name> <value>invitado</value> </managed-property> </managed-bean>
  • 15.  Creamos una nueva vista entrada.jsp y, dentro, mostramos la propiedad nombre del bean usuario mediante el componente de salida: Hola <h:outputText value="#{usuario.nombre}"/>, bienvenido a mi sitio web.<br>  Probar a acceder mediante piloto/entrada.jsf ¿Funciona?  Acceder ahora mediante piloto/entrada.jsp ¿Y ahora?  Quitar ahora f:view y probar con entrada.jsf. ¿Funciona? Resuelto en piloto 1.0.
  • 16.  Realiza una acción al ser activado.  Propiedades básicas: ◦ Action String o method-binding al método que devuelve ese String. EL String es usado por el NavigationHandier para determinar la pagina siguiente de acceso. ◦ actionListener para escuchar los eventos de acción
  • 17.  Dos tipos de etiquetas básicas ◦ commanButton representa un botón <h:commandButton ../> ◦ commandLink representa un elemento de acción en formato link (con <a></a>) .  La etiqueta ha de contener una etiqueta outputText para representar donde el usuario clickea para generar el evento
  • 18.  Representa los campos de entrada.  En el renderizador de Html tenemos varios tags ◦ inputHidden representa un campo hidden ◦ inputSecret representa a un campo password ◦ inputText ◦ inputTextArea  Suelen tener asociados elementos en las siguientes propiedades ◦ Converter Identifica el conversor de datos a utilizar. ◦ Validatos method-binding a la validación. ◦ valueChangeListener method-binding para escuchar los cambios de valor
  • 19.  Cuando apliquemos JSF, tenemos que ceñirnos a sus reglas y utilizar sus etiquetas en lugar de las etiquetas estándar HTML.  Éstas implementan más lógica por detrás que nosotros no vemos pero que nos ahorra trabajo.  Ejemplo de formulario en JSF: <h:form> <h:inputText value="#{usuario.login}"/> <h:commandButton value="Login" action=“¿?"/> </h:form>
  • 20.  Editamos welcome.jsp y añadimos lo siguiente: <h:form> <h:inputText value="#{usuario.nombre}"/> <h:commandButton value="Enviar" action=“entrada.jsf"/> </h:form> Accedemos a la aplicación y pulsamos el botón... ¿Qué ocurre? Examinamos el código fuente. ¿Adonde apunta el formulario? ¿Por qué?
  • 21.  En JSF, TODAS las peticiones van a la propia página. Entonces. ¿Dónde está el truco?  El servlet mapping hace que el controlador caputure TODAS las peticiones que concuerden con la extensión *.jsf  Lo que debemos poner en el campo action de un componente de comando (nótese que no es a nivel de formulario) es la acción que se desea disparar  ¿Cómo se navega entonces? Estableciendo el mapa de navegación en el controlador.
  • 22.  Permite configurar cual será la siguiente pagina después de pulsar un boton o link.  Cada regla define como navegar desde una página hacia otro conjunto de páginas.  La siguiente pagina depende del método action sobre el que se haya pinchado y la salida lógica que de la etiqueta referenciada.  Salidas típicas: ◦ success:  todo ocurrió correctamente. ◦ Failure:  hubo algo mal, ir a una página de error. ◦ Logon:  el usuario necesita logearse primero, IR a pagina de logon ◦ No result:  la búsqueda no encontró nada. Ir a la pagina de búsqueda de nuevo
  • 23.  From-view-id ◦ Indica la página origen de la request.  From-action ◦ indica el action del que procede y que da su valor.  From-outcome ◦ Representa el evento que dispara la transición.  To-view-id ◦ indica el id de la vista a la que pasamos
  • 25.  Vamos a establecer una regla de navegación en el faces-config.xml que determine que cuando se dispara la acción login desde la página welcome.jsp el controlador nos debe redirigir a entrada.jsf: <navigation-rule> <from-view-id>/welcome.jsp</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/entrada.jsf</to-view-id> </navigation-case> </navigation-rule>  Recordad modificar el formulario para que ejecute la acción login. ¿Funciona?
  • 26.  Problema: El bean aparece siempre con el mismo valor. ¿Por qué?:  El scope por defecto de los beans es page, y nosotros no hemos establecido ninguno diferente. Editar el faces-config.xml y forzar que el bean-scope sea request.  Volver a probar la aplicación. Resuelto en piloto 2.0
  • 27.  Con #{expresion languaje} podemos referirnos a los métodos, propiedades y elementos <managed-bean> <managed-bean-name>customer</managed-bean-name> <managed-bean-class>CustomerBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>areaCode</property-name> <value>#{initParam.defaultAreaCode}</value> </managed-property> ……………. </managed-bean>
  • 28.  Es un Map de Collections, se puede especificar la clase que hace de llave <managed-bean> <managed-property> <property-name>prices</property-name> <map-entries> <map-entry> <key>My Early Years: Growing Up *7</key> <value>30.75</value> </map-entry> <map-entry> <key>Web Servers for Fun and Profit</key> <value>40.75</value> </map-entry> </map-entries> </managed-property> </managed-bean>
  • 29. <managed-bean> ……. <managed-property> <property-name>books</property-name> < list-entries > <value-class>java.lang.String</value-class> <value>Web Servers for Fun and Profit</value> <value>#{myBooks. bookld [3]}</value> <null-value/> </ list-entries > </managed-property> </managed-bean>
  • 30.  ¿Cómo hacemos que nuestras vistas interactúen con el modelo?  Sabemos como forzar a que JSF invoque un método get o set sobre un bean, luego ¿Implementando lógica en los accessors? No, sería desnaturalizar el método.  Alternativa: Navegación dinámica
  • 31.  En el ejemplo que hemos visto, el botón de commando dispara una acción que, tal y como hemos configurado, nos redirige de terminantemente a otra vista.  En las aplicaciones reales, la redirección dependerá del resultado de la interacción con el modelo. Ejemplo hago login y: ◦ Si es correcto, paso a la página de entrada ◦ Si no, vuelvo a la página de login y muestro un error.  Para esto necesito: ◦ Elementos donde implementar la lógica decide la navegación ◦ La posibilidad de establecer las diferentes transiciones en base al resultado.
  • 32.  Para implementar navegación dinámica, debemos utilizar en el elemento de comando que hace submit una expresión de método.  Ejemplo: <h:commandButton label="Login" action="#{loginController.verifyUser}"/>  En este caso, al pulsar el botón se invocará el método verifyUser del bean dado de alta como loginController.
  • 33.  ¿Cómo se determina el destino tras ejecutar un método de bean?  Desde el bean: if (...) return "success"; else return “login-error";  El bean dispara acciones en base a las cuales se determinará cual será la siguiente vista.
  • 35.  Vamos a implementar e inyectar un bean que se encarge de nuestro futuro proceso de login. Para eso: ◦ Añadimos una propiedad password al bean usuario y completamos el formulario de la página welcome para que se recoja la contraseña. ◦ Creamos es.uniovi.si.LoginAction tal que:  Contenga una propiedad de tipo UsuarioBean  Tenga un método login que:  Si usuario=contraseña=admin entonces dispare “success”  Si no, dispare login-error. ◦ Establecemos la navegación en el faces-config.xml ◦ ¿Funciona? ¿Qué ocurre?
  • 36. <managed-bean> <managed-bean-name>customer</managed-bean-name> <managed-bean-class>com .mycompany.mybeans.CustomerBean</managed-bean-class> <managed-bean-scope> request </managed-bean-scope> <managed-property> <property-name>mailingAddress</property-name> <value>#{addressBean}</value> </managed-property> <managed-property> <property-name>streetAddress</propertyname> <value>#{addressBean}</value> </managed-property> <managed-property> <property-name>custom erType</property-name> <value>New</value> </managed-property> </managed-bean> <managed-bean> <managed-bean-name>addressBean</managed-bean-name> <managed-bean-class>com .mycompany.mybeans.AddressBean</managed-bean-class> <managed-bean-scope> none </managed-bean-scope> <managed-property> <property-name>street</property-name> <null-value/> <managed-property> </managed-bean>
  • 37.  Inyectar el bean usuario en el bean loginAction en el faces-config.xml  Probar la aplicación. Resuelto en piloto 3.0
  • 38.  Modificar la versión anterior para añadir un contador que, basándose en el contexto de la aplicación, cuente cuantos logins se realizan en la aplicación contando todos los de los usuarios.  ¿Desde donde lo hacemos? ¿En qué clase lo inyectamos?  Visualizar el resultado del contador en la página final.
  • 39.  Hasta ahora hemos visto y usado algunos de los elementos que nos aporta JSF, como los formularios, los comandos, etc.  Los elementos de JSF se clasifican en: ◦ Componentes JSP ◦ Objetos Implícitos
  • 40.  JSF basa sus vistas en un árbol de nodos visuales.  Los nodos tienen asociados un renderizador que crea su visualización.  Entre llamada y llamada se recrea el árbol de objetos en el lado servidor.  Hay un conjunto estándar de componentes base.  Tenemos una implementación de HTML que implementa de diversa manera estos componentes base.  Vamos a ver los componentes base con su reflejo sobre los componentes Html.
  • 41.  Podemos usar el EL para asociar métodos y propiedades a los elementos #{.. .}.  Con el Expresion Languaje de JSF tenemos una serie de objetos implícitos en el contenedor web estándar: ◦ applicationScope ◦ cookie ◦ facesContext ◦ header ◦ headerValues ◦ initParam. ◦ param ◦ paramValues ◦ requestScope ◦ sessionScope ◦ view  Indica el UIComponent que es raíz del árbol para esta llamada
  • 42.  Los componentes han de tener un constructor vacío para poder instanciarse.  Todo componente visual tiene una representación como objeto en el servidor en una jerarquía nodal.  El renderizador se encargara de generar su representación visual según convenga.
  • 43.  El paquete visual principal es javax.facescomponent.  Todo elemento visual forma parte de un árbol nodal de elementos.  El elemento base de la jerarquía es UIComponent.  El elemento funcional base que hereda de UIComponent es UIComponentBase.  El elemento raíz de un árbol es UIViewRoot.  Todo componente debe especificar constantes indicando el tipo bajo el cual el componente es registrado y la familia para seleccionar el render adecuado. ◦ COMPONENT_TYPE, Component_FAMILY
  • 44.  Propiedades nodales ◦ getParent. ◦ getChildren. ◦ getChildrenCount. ◦ getViewNode  Nos permite acceder al nodo principal del árbol ◦ Buscar componentes hijo. ◦ Cada componente tiene un Id, bien impuesto o bien generado.
  • 45.  Nos permite acceder al FacesContext al que pertenece el componente.  Todo componente pertenece a una familia y un renderType, la conjunción de ambos determina el render a utilizar.  Casi cada componente UI va a tener una etiqueta asociada. ◦ getAttibutes nos permite acceder a las propiedades y atributos del componente
  • 46.  Al crear componentes tenemos que implementar la codificación y decodificación de la información.  Decode: ◦ Leemos el dato del request y propagamos su valor.  Encode: ◦ EncodeBegin ◦ EncodeChildren ◦ EncodeEnd ◦ Durante la fase de renderización los datos se pasan al lenguaje de marcado. ◦ En caso de no necesitar tener en cuenta los componentes hijo solo implementaremos en encodeEnd.
  • 47.  Es el nodo raíz de un árbol de componentes visuales.  Nos permite poner el locale del árbol.  Hereda de UIBaseComponent.  Tiene asociado un RenderKit: ◦ Es una familia de renders. ◦ Cada render en el RenderKit esta designado por tipo y familia que renderiza. ◦ Su etiqueta es f:view y su único atributo opcional es locale
  • 48.  Actualmente hay dos librerías de etiquetas básicas: <%@ taglib uri=http://java.sun.com/jsf/core prefix=”f” %> <%@ taglib uri= uri=http://java.sun.com/jsf/html prefix=”h” %>
  • 49.  Los componentes han de estar metidos dentro del un único nodo raiz <f:view>  Cuando se realiza un <jsp:import> o <c:include> todos elementos incorporadas han de meterse en un <f: subview> ◦ <f:subview>  <c:include ...> ◦ </f:subview>  Cualquier texto de plantilla incluido por el include o el import, actualmente debe meterse dentro de una etiqueta <f: verbatim>  Cada elemento va a tener los atributos del componente mas los añadidos por el render. ◦ Con el render de HTML podemos ver que el Componente UIData tiene una implementaron (por extensión) HTMLDataTable que contiene los atributos configurables relativos a Html y específicos del Render
  • 50.  Propiedades usuales: ◦ Id del componente, si no se lo ponemos es generado automáticamente. ◦ lmmediate: si esta a true indica que los eventos, validaciones y conversiones se realizan en la fase de apply request en vez de en una fase posterior. ◦ Rendered indica si el componente ha de ser renderizado. ◦ Style especifica el cascading style sheet para la etiqueta. ◦ styleClass especifica el class del CSS (cascading style sheet). ◦ Value indica el valor del componente, como literal o enlazado con una propiedad del modelo de información. ◦ Binding identifica una propiedad de un bean y asocia la instancia UI del componente a esa propiedad (set.. .(UI.. A)). ◦ Todos los atributos excepto id y var permiten la asociación de value-binding con el Expresion Lenguaje de Java Server Faces.  #{objeto.propiedad}
  • 51.  Representa un form de entrada.  Engloba a todos los componentes que muestran o recogen información. ◦ <h:form>. ..</h:form>
  • 52.  Representa una tabla de información.  <h:dataTable..>...  Tiene UIColumns dentro.  Soporta estar enlazado con una colección de objetos sobre la que itera.  El atributo value indica la colección sobre la que iterar.  El atributo var indica la variable sobre la que se va a ir guardando el objeto de datos en cada iteración.
  • 53.  Tipos de datos soportados: ◦ Listas y arrays de beans. ◦ Una sóla bean. ◦ Un javax.sql.ResultSet y javax.servlet.jsp.jstl.sql.ResultSet. ◦ javax.sql.RowSet. ◦ Javaxfaces.model.DataModel  Todos los tipos de datos soportados tienen un Wrapper a DataModel, la implementación encapsula nuestro objeto en el wrapper correspondiente.
  • 54.  First indica la primera fila a ser mostrada.  Rows indica el número de filas a mostrar.  Existen varias propiedades que pueden indicar listas de estilos para los diferentes elementos: ◦ columnClasses ◦ footerClass ◦ headerClass ◦ rowClass ◦ StyleClass
  • 55.  Representa una columna de información en un UIData  Cada columna puede tener uno o varios facet que indicarían las cabeceras y pies de las columnas ◦ Si se quiere poner mas de un componente dentro de una facet se ha de usar un panelgroup para embeberlos ya que facet solo soporta tener un componente hijo. ◦ Un facet se usa para representar un componente que es independiente de la relación padre-hijo en el árbol de elementos. ◦ En el caso de las columnas las cabeceras y pies sólo se pintan una vez, no en cada bucle.  <h:column>
  • 56. <h:dataTable value="#{gestionLibrosService.libros}" var="libro"> <h:column> <f:facet name="header"> <h:outputText value="Título" /> </f:facet> <h:outputText value="#{libro.titulo}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Autor" /> </f:facet> <h:outputText value="#{libro.autor}"/> ... </h:dataTable>
  • 57.  Modificar la versión 3.0 del piloto y: ◦ Crear una clase LibroBean con las propiedades autor, título, descripción y precio. ◦ Crear una clase Libreria que contenga un Vector de LibroBeans almacenados en una propiedad catalogo ◦ Declarar una librería con al menos 3 libros diferentes y denominarla liberia ◦ Modificar la página entrada.jsp para que muestre el catálogo de la librería usando un tag h:dataTable. ¿Qué scope tendrán que tener los libros? ¿Y la librería? Resuelto en piloto 4.0
  • 58.  Cada llamada que lleva a un JSF tree pasa por una serie de fases determinadas que crean su ciclo de vida.  Existen tres tipos de escenarios posibles: ◦ Una petición sin JSF genera una respuesta con JSF. ◦ Una petición con JSF genera un respuesta con JSF. ◦ Una petición con JSF genera una respuesta sin JSF.  A su vez la aplicación también puede recibir peticiones sin JSF que generen respuestas sin JSF
  • 59.  Toda llamada o request tiene asociado un FaceContext y al hilo de llamada.  El FaceContext solo debe existir durante la request hasta que se llame a su método release.  No se le debe referenciar por un objeto que tenga una vida mas larga que la request .  Contiene toda la información relativa al estado en la request y la renderización de la respuesta.  Encapsula el elemento raíz visual ViewRoot.
  • 60.  Encapsula los posibles mensajes.  Nos permite acceder al Singleton de Application.  Encapsula ResponseWriter -salida de cáracteres- y ResponseStream —salida binaria-. Como flujos de escritura para los renderizadores.  Nos permite acceder a ExternalContext: ◦ Nos da acceso al entorno independientemente de estar en un contenedor de servlets o de portlets. ◦ Accedemos a todo el entorno de información que tendríamos como servlet.
  • 61.
  • 62.
  • 63.  El servidor recibe una llamada y recompone los objetos de la vista en el servidor.  Examina si FacesContext tiene un UIViewRoot en caso de tenerlo: ◦ Le asigna el locale correspondiente (internacionalización). ◦ Para cada valor en el árbol mira si tiene un valuebinding asociado a binding y si lo tiene llama a setValue() pasando la instancia en donde se encontró. ◦ No se realizan mas acciones.  Se crea el viewID de la URI y de los valores de prefijo: ◦ ViewHandler.DEFAULT_SUFFIX_NAME
  • 64.  Llaman a viewHandler.restoreView() pasando la instancia FacesContext asociada a la llamada y el viewID, consiguiendo el UIViewRoot como respuesta: ◦ En caso de devolver null no había vista asociada por lo que se crea una y se pasa al renderResponse:  se llama a ViewHandler.createView() y a FacesContext .renderResponse() ◦ Si la petición no contiene parámetros de llamada ni datos en POST se llama a renderResponse
  • 65.  Se almacena el UIViewRoot en el FacesContext.  Se determina el valuebinding para cada atributo binding y se llama al setValue.  Al final de esta fase tenemos recuperado el viewRoot que había y si acaso se ha creado uno nuevo.
  • 66.
  • 67.  Da la oportunidad a los componentes a actualizar sus valores a los valores que llegan de la request.  Se llama al método processDecodes() de todos los componentes del árbol UIViewRoot.  Los componentes que implementan ActionSource que reconocen que fueron activados encolan su evento. ◦ Estos eventos son notificados al final de esta fase
  • 68.  Los componentes que implementan EditableValueHolder que tienen la propiedad immediate a true realizan la conversión y validación. lncluyendo el potencial lanzamiento del evento ValueChange. ◦ Normalmente immediate esta a false esto ocurre posteriormente en la fase de Process Validations
  • 69.
  • 70.  Todo error producirá un mensaje que se encolara en el FaceContext, y el componente que la lanza será marcado como invalido.  En cualquier momento si nuestra lógica en los decode, o en los eventos llama a responseComplete en FacesContext. Se termina inmediatamente el procesado del request.  Si se llama a renderResponse en el FacesContext se transfiere el control a la fase de Render Response.  En caso contrario pasamos a la fase de Process Validations
  • 71.
  • 72.  Se procesan las validaciones llamando a processValidators.  Cualquier fallo en la validación mete un mensaje de error en el FacesContext. ◦ Y la propiedad valid del componente se pone a false.  En cualquier validador puede llamar a responseComplete o a renderResponse de FacesContext.
  • 73.
  • 74.  Llegados a esta fase se asume que los contenidos son sintácticamente y semánticamente correctos.  Se asume que el valor local de los componentes ha sido actualizado.  Es el momento de actualizar los datos del modelo de la aplicación.  Esto se produce recursivamente llamando a UlComponent.processUpdates.  La actualización dentro de un componente se realiza llamando al método updateModel.
  • 75.  Durante la actualización los eventos son encolados hasta la finalización de la fase donde se procesan.  Al finalizar esta fase los valores del modelo de datos han sido actualizados y los valores de los componentes han sido vaciados.  Cualquiera de nuestros métodos podría llamar a responseComplete o a renderResponse.
  • 76.
  • 77.  Si se alcanza esta fase se asume que la actualización del modelo ha sido completada.  Se llama al método processApplication de UIViewRoot.  Se llama a todos los eventos encolados con phaseId.INVOKE_APPLICATION.  Excepcionalmente se podría llegar a cambiar el actionListener por defecto con setActionListener
  • 78.
  • 79.  Hace que la respuesta sea renderizada al cliente.  Hace que el estado de la respuesta sea guardado para ser procesado en llamadas sucesivas.  Cuando un componente de árbol es seleccionado para renderizarse se llama a su método de encodexxx().  Para los elementos que implementan ValueHolder se ha de producir su conversión.  Antes de completarse el estado de la vista ha de ser guardado usando los métodos de la clase StateManager. ◦ Esta información ha de estar disponible para que Restore View pueda acceder a ella en sucesivas llamadas.
  • 80.  Son beans que no responden a entidades, sino a agrupaciones que datos que por motivos prácticos, nos puede interesar procesar juntos, a nivel no de valores sino de componentes.  Es imprescindible para validaciones en las que se han de comprobar relaciones entre componentes.  Ejemplo: Representación de formularios
  • 81.  Si queremos hacer un backing bean para un formulario de cambio de usuario en sesión que muestra y recibe información al mismo tiempo, por ejemplo: Public class ChangeSessionForm { UIInput newUser; UIOutput oldUser; //getters and setters... } ... En la JSP: <h:outputText binding="#{changeSessionForm.oldUser}"/> Lo que le pasa JSF al formulario al hacer binding no es el valor del componente, sino su referencia.
  • 82.  Vamos a alterar el proceso de login para utilizar es.uniovi.si.backing.LoginForm como backing bean. Para ello: ◦ Declaramos dos propiedades UIInput (login y password) ◦ Declaramos el bean como loginForm y se lo inyectamos al LoginAction ◦ Hacemos el enlazado entre los campos del formulario y modificamos adecuadamente la clase LoginAction para que partir de ahora recupere los valores del formulario. Resuelto en piloto 5.0
  • 83.  Los elementos de formulario que muestran elementos entre los que seleccionar (combo, radio, listas, etc) comparten modo de funcionamiento.  La entrada de datos debe ser una colección de elementos SelectItem.  Ej: ◦ New SelectItem(“010”,”The Matrix”);  ¿Cómo se conecta con el formulario?
  • 84.  Etiqueta h:selectBooleanCheckbox  Representa un estado booleano
  • 85.  Tres renderizaciones básicas ◦ selectManycheckbox  Muestra una lista de checkboxes  Value indica el set de elementos seleccionados actualmente.  Layout indica como se han de poner los checkbox pageDirection/lineDirection.  Contiene etiquetas selectItem o selectItems representando a los elementos. ◦ selectManyListBox ◦ selectManyMenu
  • 86.  Permite seleccionar solo un elemento: ◦ selectOneRadio ◦ selectOneMenu ◦ selectOneListbox  Su contenido son colecciones de Selectltem o Selectltems
  • 87.  Nos permiten anidar elementos en los select  f:SelectItem  Un UISelectItems representa a una colección de SelectItem o de SelectItemGroup.  SelectItems permite tomar los datos de Arrays, Map y Collection de elementos tipo SelectItem o SelectItemGroup ◦ Javax.faces.modelSelectItem. ◦ Todo Item tiene un Label y un value.
  • 88.  Ej: para cargar un combo... ◦ Bean pruebaForm: Private UIInput propiedadDestino; public Collection getOpciones() { opciones = new ArrayList(); opciones SelectItem(“01”,“Opción 1")); opciones SelectItem(“02",“Opción 2")); return opciones; } ◦ En la jsp: <h:selectOneMenu binding="#{pruebaForm.propiedadDestino}"> <f:selectItems value="#{pruebaForm.opciones}"/> </h:selectOneMenu>
  • 89.  Vamos a añadir al formulario de login un combo con el idioma preferido por el usuario. Para ello: ◦ Añadimos una propiedad idioma de tipo IUInput al LoginForm, y un método getIdiomas que retorne una colección de SelectItems con:  “es”,”Español”  “en”,”English” ◦ Lo enlazamos y mostramos lo recibido en el LoginForm al pulsar el botón. (Resuelto en piloto 6.0)
  • 90.  Completar piloto 6.0 para: ◦ Añadir un formulario en entrada.jsp con:  Un combo donde se muestre la lista de libros  Un editBox donde se introduzca la cantidad del libro seleccionado ◦ Un backing bean CarritoForm con un método add para gestionar el carrito de la compra ◦ Un CarritoBean que resida en sesión y que encapsule una HashMap. Tendrá que tener un método public List<Entry> getProductos() que retorne una lista de objetos entry obtenidos mediante el método entrySet de la HashMap.
  • 91. ◦ Una página vercarrito que muestre el estado del carrito de la compra mediante una tabla, con un enlace a la página anterior: <h:form> <h:commandLink action="success">Volver</h:commandLink> </h:form> Resuelto en piloto 7.0
  • 92. En cualquier aplicación es conveniente evitar tener las cadenas de texto hardcodeadas en el código fuente de las pantallas o páginas. Los resource bundles sirven para seleccionar el mensaje de error en función de la clave, buscándolo en los resource bundle cargados. En el faces-config: <application> <resource-bundle> <base-name>messages</base-name> <var>msgs</var> </resource-bundle> </application> Luego los referenciamos mediante EL. Ejemplo: <h:outputText value="#{msgs.welcome}"/> El fichero messages.properties: welcome=Benvenido a mi página web!!!!
  • 93.  Sobre piloto 7.0...  Creamos messages.properties.  Lo configuramos como fichero de recursos con el prefijo msgs.  Extraer los mensajes de al menos una de las vistas, por ejemplo, welcome.jsp.  Probar la aplicación. Resuelto en piloto 8.0
  • 94.  JSF aprovecha la externalización de cadenas de texto para implementar la internacionalización de etiquetas.  En la request viaja el idioma preferido del navegador, representado por el parámetro LOCALE.  El locale responde a un código estandarizado (es,en,fr, etc).  Para internacionalizar la aplicación: un fichero de recursos por locale: ◦ messages.properties ◦ Messages_en.properties ◦ Messages_fr.properties ◦ ...
  • 95.  Internacionalizar la aplicación para el inglés. Para ello: ◦ Creamos un fichero messages_en.properties copiando el messages.properties. ◦ Traducimos las cadenas de texto al inglés ◦ Para probarlo, establecemos en el navegador el inglés como idioma por defecto.
  • 96.  Actualmente se recomienda que el usuario pueda seleccionar explícitamente el idioma por encima de lo que diga el parámetro de idioma preferido del navegador.  JSF permite establecer el locale de varias formas diferentes:
  • 97. 1. Estableciéndolo directamente en el faces- config.xml, el criterio idioma del navegador prevalece sobre ésto.: <faces-config> <application> <locale-config> <default-locale>en</default-locale> <supported-locale>de</supported-locale> </locale-config> </application> </faces-config>
  • 98. 2. Establecerlo como parámetro de la etiqueta f:view: <f:view locale="de"> Ventaja, podemos establecerlo dinámicamente <f:view locale="#{user.locale}"/> 3. Establecerlo por programa UIViewRoot object: UIViewRoot viewRoot = FacesContext.getCurrentInstance().getViewRoot(); viewRoot.setLocale(new Locale("de"));
  • 99.  Modificar la aplicación para que el criterio del idioma que estamos seleccionando al hacer login cambie el locale de la aplicación.  Para verlo reflejado, internacionalizar alguna de las páginas posteriores al proceso de login.  ¿Dónde recogemos el locale? Resuelto en piloto 9.0
  • 100.  JSF aporta una colección de conversores predefinidos para tipos de datos estádar.  Converter es el interfaz capaz de hacer transformaciones string-objeto y objeto-string. ◦ public java.langObject getAsObject(javax.faces.context.FacesContext context, javax.faces.com ponent. UlComponent component, java.lang.String value) ◦ public java.Iang.String getAsString(javax.faces.context. FacesContext context, javax.faces.component. UlComponent component, java.lang.Object value)  Podemos asociar un conversor a un lnput/Output.  El atributo converter indica la clase java que implementa ese interface.  También se puede anidar dentro de una etiqueta con f:converter. ◦ Su atributo converteride indica el id del conversor a usar.
  • 101.  Tenemos conversores automáticos para los tipos básicos: ◦ BigDecimalConverter ◦ BigIntegerConverter ◦ ByteConverter ◦ CharacterConverter ◦ DateTimeConverter ◦ DoubleConverter ◦ FloatConverter ◦ IntegerConverter ◦ LongConverter ◦ NumberConverter ◦ ShortConverter
  • 102.  f:dateTimeConverter permite hacer conversiones de fecha: ◦ datestyle: indica el formato: default, short, medium, long y full. ◦ locale: indica el Locale, por defecto FacesContext.getLocale. ◦ pattern: indica el patrón de fecha (dd/MM/yy por ejemplo) ◦ timeStyle: define el formato de hora ◦ timeZone: ◦ type: indica si el string va a contener una fecha, hora o ambos
  • 103.  F:numberConverter permite controlar conversiones de numero ◦ currencyCode, currencySymbol, pattern, locale, minIntegerDigits, maxIntegerDigits, minFractionDigits, maxFractionDigits. ◦ groupingUsed: boolean indica si la cadena de salida tiene separadores de agrupamiento. ◦ integerOnly: boolean indica si se va a parsear la parte entera del valor. ◦ Type: indica si el valor a parsear y formatear es número, moneda o porcentaje
  • 104.  El funcionamiento cuando hay un conversor es el siguiente: ◦ El usuario envía los datos ◦ Se vuelvan al árbol de componentes ◦ Se invocan los conversores ◦ En caso de error,  Se añaden los mensajes de error a la lista global de mensajes  Se vuelve a mostrar la página original y, en caso de que exista una etiqueta h:messages, se muestran los errores.
  • 105.  Ejemplos: <h:outputText value="#{payment.date}"> <f:convertDateTime/> </h:outputText> <h:outputText value="#{payment.amount}"> <f:convertNumber type="currency"/> </h:outputText> <h:inputText value="#{payment.amount}"> <f:convertNumber minFractionDigits="2"/> </h:inputText>
  • 106.  ¿Cómo muestro los errores de conversión/validación? Si quiero mostrarlos todos juntos: <h:messages/> Si quiero mostrar los específicos de un campo: <h:inputText id=“unidades" label=“Unidades" binding="#{bean.unidades}"> <f:convertNumber integerOnly="true"/> </h:inputText> <h:message for=“unidades"/>
  • 107.  Basarse en el ejemplo anterior para aplicar un conversor para la cantidad de productos que se añaden al carrito y mostrar los errores asociados al cambo justo debajo del mismo.  Probarlo metiendo caracteres en el campo. ¿Funciona? ¿Cómo sale el mensaje? Resuelto en piloto 10.0.
  • 108.  Lo habitual será personalizar los mensajes de error que disparan los validadores, entre otras cosas, para internacionalizar la aplicación  Para ello, en los message-bundles sobrescribimos los mensajes predefinidos haciendo referencia a los códigos de identificación de cada mensaje.  Ejemplo:
  • 109. Código mensaje javax.faces.converter.Integer Converter. INTEGER {2}: "{0}" must be a number consisting of one or more digits. javax.faces.converter.Integer Converter.INTEGER_detail {2}: "{0}" must be a number between -2147483648 and 2147483647. Example: {1} javax.faces.converter.DoubleC onverter.DOUBLE {2}: "{0}" must be a number consisting of one or more digits. javax.faces.converter.DoubleC onverter.DOUBLE_detail {2}: "{0}" must be a number between 4.9E-324 and 1.7976931348623157E308.Exampl e: {1} javax.faces.converter.Boolean Converter.BOOLEAN_detail {1}: "{0}" must be 'true' or 'false'. Any value other than 'true' will evaluate to
  • 110.  JSF permite validar el contenido de diferentes datos.  Podemos usar el atributo validator para apuntar al método de una bean que realiza validación.  Los validadores se pueden registrar en las clases que implementan EditableValueHolder.  En caso de no cumplirse la validación han de lanzar ValidatorException coteniendo un FacesMassage con el error.
  • 111.  La clase DoubleRangeValidator con tag f:validateDoubleRange: ◦ Valida un valor que puede ser convertido a coma flotante. ◦ Mira que este entre dos valores dados, minimum- maximum.  La clase LengthValidator con tag f:validateLength.  Mira que la longitud de la cadena este entre un mínimo y un máximo  La clase LongRangeValidator con tag f:validateLongRange  Para valores que se puedan convertir a long.  Mira que este entre dos valores dados.
  • 113.  Para comprobar que un dato está presente, no hace falta ningún validador anidado, basta con establecer el atributo required a true. <h:inputText id="card" value="#{payment.card}" required="true”requiredMessage="#{msgs.campoRequerido}"> <f:validateLength minimum="13"/> </h:inputText> Taller práctico Modificar el piloto anterior para que además se requiera el campo cantidad.
  • 114.  Modificar la welcome.jsp para que: ◦ Los campos login y password sean obligatorios. ◦ La password tenga al menos 3 caracteres ◦ Se visualicen mensajes personalizados e internacionalizados.  Resuelto en piloto11.0
  • 115.  A partir del piloto anterior: ◦ Definir un bean Usuarios (y declararlo como usuario) que contenga un ArrayList con un UsuarioBean por cada usuario que queramos en la aplicación. ◦ Modificar el proceso de login para que el proceso se realice contra los usuarios del bean Usuarios. ◦ Crear una página registro.jsp y un backingbean RegistroForm con un método registro que reciba login y password y añada el nuevo usuario al bean usuarios. ◦ Enlazar desde welcome.jsp a registro.jsp con: <h:outputLink value="registro.jsf"> <f:verbatim>Nuevo usuario</f:verbatim> </h:outputLink> Resuelto en piloto 12.0
  • 116.  En entornos de desarrollo de tipo cliente/servidor estamos acostumbrados a poder asociar eventos de tipo onClick o onChange a los componentes visuales de la pantalla.  En Web, dado que trabajamos sobre Http... ¿Se puede hacer esto?  JSF, al igual que otras plataformas como .NET simula esto encapsulando el evento en una request que es enviada al servidor sin llegar a disparar la acción del formulario.
  • 117.  JSF soporta tres tipos de eventos: ◦ Value change events  Disparados por elementos UIInput cuando el valor que contienen cambia. ◦ Action events  Los disparan los elementos UICommand cuando el botón o enlace asociado es activado. ◦ Phase Events  Son disparados rutinariamente por el ciclo de vida JSF.
  • 118.  Pensados para elementos dependientes en los formularios. Ej: Combo de paises + combo provincias. <h:selectOneMenu value="#{form.country}" onchange="submit()" valueChangeListener="#{form.countryChanged}"> <f:selectItems value="#{form.countryNames}"/> </h:selectOneMenu>  Esto dispara el método form.countryNames que se espera recibir un evento... public void countryChanged(ValueChangeEvent event) { FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale(new Locale( (String) event.getNewValue())); }
  • 119. Método Descripción UIComponent getComponent() Retorna una referencia al objeto que disparó el evento. Object getNewValue() Retorna el nuevo valor Object getOldValue() Retorna el valor antiguo Los heredados de FacesEvent... void queue() Encola el evento para que sea disparado al final del ciclo de vida actual PhaseId getPhaseId() Devuelve el id de la fase en la que nos encontramos. void setPhaseId(PhaseId) Marca el evento con el identificador de la fase en la que fue añadido a la cola.
  • 120.  Modificar el piloto para que el combo del idioma que se muestra en la página welcome tenga asociado un manejador de evento idiomaCambiado en loginForm de forma que cambie el idioma de la aplicación. Para ello: ◦ Asociamos el evento al componente y al manejador de evento en la jsp. ◦ Implementamos el manejador en loginForm de forma que establezca el nuevo idioma obteniendo la referencia al ViewRoot por medio de FacesConfig. Resuelto en piloto 13.0
  • 121.  Modificar entrada.jsp para que cuando cambie el combo del formulario, a su derecha se muestre el valor del libro seleccionado.  Para ello: ◦ Asociamos el evento onValueChange a un método productoSeleccionado del CarritoForm ◦ Creamos un objeto UIOutput en la jsp que tome el valor de un campo de tipo Integer del CarritoForm. Resuelto en piloto 14.0
  • 122.  Son disparados por los objetos UICommand cuando se activa el componente  Se invocan durante la fase Invoke Application <h:commandLink actionListener="#{bean.linkActivated}"> ... </h:commandLink>  Cuando se activa el componente, el formulario se envía y el controlador dispara los eventos.  Entonces... ¿En qué se diferencian de los actions?
  • 123.  Actions: ◦ Diseñados para la lógica de negocio. ◦ Deciden sobre la navegabilidad del sistema  Action listeners: ◦ Orientados a ejecutar lógica de presentación. ◦ No pueden decidir qué mensaje se envía al controlador.  Los dos tipos de elementos trabajan coordinadamente cuando el Action requiere información del interfaz de usuario.  Ejemplo: Una imagen enlazada que dependiendo de la zona pulsada, generará una redirección u otra.
  • 124.  Enlace en la JSP: <h:commandButton image="mountrushmore.jpg" actionListener="#{rushmore.listen}" action="#{rushmore.act}"/> En el backing bean... private String outcome; private Rectangle washingtonRect = new Rectangle(70,30,40,40); private Rectangle jeffersonRect = new Rectangle(115,45,40,40); public void listen(ActionEvent e) { FacesContext context = FacesContext.getCurrentInstance(); String clientId = e.getComponent().getClientId(context); Map requestParams = context.getExternalContext().getRequestParameterMap(); int x = new Integer((String) requestParams.get(clientId + ".x")).intValue(); int y = new Integer((String) requestParams.get(clientId + ".y")).intValue(); outcome = null; if (washingtonRect.contains(new Point(x,y))) outcome = "washington"; ... public String act() { return outcome; }
  • 125.  En primer lugar, creamos un nuevo método public void listen(ActionEvent e) en el CarritoForm que muestre un mensaje por pantalla demostrando que ha sido invocado.  Lo asociamos al botón de submit del formulario de la página entrada.jsp. ¿Cuál se dispara primero?
  • 126.  Extender la versión anterior para: ◦ Desligar al botón de submit del listener ◦ Crear un enlace activo (h:commandLink) que:  no tenga atributo action  Esté asociado al listener que hemos creado  Se represente con la cadena de texto Incrementa ◦ Modificar el método listen para que cada vez que se ejecuta, además de mostrar el mensaje:  Tome el string del UIInput cantidad  Cree un entero y le sume uno  Estableza de nuevo el valor calculado en el componente cantidad. Resuelto en piloto 15.0
  • 127.  Hasta ahora hemos asociado los listeners por medio de los atributos de los elementos HTML.  Esto mismo se puede realizar utilizando dos etiquetas: ◦ f:actionListener ◦ f:valueChangeListener  Ventajas sobre la alternativa anterior: Puede asociar varios listeners diferentes al mismo elemento.
  • 128.  Diferencias en la aplicación: ◦ Versión con el atributo <h:selectOneMenu value="#{form.country}" onchange="submit()" valueChangeListener="#{form.countryChanged}"> <f:selectItems value="#{form.countryNames}"/> </h:selectOneMenu> ◦ Versión con f:valueChangeListener: <h:selectOneMenu value="#{form.country}" onchange="submit()"> <f:valueChangeListener type="com.corejsf.CountryListener"/> <f:selectItems value="#{form.countryNames}"/> </h:selectOneMenu> No es una method expression sino una clase!
  • 129.  La clase listener para los eventos de cambio de valor tiene que implementar una determinada interfaz: ValueChangeListener public class CountryListener implements ValueChangeListener { public void processValueChange(ValueChangeEvent event) { ... } }  El controlador invoca el método processValueChange tras cada cambio.
  • 130.  Similar a la anterior: <f:actionListener type=" com.corejsf. RushmoreListener "/>  Y la clase, implementando la interfaz ActionListener: public class RushmoreListener implements ActionListener { public void processAction(ValueChangeEvent event) { ... } }
  • 131.  Crear una clase LibroCambiadoListener que implemente la interfaz ValueChangeListener  Implementar su método processValueChange para que saque un mensaje.  Asociarla a la etiqueta del combo de la págin entrada.jsp. Ojo! Hay que quitar el atributo que la liga al otro listener, son dos alternativas incompatibles! Resuelto en piloto 16.0
  • 132.  Problema: En casos como el combo de cambio de idioma, se nos están disparando los validadores que conviven dentro del mismo formulario. ¿Porqué? Se disparan los validadores y conversores Se procesan los eventos
  • 133.  Si marcamos un componente como inmediato: <h:selectOneMenu binding="#{loginForm.idioma}" onchange="submit()” valueChangeListener="#{loginAction.idiomaCambiado}" immediate="true">
  • 134.  Problema: ◦ El ciclo de vida sigue si rumbo normal tras la validación y procesado de eventos de los componentes inmediatos  Solución: ◦ Cortamos el flujo desde el listener y forzamos la renderización de la respuesta (el atajo en el gráfico anterior) context.renderResponse(); Taller práctico  Hacerlo sobre la versión actual del piloto para el cambio de idioma en el login ¿Comandos inmediatos?  En el caso de los comandos, también podemos hacerlos inmediatos, pero no hacer falta forzar el renderizado porque al terminar van directos a dicha fase.
  • 135.  Supongamos que queremos hacer la internacionalización con dos banderas, una por idioma, haciendo que ambas sean commandLinks: <h:commandLink action="#{localeChanger.englishAction}" immediate="true"> <h:graphicImage value="/british_flag.gif"/> </h:commandLink>  En el servidor: public class ChangeLocaleBean { public String germanAction() { FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale(Locale.GERMAN); return null; } public String englishAction() { FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale(Locale.ENGLISH); return null; } }
  • 136.  Problema: ◦ Estamos definiendo métodos que son prácticamente iguales –repetimos lógica- y que en orientación a objetos podría ser uno solo parametrizado.  Solución: ◦ Envío de información desde la interfaz al usuario. ◦ Métodos:  f:param  f:setPropertyActionListener  f:attribute
  • 137.  Nos permite adjuntarle un parámetro a un componente.  Se comporta diferentemente dependiendo del tipo de componente: ◦ Si lo usamos en un h:outputText, los distintos parámetros se usan para rellenar las variables ({0} is bigger than{1}) que se encuentren en el valor del componente. ◦ Si lo usamos en un UICommand, los parámetros se añaden como un parámetro de la request.
  • 138.  Para el ejemplo anterior: <h:commandLink immediate="true” action="#{localeChanger.changeLocale}"> <f:param name="languageCode" value="de"/> <h:graphicImage value="/german_flag.gif" style="border: 0px"/> </h:commandLink>  En el servidor: public String changeLocale() { FacesContext context = FacesContext.getCurrentInstance(); String languageCode = getLanguageCode(context); context.getViewRoot().setLocale(new Locale(languageCode)); return null; } private String getLanguageCode(FacesContext context) { Map<String,String> params=context.getExternalContext().getRequestParameterMap(); return params.get("languageCode"); }
  • 139.  Crear en LoginForm un nuevo método idiomaCambiado() que recupere el parámetro nuevoIdioma de la request y establezca el nuevo Locale  Añadir dos etiquetas de comando, una por idioma, a la entrada.jsp, estableciendo como atributo action (no actionListener!) e inmediato = true; Resuelto en trabajo 17.0
  • 140.  Similar, pero en lugar de añadirlo a la request, se añade como atributo al componente, por lo que tenemos que usar action listeners (reciben el componente en el evento!) <h:commandLink immediate="true” actionListener="#{localeChanger.changeLocale}"> <f:attribute name="languageCode" value="de"/> <h:graphicImage value="/german_flag.gif" style="border: 0px"/> </h:commandLink>  En el servidor public void changeLocale(ActionEvent event) { UIComponent component = event.getComponent(); String languageCode = getLanguageCode(component); FacesContext.getCurrentInstance().getViewRoot().setLocale(new Locale(languageCode)); } private String getLanguageCode(UIComponent component) { Map<String, Object> attrs = component.getAttributes(); return (String) attrs.get("languageCode"); }
  • 141.  Desde JSF 1.2, establece una propiedad directamente en nuestro backing bean... <h:commandLink immediate="true” action="#{localeChanger.changeLocale}"> <f:setPropertyActionListener target="#{localeChanger.languageCode}” value="de"/> <h:graphicImage value="/german_flag.gif" style="border: 0px"/> </h:commandLink>  En el servidor... public class ChangeLocaleBean { private String languageCode; public String changeLocale() { FacesContext context = FacesContext.getCurrentInstance(); context.getViewRoot().setLocale(new Locale(languageCode)); return null; } public void setLanguageCode(String newValue) { languageCode = newValue; } }
  • 142.
  • 143. <converter> <description>Converter for credit card numbers that normalizes the input to a standard format</description> <converter-id>CreditCardConverter</converter-id> <converter-class> converters Cred itCardConverter </converter-class> </converter>
  • 145.  Podemos registrar componentes visuales propios <component> <component-type>DemoArea</component-type> <component-class>components.AreaComponent</component-class> <property> <property-name>alt</property-name> <property-class>java.lang.String</property-class> </property> <property> <property-name>coords</property-.name> <property-class>java.lang.String</property-class> </property> <property> <property-name>shape</property-name> <property-class>java.lang.String</property-class> </property> <component-extension> <component-family>Area</component-family> <renderer-type>DemoArea</renderer-type> </component-extension> </component>
  • 146.  Muestra una imagen.  Propiedades de un, alt (texto alternativo, normalmente mostrado al pasar el ratón por encima) y demás relativas al uso común en html (en la renderización típica Html).  <h:graphiclmage…./>
  • 147.  Indica un dato de salida  Con el Renderizador de Html tenemos ◦ outputLabel  Su atributo ‘for’ apunta a un id de un campo de entrada con el que se encuentra asociada la etiqueta ◦ outputLink  Necesita una etiqueta verbatim que muestra el texto que el usuario clickea para lanzar el link
  • 148. ◦ outputFormat que muestra un mensaje  Permite la utilización de java.text.MessageFormat.  Value indica la frase a parametrizar normalmente de un ResourceBoundle.  Tiene etiquetas de tipo <f:param value...> para indicar los parámetros del mensaje. ◦ outputText que muestra un texto de una línea