Ir al contenido principal

JSF 2.0: Navegación (II)

En un  post anterior vimos los conceptos básicos de la navegación en una aplicación JSF. En este post vamos a ver conceptos más avanzados.

¿Cómo podemos mostrar la nueva página en la URL del navegador?

Si queremos que se muestre en la URL del navegador la página destino a la que vamos a navegar, y así dejemos de ver la página origen, tenemos que hacer una redirección. Esto hace que el navegador realice una nueva petición HTTP, en vez de mostrarnos sólo la respuesta del servidor sin realizar esta una nueva petición (en un post posterior veremos cómo funciona el ciclo de vida de JSF).
<h:commandButton label="Login" action"login?faces-redirect=true"/>
<navigation-case>
    <from-outcome>login</from-outcome>
    <to-view-id>/page2.xhtml</to-view-id>
    <redirect/>
</navigation-case>

Como buena práctica se recomienda asignar scope request a todos los beans que podamos. Por tanto, si se hace la redirección y el bean de la página actual es scope request, cuando se nos redirija a la nueva página, el bean anterior ya se habrá eliminado, perdiendo así toda la información que el usuario haya introducido. Para solucionarlo, JSF 2.0 nos proporciona el objeto flash, que se crea en una petición y puede ser usado también en la siguiente.

Así, en nuestra página origen pondríamos en nuestros componentes input como value #{flash.name} (por ejemplo), y en la página destino accederíamos a su valor con <h:outputText value="#{flash.keep.name}"/>.

Si queremos evitar el utilizar flash.keep.* en la página destino, podemos crear un método en el bean que obtenga los valores de este objeto y se los asigne a las propiedades del bean:
public void injectPropertiesFromFlash() {
   Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
   setName((String) flash.get("name"));
}

Ya sólo nos quedaría llamar a este método desde la página JSF destino:
<h:form>
    #{userBean.injectPropertiesFromFlash()}
    ...
    <h:outputText value="#{userBean.name}"/>

¿Se pueden realizar peticiónes HTTP GET en JSF?

Desde JSF 2.0 sí. Se diferencia de una petición HTTP POST en que tenemos que utilizar los componentes <h:button><h:link> en vez de <h:commandButton> y <h:commandLink>
<h:link value="Aceptar" outcome="login?myname=Ana"/>

Para transferir los parámetros de la query de la petición GET a las propiedades de nuestros beans, añadimos al principio de una página JSF la siguiente asociación entre parámetros y propiedades:
<f:metadata>
     <f:viewParam name="myname" value="#{userBean.name}"/>
</f:metadata>

En este ejemplo, asociamos el parámetro llamado myname a la propiedad #{userBean.name}. Si la URL de la petición HTTP GET fuera localhost:8080/myfirstapp/faces/index.xhtml?myname=Ana, se llamaría al método setName() del bean con Ana como argumento.

Cuando queramos que se incluyan todos los parámetros definidos en la página JSF, utilizamos el atributo includeViewsParams a true:
<h:button value="Aceptar" outcome="login?faces-redirect=true&amp;includeViewParams=true"/>

Si ocurre una excepción ¿Podemos hacer que se redirija a una página concreta?

Sí. En el fichero web.xml asociamos la excepción con la página de la siguiente manera:
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/sessionExpired.xhtml</location>
</error-page>

Enlace: Conceptos básicos sobre la navegación de una aplicación JSF

Comentarios

Entradas populares de este blog

Leer un fichero properties con java.util.Properties

Los ficheros .properties son simples ficheros de texto que se suelen utilizar para guardar parámetros de configuración, en forma de pares clave-valor. Ejemplo de fichero: configuration.properties #User parameters user.name=Ana user.language=spanish Si estamos usando Java, podemos utilizar la clase java.util.Properties para leer los parámetros de este fichero: private static final String USER_NAME = "user.name"; private static final String USER_LANGUAGE = "user.language"; public void showProperties() throws Exception { Properties p = new Properties(); InputStream is = App.class.getResourceAsStream("/configuration.properties"); p.load(is); is.close(); String userName = p.getProperty(USER_NAME); String userCountry = p.getProperty(USER_LANGUAGE); System.out.println("userName: "+userName); System.out.println("userLanguage: "+userCountry); } Después de ejecutar este método, obtendríamos la siguiente salida: ...

JSF 2.0: Managed Beans (III)

Anteriormente ya hemos visto que cuando se declara un bean, tenemos que darle un scope: application, session, view, request, none. Un scope es un mapeo entre nombres y objetos que se almacena durante un determinado periodo de tiempo. En este post 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 información durante toda la vida de la aplicación web, independientemente de todas las peticiones y sesiones que se realicen. Este bean se instancia con la primera petición a la aplicación y desaparece cuando la aplicación web se elimina del servidor. Si queremos que el bean se instancie antes de que se muestre la primera página de la aplicación, usamos la propiedad eager a true. @ManagedBean(eager=true) ó <managed-bean eager="true"> Session...

JSF 2.0: Message bundles

Los message bundles son ficheros .properties que guardan mensajes del tipo clave=valor. Si centralizamos todos los mensajes de nuestra aplicación en estos ficheros, es más fácil poder localizarlos si queremos realizar algún cambio y también nos ayuda para la internacionalización de la aplicación. Ejemplo: messages.properties (en src/java/com/examples) con dos mensajes name=Tu nombre: age=Tu edad: ¿Cómo los declaramos? 1) En cada página JSF donde lo necesitemos <f:loadBundle basename="com.examples.messages" var="msgs"/> 2) De manera global en faces-config.xml <application>      <resource-bundle>           <base-name>com.examples.messages</base-name>           <var>msg</var>      </resource-bundle> </application> Esta opción es más eficiente ya que sólo crea el bundle una v...