You are on page 1of 6

JSF 2.

0: Managed Beans
JSF es un framework para desarrollar UIs en aplicaciones web Java EE. Sigue el diseo Modelo-Vista-Controlador: - Modelo: contiene la lgica de negocio (managed beans) - Vista: son las interfaces grficas de usuario (pginas JSF) - Controlador: gestiona las peticiones del usuario, mostrando en cada ocasin la vista apropiada (FacesServlet) El servlet FacesServlet ya viene implementado, con lo que no tenemos que hacerlo nosotros. Cuando el controlador recibe una peticin, comprueba si sigue un patrn definido en el fichero web.xml, como por ejemplo /faces/*. Si es as, la considera una 'Faces Request' y al procesarla crea un objeto conocido como JSF context, que contiene los datos y la navegacin correspondiente a las vistas apropiadas. Esta informacin se encuentra en el fichero faces-config.xml, que se conoce como 'JSF Navigation Model'. Este fichero contiene toda la posible navegacin entre las pginas JSF de nuestra aplicacin. Veamos un ejemplo de regla de navegacin entre pginas: <navigation-rule> <from-view-id>/page1.xhtml</from-view-id> <navigation-case> <from-outcome>success</from-outcome> <to-view-id>/page2.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>failure</from-outcome> <to-view-id>/page3.xhtml</to-view-id> </navigation-case> </navigation-rule> Con esta regla de navegacin, desde la pgina page1.xhtml, podemos ir a page2.xhtml si todo ha ido bien o a page3.xhtml si ha ocurrido un error. En posteriores post veremos cmo devolver 'success' o 'failure' para saber as a qu pgina hay que ir. El ciclo de vida de JSF procesa la peticin del usuario con sus datos de entrada, haciendo que el desarrollador no necesita escribir cdigo para procesarla. Por ejemplo, cuando pinchamos sobre un botn en tiempo de ejecucin, se activa automticamente este ciclo de vida. <h:commandButton value="I am a button"/> Managed Beans (I) : Como ya hemos visto anteriormente, JSF separa la capa de presentacin de la lgica de negocio. Para que nuestras pginas JSF puedan acceder a esta lgica, utilizamos managed beans. Un bean es un POJO (Plain Old Java Object), algo tan sencillo como una clase que tiene un constructor pblico sin argumentos (constructor por defecto) y sus propiedades tienen asociados sus correspondientes mtodos get/set .Si en una clase no indicamos ningn constructor, el compilador le aade este constructor por defecto. Hay que tener en cuenta que si escribimos en la clase un constructor no vacio, ya no se nos aadir en tiempo de compilacin este constructor por defecto. No necesitamos instanciarlos con new(), ya que son inicializados por su contenedor en tiempo de ejecucin cuando la aplicacin los necesita. 1pgina JSF lee los valores d las propiedades del bean q tiene asociada, y cuando se hace 1 post d 1formulario, se guardan sus valores en el bean (luego veremos cmo funciona el Ciclo Vida JSF y sabremos en q momento se guardan esos valores). Cmo declaramos un bean? Desde el fichero faces-config.xml o con anotaciones. Utilizando el fichero faces-config.xml <managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>com.examples.UserBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> Siendo desarrolladores, puede que alguna vez le hayamos cogido mana a los ficheros de configuracin .xml... s, no pasa nada por reconocerlo, tambin somos humanos ;D Por eso, desde q Java 5 introdujo las anotaciones todo es mas facil Utilizando anotaciones package com.examples; import javax.faces.bean.ManagedBean import javax.faces.bean.SessionScoped @ManagedBean @SessionScoped public class UserBean {...} Una vez declarado nuestro bean de ejemplo, una pgina JSF puede acceder a l utilizando el nombre userBean ya que, si no indicamos ningn nombre concreto, por defecto se le asigna el nombre de la clase con la primera letra en minscula. @ManagedBean(name="user") @SessionScoped public class UserBean {...} En este nuevo ejemplo vemos que ahora el nombre del bean es user.

JSF 2.0: Managed Beans


Managed Beans (II) : Cmo inicializar las propiedades de 1 bean, q pasa cuando son propiedades d tipo array, List o Map y cmo declarar 1bean directamente como 1 List o 1 Map. 1. Cmo inicializamos las propiedades de un bean? Utilizando anotaciones @ManagedBean @SessionScoped public class UserBean { @ManagedProperty(value="Ana") private String name ... } Utilizando el fichero faces-config.xml <managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>com.examples.UserBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>name</property-name> <value>Ana</value> </managed-property> </managed-bean> En <value> podemos hacer referencia a otro bean con expresiones del tipo #{adress}. Tambin podemos poner a null una propiedad: <managed-property> <property-name>nick</property-name> <null-value/> </managed-property> 2. Cmo inicializamos propiedades de tipo array o java.util.List? Tenemos q hacerlo en el fichero faces-config.xml y no con anotaciones, ya que no existe ninguna sintxis que nos permita hacerlo. <managed-property> <property-name>colores</property-name> <list-entries> <value>Rojo</value> <value>Verde</value> <value>Amarillo</value> </list-entries> </managed-property> Desde nuestra pgina JSF, podemos acceder a estos valores: <h:outputText value="#{userBean.colores[2]}"/>. El por qu accedemos de esta manera a las propiedades de 1bean lo veremos en 1post posterior, ahora quedaros con la idea. Si nuestro array no contiene Strings, como en el ejemplo anterior, sino x ejemplo enteros, tendramos q indicarlo asi : <managed-property> <property-name>numHabitaciones</property-name> <list-entries> <value-class>java.lang.Integer</value-class> <value>1</value> <value>2</value> <value>3</value> </list-entries> </managed-property>

JSF 2.0: Managed Beans


3. Cmo inicializamos propiedades de tipo java.util.Map? Tambin tenemos que hacerlo en el fichero faces-config.xml. <managed-property> <property-name>colores</property-name> <map-entries> <map-entry> <key>Rojo</key> <value>No puedes continuar</value> </map-entry> <map-entry> <key>Verde</key> <value>Puedes continuar</value> </map-entry> </map-entries> </managed-property> Desde nuestra pgina JSF, podemos acceder a estos valores: <h:outputText value="#{userBean.colores['Verde']}"/> Como hemos visto antes, aqu se utilizan Strings por defecto. Si quisiramos que nuestras keys fueran enteros, haramos lo siguiente: <map-entries> <key-class>java.lang.Integer</key-class> <map-entry> <key>1</key> ... </map-entries> 4. Cmo declaramos un List o Map como un managed bean directamente? <managed-bean> <managed-bean-name>colores</managed-bean-name> <managed-bean-class>java.util.ArrayList</managed-bean-class> <managed-bean-scope>none</managed-bean-scope> <list-entries> <value>Rojo</value> <value>Amarillo</value> <value>Verde</value> </list-entries> </managed-bean> Si nos fijamos en el ejemplo, vemos que el scope del bean se ha puesto a none. Esto significa que el bean no va a ser almacenado en ningn sitio, sino que va a ser instanciado siempre que se necesite. Tambin podemos hacer que un bean referencie a otro bean de la siguiente manera: <managed-bean> <managed-bean-name>datosBean</managed-bean-name> <managed-bean-class>com.examples.DatosPersonalesBean</managed-bean-class> <managed-bean-scope>none</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>com.examples.UserBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> <managed-property> <property-name>datos</property-name> <value>#{datosBean}</value> </managed-property> </managed-bean> Con anotaciones sera: @ManaqedProperty(value="#{datosBean}") private DatosPersonalesBean datos;

JSF 2.0: Managed Beans


Managed Beans(III): Hemos visto q cuando se declara 1 bean, tenemos q darle 1 scope: application, session, view, request, none. Un scope es 1mapeo entre nombres y objetos q se almacena durante 1determinado periodo de tiempo. vamos a explicar cada uno de ellos. Si declaramos el bean desde el fichero faces-config.xml, indicamos el scope en <managed-bean-scope> y si queremos hacerlo con anotaciones, utilizaremos @{Application,Session,View,Request,None}Scoped Application : Con este scope, se guarda la informacin durante toda la vida de la aplicacin web, independientemente de todas las peticiones y sesiones que se realicen. Este bean se instancia con la primera peticin a la aplicacin y desaparece cuando la aplicacin web se elimina del servidor. Si queremos que el bean se instancie antes de que se muestre la primera pgina de la aplicacin, usamos la propiedad eager a true. @ManagedBean(eager=true) <managed-bean eager="true"> Session : Como su mismo nombre indica, este scope guarda la informacin desde que el usuario comienza una sesin hasta que sta termina (porque el tiempo expir o se invoc al mtodo invalidate sobre un objeto HttpSession). HTTP es un protocolo sin estado, y por tanto, una vez que se enva una peticin al servidor y ste responde, no se guarda ninguna informacin sobre esta transicin. Esto no es siempre adecuado en aplicaciones de lado de servidor, ya que es normal que necesiten ir guardando el estado. Para ello, podemos utilizar: - Cookies: pares nombre-valor que el servidor enva al usuario, confiando en que en posteriores peticiones se la vaya "devolviendo" - URL rewriting: aade un identificador de sesin a la URL Los beans de sesin no son single-threaded. Los usuarios podran mandar peticiones desde varios navegadores a la vez, manejada cada una de ellas por un hilo diferente. Si necesitamos que sea thread-safe, tenemos que implementar mecanismos de bloqueo. View (a partir de JSF 2.0) : El scope dura desde q se muestra 1 pgina JSF al usuario hasta q el usuario navega hacia otra pgina. Es muy til para pginas q usan AJAX. Request : Comienza cuando se enva una peticin al servidor y termina cuando se devuelve la respuesta al usuario. Esto hace que se cree una instancia del bean asociado para cada peticin. Los mensajes de estado y de error que se muestran al usuario son buenos candidatos a ser request, ya que se muestran una vez que el servidor devuelve la respuesta. Son single-threaded y por lo tanto, thread-safe. None : Los beans se instancian cuando son necesitados por otros beans, y se eliminan cuando esta necesidad desaparece. Desde JSF 2.0, tambin se permite crear scopes customizados (@CustomScoped) donde el tiempo que dura este scope lo definimos nosotros. Por tanto la aplicacin se vuelve responsable de ir eliminando las instancias de los beans del mapeo. Cuando a un mtodo le asocias la anotacin @PostConstruct se ejecutar despus de la inicializacin del bean pero antes de que sea guardado en su scope correspondiente. Si al mtodo le asocias la anotacin @PreDestroy se ejecutar justo antes de que el bean sea eliminado del scope. Como buenas prcticas, se recomienda utilizar siempre el menor scope que necesite el bean, para evitar as posibles problemas de memoria al tener que almacenar ms informacin de la necesaria

JSF 2.0: Managed Beans


Managed Beans (IV) : JSF proporciona un Expression Language (EL) que nos permite acceder a las propiedades de nuestros beans. En post anteriores ya hemos visto algn ejemplo, pero en este post vamos a entrar en profundidad en este lenguaje. 1. Cmo podemos acceder a las propiedades de un bean? Podemos utilizar diferentes maneras de acceso, todas ellas equivalentes: a.b // #{userBean.name} a["b"] // #{userBean["name"]} a['b'] // #{userBean['name']} Tambin podemos utilizar operadores aritmticos, relacionales, lgicos, ternario o ver si es empty. <h:outputText rendered="#{userBean.profile=='VIP'}" value="Bono regalo de #{bono.base*7} Euros"/> <h:commandButton value="Aceptar" action="#{userBean.registerUser}"/> 2. Se pueden invocar mtodos con parmetros? Desde JSF 2.0 s, pero mtodos que no estn sobrecargados. Ej. #{bean.metodo("a")} 3. Cmo se accede a un bean desde Java? Podemos acceder de diferentes maneras. Vemoslo programticamente con unos ejemplos: FacesContext ctx = FacesContext.getCurrentInstance(); ELContext ec = ctx.getELContext( ); Application app = ec.getApplication( ); String name = (String) app.evaluateValueExpressionGet(ctx,"#{userBean.name}",String.class); ---------------------------------ExpressionFactory ef = app.getExpressionFactory( ); ValueExpression ve =.ef.createValueExpression(ec,"#{userBean.name}",String.class); name = (String) ve.getValue(ec); ve.setValue(ec, "Serena"); ---------------------------------ValueExpression ve = ef.createValueExpression(ec,"#{userBean}",UserBean.class); UserBean ub = (UserBean) ve.getValue(ec); ub.setName("Serena"); 4. Qu son los objetos implcitos? Son unos objetos que ya vienen predefinidos: applicationScope, cc, component, cookie, facesContext, flash, header, headerValues, initParam, param, paramValues, requestScope, resource, sessionScope, view, viewScope. Ej. header['User-Agent'] es el valor del parmetro User-Agent de la peticin HTTP. 5. Cmo se resuelven las expresiones? Si nuestra expresin no contiene 1objeto implcito, se busca si el bean est en el scope request, view, session o application, en este orden, ya q todos los beans instanciados se almacenan aqu. Si no se encuentran en estos scopes, entonces se instancia el bean. Veamos esto mejor con un ejemplo: <managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>com.examples.UserBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> La primera vez que se accede a #{userBean.name}, como no es un objeto implcito, se le busca entre los distintos scopes. Como la primera vez todava no se encuentra en ninguno, se busca el managed bean que tenga el nombre userBean y se llama al constructor por defecto de su clase correspondiente (com.examples.UserBean). Despus, se asocia al scope session (<managed-beanscope>session</managed-bean-scope>). As, la prxima vez q se acceda a este bean, s estar en el scope session

JSF 2.0: Managed Beans


JSF 2.0: Navegacin (I) Navegacin de una aplicacin JSF.
La navegacin ms sencilla en JSF consiste en asociar un String al action de un botn o link: <h:commandButton label="Aceptar" action="login"/> <h:commandLink action="login"> <h:outputText value="Aceptar"/> </h:commandLink> En este ejemplo, pinchar en el botn o el link nos llevar a la pgina JSF asociada al String "login". Si queremos poder elegir la pgina a mostrar en tiempo d ejecucin, asociamos el action a 1mtodo q nos devuelva el String correspondiente: <h:commandButton label="Aceptar" action"#{userBean.login}"/> En este ejemplo, al pinchar el botn se ejecuta el mtodo login() del bean userBean, devolviendo ste un String que indicar la siguiente pgina a mostrar. Estos mtodos tienen que ser pblicos, sin argumentos y devolver un String. public String login() { return "login"; } Cmo asociamos el String del action con una pgina JSF? : Creando reglas de navegacin en el fichero faces-config.xml: <navigation-rule> <from-view-id>/index.xhtml</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/login.xhtml</to-view-id> </navigation-case> <navigation-case> <from-outcome>register</from-outcome> <to-view-id>/register.xhtml</to-view-id> </navigation-case> </navigation-rule> En este ejemplo podemos ver que desde la pgina index.xhtml podemos ir a login.xhtml o a register.xhtml dependiendo si el action devuelve "login" o "register" respectivamente. Omitir <from-view-id> o ponerlo como <from-view-id>*</from-view-id> es equivalente. El wildcard '*' se puede utilizar una sola vez y siempre al final (ej. <from-view-id>/pages/*</from-view-id>). Tambin podemos utilizar el mismo <from-outcome> y diferenciarlos segn la accin que se realice: <navigation-case> <from-action>#{userBean.login}</from-action> <from-outcome>success</from-outcome> <to-view-id>/login.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{userBean.registerUser}</from-action> <from-outcome>success</from-outcome> <to-view-id>/register.xhtml</to-view-id> </navigation-case> En este ejemplo no se llama al mtodo que est entre #{}, ya que esto se realiza dinmicamente desde una pgina, simplemente se asocia al action correspondiente. Tenemos que utilizar obligatoriamente faces-config.xml? No. Desde JSF 2.0 podemos utilizar navegacin implcita, es decir, nos basta con poner en el action el nombre de nuestra pgina JSF sin la extensin correspondiente. <h:commandButton action="login"/> nos llevara a la pgina login.xhtml Se puede navegar a una pgina dependiendo de si se cumple una condicin? Desde JSF 2.0 s. <navigation-case> <from-outcome>login</from-outcome> <if>#{userBean.profile != 1}</if> <to-view-id>/login.xhtml</to-view-id> </navigation-case>

You might also like