Una Sencilla Aplicación JavaServer Faces
Esta sección describe el proceso de desarrollo de una sencilla aplicación JavaServer Faces. Veremos qué características contiene una típica aplicación JavaServer Faces, y qué hace cada rol en el desarrollo de la aplicación.
Pasos del Proceso de Desarrollo
Desarrollar una sencilla aplicación JavaServer Faces requiere la realización de estos pasos:
- Desarrollar los objetos del modelo, los que contendrán los datos.
- Añadir las declaraciones del bean controlado al fichero de configuración de la aplicación.
- Crear las páginas utilizando las etiquetas de componentes UI y las etiquetas "core".
- Definir la navegación entre las páginas.
Estas tareas se pueden realizar simultáneamente o en cualquier orden. Sin embargo, la gente que realice las tareas necesitará comunicarse durante el proceso de desarrollo. Por ejemplo, el autor de las páginas necesita saber los nombres de los objetos del modelo para poder acceder a ellos desde la página.
Este ejemplo nos pedirá que adivinemos un número del 0 al 10, ambos inclusives. La segunda página nos dirá si hemos acertado. El ejemplo también chequea la validez de nuestra entrada.
Desarrollar los Objetos del Modelo
Desarrollar los objetos del modelo es responsabilidad del desarrollador de aplicaciones. El autor de las páginas y el desarrollador de aplicaciones podrían necesitar trabajar juntos para asegurarse que las etiquetas de componentes se refieren a las propiedades del objeto apropiado, que las propiedades del objeto son de los tipos apropiados, y para tener cuidado de otros detalles.
Aquí tenemos la clase UserNumberBean.java que contiene los datos introducidos en el campo de texto de la página greeting.jsp:
package guessNumber;
import java.util.Random;
public class UserNumberBean {
Integer userNumber = null;
Integer randomInt = null;
String response = null;
public UserNumberBean () {
Random randomGR = new Random();
randomInt = new Integer(randomGR.nextInt(10));
System.out.println("Duke’s Number: "+randomInt);
}
public void setUserNumber(Integer user_number) {
userNumber = user_number;
System.out.println("Set userNumber " + userNumber);
}
public Integer getUserNumber() {
System.out.println("get userNumber " + userNumber);
return userNumber;
}
public String getResponse() {
if(userNumber.compareTo(randomInt) == 0)
return "Yay! You got it!";
else
return "Sorry, "+userNumber+" is incorrect.";
}
}
Como podemos ver, este bean es como cualquier otro componente JavaBeans. Tiene un método set o accesor y un campo privado o propiedad. Esto significa que podemos concebir referenciar beans que ya hayamos escrito desde nuestras páginas JavaServer Faces.
Dependiendo del tipo de componente que referencia una propiedad del objeto del modelo, esta propiedad puede ser de cualquiera de los tipos básicos primitivos y los tipos referencia. Esto incluye cualquiera de los tipos numéricos, String, int, double, y float. La tecnología JavaServer Faces convertirá automáticamente el dato al tipo especificado por la propiedaded del objeto del modelo.
También podemos aplicar una conversión a un componente para convertir los valores de los componentes a un tipo que no esté soportado por el componente.
En el UserNumberBean, la propiedad userNumber es del tipo Integer. La implementación de JavaServer Faces puede convertir el String de los parámetros de la solicitud que contiene este valor a un Integer antes de actualizar la propiedad del objeto del modelo cuando utilicemos una etiqueta input_number. Aunque este ejemplo lo convierte a un Integer, en general, deberíamos utilizar tipos nativos en vez de utilizar las clases envoltura (int en lugar de Integer).
Añadir las Declaraciones del Bean Controlado
Después de desarrollar los beans utilizados en la aplicación, necesitamos añadir declaraciones para ellos en el fichero de configuración de la aplicación. Cualquier miembro del equipo de desarrollo puede realizar la trarea de añadir las declaracones al fichero de configuración de la aplicación. Aquí tenemos la declaración de bean controlado para UserNumberBean:
<managed-bean>
<managed-bean-name>UserNumberBean</managed-bean-name>
<managed-bean-class>
guessNumber.UserNumberBean
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
La implementación de JavaServer Faces procesa este fichero en el momento de arrancada de la aplicación e inicializa el UserNumberBean y lo almacena en el ámbito de sesión. Entonces el bean estará disponible para todas las páginas de la aplicación. Para aquellos que estén familiarizados con versiones anteriores, esta facilidad de "bean controlado" reemplaza la utilización de la etiqueta jsp:useBean.
Crear las Páginas
La creacción de las páginas es responsabilidad del autor de páginas. Esta tarea implica distribuir los componentes UI en las páginas, mapear los componentes a los datos de los objetos del modelo, y añadir otras etiquetas importanes (como etiquetas del validador) a las etiquetas de los componentes. Aquí tenemos la página greeting.jsp con las etiquetas de validador (menos los HTML que lo rodea):
<HTML>
<HEAD> <title>Hello</title> </HEAD>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<body bgcolor="white">
<h:graphic_image id="wave_img" url="/wave.med.gif" />
<h2>Hi. My name is Duke.
I'm thinking of a number from 0 to 10.
Can you guess it?</h2>
<f:use_faces>
<h:form id="helloForm" formName="helloForm" >
<h:graphic_image id="wave_img" url="/wave.med.gif" />
<h:input_number id="userNo" numberStyle="NUMBER"
valueRef="UserNumberBean.userNumber">
<f:validate_longrange minimum="0" maximum="10" />
</h:input_number>
<h:command_button id="submit" action="success"
label="Submit" commandName="submit" /><p>
<h:output_errors id="errors1" for="userNo"/>
</h:form>
</f:use_faces>
Esta página demuestra unas cuantas características importantes que utilizaremos en la mayoría de nuestras aplicaciones JavaServer Faces:
- La etiqueta form:
Esta etiqueta representa un formulario de entrada, que permite al usuario introducir algún dato y enviarlo al servidor, normalmente pulsando un botón. Las etiquetas que representan los componentes que conforman el formulario se anidan dentro de la etiqueta form. Estas etiquetas son h:input_number y h:command_button.
- La etiqueta input_number:
Esta etiqueta representa un componente que es un campo de texto, dentro del que el usuario introduce un número. Esta etiqueta tiene tres atributos: id, valueRef, y numberStyle. El atributo id es opcional y corresponde al identificador ID del componente. Si no incluimos uno, la implementación JavaServer Faces generará uno automáticamente.
El atributo valueRef utiliza una expresión de referencia para referirse a la propiedad del objeto del modelo que contiene los datos introducidos en el campo de texto. La parte de la expresión que hay antes del "." debe corresponder con el nombre definido por el elemento managed-bean-name del bean controlado en el fichero de configuración. La parte de la expresión que hay después del "." debe corresponder con el nombre del elemento property-name correspondiente en la declaración del propio bean controlado. En este ejemplo, no se declararon elementos property-name porque no se inicializaron propiedades en la arrancada de la aplicación para este ejemplo.
El atributo numberStyle indica el nombre del patrón de estilo de número definido según la clase java.text.NumberFormat. Los valores válidos son: currency, integer, number, o percent.
- La etiqueta validate_longrange:
La etiqueta input_number también contiene una etiqueta validate_longrange, que es una del conjunto de etiquetas validadores estándar incluido con la implementación de referencia de JavaServer Faces.
Este validador chequea si el valor local de un componente está dentro de un cierto rango. El valor debe ser cualquier cosa que se pueda convertir a long. Esta etiqueta tiene dos atributos, uno que especifica un valor mínimo y otro que especifica un valor máximo. Aquí, la etiqueta se utiliza para asegurarnos de que el número introducido en el campo de texto es un número entre el 0 y el 10.
- La etiqueta command_button:
Esta etiqueta representa el botón utilizado para enviar los datos introducidos en el campo de texto. El atributo action especifica una salida que facilita al mecanismo de navegación la decisión de qué página abrir luego. La siguiente página describe esto en más detalle.
- La etiqueta output_errors:
Esta etiqueta mostrará un mensaje de error si el dato introducido en el campo de texto no cumple con las reglas especificadas por el validador. El mensaje de error se muestra en el lugar de la página donde hayamos situado la etiqueta output_errors.
Definir las Navegación por las Páginas
Otra posibilidad que tiene el desarrollador de la aplicación es definir la navegación de páginas por la aplicación, como qué página va después de que el usuario pulse un botón para enviar un formulario.
El desarrollador de la aplicación define la navegación por la aplicación mediante el fichero de configuración, el mismo fichero en el que se declararón los beans manejados. Aquí están las reglas de navegación definidas para el ejemplo guessNumber:
<navigation-rule>
<from-tree-id>/greeting.jsp</from-tree-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-tree-id>/response.jsp</to-tree-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-tree-id>/response.jsp</from-tree-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-tree-id>/greeting.jsp</to-tree-id>
</navigation-case>
</navigation-rule>
Cada regla de navegación define cómo ir de una página (especificada en el elemento from-tree-id) a otras páginas de la aplicación. El elemento navigation-rule puede contener cualquier número de elemento navigation-case, cada uno de los cuales define la página que se abrirá luego (definida por to-tree-id) basándose en una salida lógica (definida mediante from-outcome).
La salida se puede definir mediante el atributo action del componente UICommand que envía el formulario, como en el ejemplo guessNumber:
<h:command_button id="submit"
action="success" label="Submit" />
La salida también puede venir del valor de retorno del método invoke de un objeto Action. Este método realiza algún procesamiento para determinar la salida. Un ejemplo es que el método invoke puede chequear si la password que el usuario ha introducido en la página corresponde con la del fichero. Si es así, el método invoke podría devolver "success"; si no es así, podría devolver "failure". Un salida de "failure" podría resultar en la recarga de la página de logon. Una salida de "success" podría resultar en que se mostrara una página con las actividades de la tarjeta de crédito del usuario, por ejemplo.