JBoss RichFaces. Capítulo 4. La aplicación.

18
4 La aplicación En este capítulo, vamos a comenzar a desarrollar nuestra aplicación web rica! Vamos a explicar todos los pasos para construir un proyecto vacío de la nada (con seam-gen), que soporta todas las tecnologías que se necesitan para desarrollar una "verdadera" aplicación JSF con Ajax. El objetivo de este libro no sólo debe ser una descripción de una tecnología, sino también queremos que el lector aprenda sobre el marco RichFaces, mientras que desarrolla de una aplicación real, de modo que puede estar listo para desarrollar su propia aplicación. La aplicación que hemos elegido es un administrador de contactos avanzada con una gran cantidad de "ricas" características que veremos en la siguiente sección. Después de crear el proyecto, vamos a empezar a buscar en las páginas y entender las páginas básica generadas así como el formulario de entrada, mientras que vamos haciendo algunas modificaciones en ellos. ¿ Qué es el lo que vamos a desarrollar ? El ejemplo que hemos desarrollado en el capítulo 3, primeros pasos fue básica. Ahora, vamos a desarrollar una aplicación avanzada de administración de contactos con una gran variedad de funciones. Durante el desarrollo de todas las características de la aplicación web, vamos a utilizar el marco Ajax RichFaces tanto como sea posible. También vamos a utilizar los componentes ricos que pone a nuestra disposición. La siguiente imagen muestra una maqueta simple de la aplicación que queremos desarrollar:

description

En este capítulo, vamos a comenzar a desarrollar nuestra aplicación web rica!Vamos a explicar todos los pasos para construir un proyecto vacío de la nada (con seam-gen), que soporta todas las tecnologías que se necesitan para desarrollar una "verdadera" aplicación JSF con Ajax.El objetivo de este libro no sólo debe ser una descripción de una tecnología, sino también queremos que el lector aprenda sobre el marco RichFaces, mientras que desarrolla de una aplicación real, de modo que puede estar listo para desarrollar su propia aplicación.La aplicación que hemos elegido es un administrador de contactos avanzada con una gran cantidad de "ricas" características que veremos en la siguiente sección.Después de crear el proyecto, vamos a empezar a buscar en las páginas y entender las páginas básica generadas así como el formulario de entrada, mientras que vamos haciendo algunas modificaciones en ellos.

Transcript of JBoss RichFaces. Capítulo 4. La aplicación.

Page 1: JBoss RichFaces. Capítulo 4. La aplicación.

4 La aplicación

En este capítulo, vamos a comenzar a desarrollar nuestra aplicación web rica! Vamos a explicar todos los pasos para construir un proyecto vacío de la nada (con seam-gen), que soporta todas las tecnologías que se necesitan para desarrollar una "verdadera" aplicación JSF con Ajax. El objetivo de este libro no sólo debe ser una descripción de una tecnología, sino también queremos que el lector aprenda sobre el marco RichFaces, mientras que desarrolla de una aplicación real, de modo que puede estar listo para desarrollar su propia aplicación. La aplicación que hemos elegido es un administrador de contactos avanzada con una gran cantidad de "ricas" características que veremos en la siguiente sección. Después de crear el proyecto, vamos a empezar a buscar en las páginas y entender las páginas básica generadas así como el formulario de entrada, mientras que vamos haciendo algunas modificaciones en ellos.

¿ Qué es el lo que vamos a desarrollar ? El ejemplo que hemos desarrollado en el capítulo 3, primeros pasos fue básica. Ahora, vamos a desarrollar una aplicación avanzada de administración de contactos con una gran variedad de funciones. Durante el desarrollo de todas las características de la aplicación web, vamos a utilizar el marco Ajax RichFaces tanto como sea posible. También vamos a utilizar los componentes ricos que pone a nuestra disposición. La siguiente imagen muestra una maqueta simple de la aplicación que queremos desarrollar:

Page 2: JBoss RichFaces. Capítulo 4. La aplicación.

Características Aquí está la descripción de las características principales de la aplicación Administrador Avanzado de Contactos.

Administrador de Grupos Cada contacto se puede poner en uno o más grupos para una mejor organización de sus datos. La lista de grupos de contacto que aparece dentro de una lista de colores con una herramienta de ventana de información emergente que muestra la descripción del grupo.

Subir archivos y notas El usuario será capaz de asociar los archivos (por ejemplo CV) y notas con "texto enriquecido", a los contactos. La carga de archivos le permitirá al usuario seleccionar más de un archivo a la vez y añadir una descripción de cada archivo mediante un asistente de panel modal.

Búsqueda simple Una simple búsqueda siempre estará disponible para el usuario. Él o ella será capaz de buscar contactos, filtrar éstos por su nombre y apellido.

El tema del usuario Cada usuario de la aplicación web puede elegir su propio tema y utilice durante el la sesion.

Multilenguaje Nuestra aplicación es real. Por lo tanto, aunque no tenga características de RichFaces (pero sí características JSF/Seam), para dar soporte a diferentes idiomas.

Page 3: JBoss RichFaces. Capítulo 4. La aplicación.

La base de datos: diagrama E-R Este es el diagrama ER (Entidad-Relación) de la base de datos que vamos a utilizar:

Sobre el diagrama E-R Un diagrama Entidad-Relación (ER), en definitiva, sirve para representar una base de datos relacional. En él se describe la información que se almacena en la base de datos en términos de las entidades y las conexiones entre ellas (relaciones). Una entidad es un objeto (por ejemplo, una persona o un grupo) que pueden ser identificados de forma unívoca y es independiente (es decir, que pueden "vivir" solas). Una relación se describe cómo dos o más entidades relacionadas entre sí.

Page 4: JBoss RichFaces. Capítulo 4. La aplicación.

Tanto las entidades y las relaciones pueden tener atributos. Para encontrar más acerca de los diagramas ER, se puede leer más en http://en.wikipedia.org/wiki/Entityrelationship_model. Como puede ver, es bastante simple, todo está en torno a la entidad de contacto. Cada contacto puede ser también un usuario de la aplicación web (con un nombre de usuario y una contraseña establecida). Además, los demás campos se puede asociar con un tipo diferente de campo personalizado (como dirección URL, correo electrónico, etc) y una etiqueta (casa, trabajo, etc, dependiendo del tipo). Un contacto puede tener una o más direcciones asociadas con una etiqueta (como el hogar, el trabajo, y así sucesivamente). Los usuarios pueden crear uno o más grupos de contactos con un color diferente para cada uno. Por último, una lista de archivos (como un CV o de otro tipo) se puede asociar a cada contacto. La base de datos está lista, podemos pasar a crear la estructura del proyecto y la API de persistencia Java (JPA) con entidades vinculadas a las tablas de base de datos.

¿ Qué es la JPA ? Hemos hablado acerca de JBoss Seam y Facelets, pero esta es la primera vez que hemos hablado sobre JPA. La JPA es el acrónimo de Java Persistence API y es el estándar API de persistencia y mapeo objeto/relacional para la plataforma Java (SE y EE). Este es otro de los diversos conocimientos de tecnología. Es muy útil para administrar (consultar, insertar, actualizar) datos persistentes conectado a un DBMS de una forma sencilla. El concepto principal es la entidad, que es un POJO que normalmente representa una tabla en una base de datos, y cada instancia de la misma representa una fila individual de la tabla. Para dar un ejemplo, si desea insertar una nueva fila en una tabla de base de datos, sólo tienes que crear una instancia de la clase de entidad que representa la tabla, a continuación, rellene los campos de la entidad con los datos, y llamar al método persistente para insertar una nueva fila en la base de datos. Usted no tiene que escribir una sola línea de SQL (JPA va a hacer ese trabajo por usted). Además, cuando se consulta la base de datos, se utiliza un lenguaje similar al SQL (llamado Java Persistence Query Language (JPQL)) y el resultado será una lista de objetos (java.util.list), estos encajan perfectamente en una aplicación JSF. La conexión con las entidades de las tablas es muy sencilla, utilizando anotaciones (dentro de la propia clase) o los archivos descriptor XML. Hay algunas buenas implementaciones de la JPA. Vamos a utilizar una de JBoss, puede que usted conozca: Hibernate. Fue un marco ORM antes de la existencia de la JPA (que tiene muchas ideas de él) y está incluido en el proyecto que la seam-gen genera para nosotros.

Importar la base de datos En primer lugar, tenemos que crear una base de datos MySQL llamado advcm_db e importar el lenguaje de definición de datos (DDL) que crea la estructura de base de datos que vamos a utilizar. El archivo DDL de SQL se llamará adv_contact_manager_create.sql y contiene: SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0; SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0; SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL'; CREATE SCHEMA IF NOT EXISTS `advcm_db` DEFAULT CHARACTER SET utf8 ; USE `advcm_db`;

Page 5: JBoss RichFaces. Capítulo 4. La aplicación.

-- ----------------------------------------------------- -- Table `advcm_db`.`contact` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `ContactOwner` INT(11) NULL DEFAULT NULL , `name` VARCHAR(45) NULL DEFAULT NULL , `surname` VARCHAR(45) NULL DEFAULT NULL , `email` VARCHAR(255) NULL DEFAULT NULL , `company` VARCHAR(255) NULL DEFAULT NULL , `username` VARCHAR(20) NULL DEFAULT NULL COMMENT 'null if the user has no access permission' , `password` VARCHAR(20) NULL DEFAULT NULL COMMENT 'null if the user has no access permission' , `createdOn` DATETIME NOT NULL , `lastUpdatedOn` DATETIME NOT NULL , `lastAccessOn` DATETIME NULL DEFAULT NULL COMMENT 'Only for user with access permissions (username not null)' , `note` TEXT NULL DEFAULT NULL , `active` TINYINT(1) NULL DEFAULT '0' , PRIMARY KEY (`id`) , INDEX `fk_contact_contact` (`ContactOwner` ASC) , INDEX `FK38B724204FF86D69` (`ContactOwner` ASC) , CONSTRAINT `FK38B724204FF86D69` FOREIGN KEY (`ContactOwner` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `fk_contact_contact` FOREIGN KEY (`ContactOwner` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8; -- ----------------------------------------------------- -- Table `advcm_db`.`contact_address` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact_address` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `ContactId` INT(11) NOT NULL , `position` INT(11) NOT NULL DEFAULT '0' , `address1` VARCHAR(255) NULL DEFAULT NULL , `address2` VARCHAR(255) NULL DEFAULT NULL , `postCode` VARCHAR(50) NULL DEFAULT NULL , `city` VARCHAR(255) NULL DEFAULT NULL , `province` VARCHAR(50) NULL DEFAULT NULL , `country` VARCHAR(255) NULL DEFAULT NULL , `label` VARCHAR(255) NOT NULL COMMENT 'it is suggested but can be a free text' , `createdOn` DATETIME NOT NULL , `lastUpdatedOn` DATETIME NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_ContactAddress_contact` (`ContactId` ASC) , INDEX `FK20846D5EA68B411` (`ContactId` ASC) , CONSTRAINT `FK20846D5EA68B411` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `fk_ContactAddress_contact` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8; -- ----------------------------------------------------- -- Table `advcm_db`.`contact_field` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact_field` (

Page 6: JBoss RichFaces. Capítulo 4. La aplicación.

`id` INT(11) NOT NULL AUTO_INCREMENT , `ContactId` INT(11) NOT NULL , `label` VARCHAR(255) NOT NULL COMMENT 'the suggestions on it dipend on type but it is a free field' , `value` VARCHAR(255) NOT NULL , `type` VARCHAR(255) NOT NULL COMMENT 'phone, url, email, etc.' , PRIMARY KEY (`id`) , INDEX `fk_ContactField_contact` (`ContactId` ASC) , INDEX `FK387E901BEA68B411` (`ContactId` ASC) , CONSTRAINT `FK387E901BEA68B411` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `fk_ContactField_contact` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8 COMMENT = 'It contains the value with a label'; -- ----------------------------------------------------- -- Table `advcm_db`.`contact_file` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact_file` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `ContactId` INT(11) NOT NULL , `fileName` VARCHAR(255) NOT NULL , `fileType` VARCHAR(25) NOT NULL , `description` TINYTEXT NULL DEFAULT NULL , `createdOn` DATETIME NOT NULL , `lastUpdatedOn` DATETIME NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_ContactFile_contact` (`ContactId` ASC) , INDEX `FK4C251E3BEA68B411` (`ContactId` ASC) , CONSTRAINT `FK4C251E3BEA68B411` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `fk_ContactFile_contact` FOREIGN KEY (`ContactId` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8; -- ----------------------------------------------------- -- Table `advcm_db`.`contact_group` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact_group` ( `id` INT(11) NOT NULL AUTO_INCREMENT , `ContactOwner` INT(11) NOT NULL , `name` VARCHAR(255) NOT NULL , `description` TINYTEXT NULL DEFAULT NULL , `color` VARCHAR(7) NULL DEFAULT NULL , `createdOn` DATETIME NOT NULL , `lastUpdatedOn` DATETIME NOT NULL , PRIMARY KEY (`id`) , INDEX `fk_ContactGroup_contact` (`ContactOwner` ASC) , INDEX `FK3890E5A04FF86D69` (`ContactOwner` ASC) , CONSTRAINT `FK3890E5A04FF86D69` FOREIGN KEY (`ContactOwner` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `fk_ContactGroup_contact` FOREIGN KEY (`ContactOwner` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB

Page 7: JBoss RichFaces. Capítulo 4. La aplicación.

DEFAULT CHARACTER SET = utf8; -- ----------------------------------------------------- -- Table `advcm_db`.`contact_in_group` -- ----------------------------------------------------- CREATE TABLE IF NOT EXISTS `advcm_db`.`contact_in_group` ( `Contact` INT(11) NOT NULL , `ContactGroup` INT(11) NOT NULL , `insertedOn` DATETIME NOT NULL , PRIMARY KEY (`ContactGroup`, `Contact`) , INDEX `fk_ContactInGroup_Contact` (`Contact` ASC) , INDEX `fk_ContactInGroup_ContactGroup` (`ContactGroup` ASC) , INDEX `FK85EAE8243BA12EF6` (`Contact` ASC) , INDEX `FK85EAE824DB2B7A8` (`ContactGroup` ASC) , CONSTRAINT `contact_in_group_ibfk_1` FOREIGN KEY (`ContactGroup` ) REFERENCES `advcm_db`.`contact_group` (`id` ) ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT `FK85EAE8243BA12EF6` FOREIGN KEY (`Contact` ) REFERENCES `advcm_db`.`contact` (`id` ), CONSTRAINT `FK85EAE824DB2B7A8` FOREIGN KEY (`ContactGroup` ) REFERENCES `advcm_db`.`contact_group` (`id` ), CONSTRAINT `fk_ContactInGroup_Contact` FOREIGN KEY (`Contact` ) REFERENCES `advcm_db`.`contact` (`id` ) ON DELETE NO ACTION ON UPDATE NO ACTION) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8; SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; Seam-gen leerá la estructura de base de datos para generar las entidades JPA para nosotros. Vamos a ver cómo utilizar esta característica al crear el proyecto.

Crear el proyecto La creación del proyecto es muy similar a la que hemos usado para el ejemplo en el capítulo 3, la única diferencia es que ahora se va a conectar nuestro proyecto para el DBMS MySQL. Por lo tanto, tenemos que configurar de una manera adecuada. Abra una ventana de terminal y ubíquese en el directorio de la distribución de JBoss Seam, ejecute el comando siguiente desde aquí, para Microsoft Windows y Unix/Linux/Mac OS X:

Microsoft Windows Unix/Linux/Mac OS X seam setup ./seam setup

Después de que el texto de bienvenida, vamos a entrar en nuestro nuevo proyecto de datos de configuración (seam-gen guardará los datos anteriores, por lo que no tiene que volver a escribir toda la información de configuración): Pregunta Descripción Respuesta Introduzca el lugar de trabajo para sus proyectos de Java (el directorio que contiene sus proyectos de Seam)

Este es el directorio en el que queremos salvar nuestro nuevo proyecto (que depende de nuestro entorno y preferencias)

Sólo dar intro, ya que es el mismo que en proyecto de ejemplo.

Page 8: JBoss RichFaces. Capítulo 4. La aplicación.

Ingrese el directorio predeterminado de JBoss AS

Es el directorio donde está instalado el servidor de aplicaciones JBoss

(El directorio de JBoss)

Introduzca el nombre del proyecto

El nombre de la aplicación AdvContactManager

¿Quieres usar ICEfaces en lugar de RichFaces [n]?

seam-gen también es compatible con ICEfaces (otro marco de componentes), pero queremos utilizar RichFaces, así que pulse Enter

No

Seleccione un tema para RichFaces [classic] (blueSky, [classic], deepMarine, DEFAULT, emeraldTown, japanCherry, ruby, wine)

Tenemos la opción de seleccionar cualquiera de los temas mostrados para nuestro proyecto, tambien podemos cambiarlo más tarde, por ahora, el tema classic esta bien

Solo presione Intro

Este proyecto es empaquetado como un EAR (con componentes EJB) o un WAR (sin soporte EJB) [ear]

Podemos generar un paquete WAR o un paquete EAR para nuestra aplicación. Nos gustaría una aplicación completa EAR con soporte EJB

Solo presione Intro

Introduzca el nombre del paquete Java para el beans de sesión

El nombre del paquete que contiene los beans de sesión (generado por seam-gen)

book.richfaces.advcm

Introduzca el nombre del paquete de Java para su beans de entidad

El nombre del paquete que contiene los beans de entidad (generado por seam-gen)

book.richfaces.advcm

Introduzca el nombre del paquete Java para los casos de prueba

El nombre del paquete que contiene los beans para nuestros casos de prueba

book.richfaces.advcm.test

¿Qué tipo de base de datos se utiliza?

Por este simple ejemplo, no usamos ninguna base de datos

mysql

Introduzca el dialecto de Hibernate para la base de datos

Dialecto de Hibernate org.hibernate.dialect.MySQLDialect

Escriba la ruta del sistema para los controladores jar de JDBC

Tiene que ser una ruta de acceso al archivo JAR del controlador JDBC de MySQL (si no lo tiene, puede descargarlo desde http://dev.mysql.com/downloads/connector/j/ (la versión actual es 5.1.10-bin.jar)).

c:\ruta_controlador_mysql\mysql-connector-java-5.1.10-bin.jar

Introduzca la clase para el controlador JDBC de la base de datos

Clase del Driver JDBC para MySQL com.mysql.jdbc.Driver

Introduzca la dirección URL de conexión JDBC de la base de datos

URL de conexión a la base de datos jdbc:mysql://localhost:3306/advcm_db

Introduzca el nombre de la base de datos

Usuario de la bases de datos de la aplicación

root

Introduzca la contraseña de la base de datos

Contraseña de la base de datos de la aplicación

mysqlpass

Introduzca el nombre del esquema de base de datos

Nombre de la base de datos( está bien dejar este espacio en blanco)

sólo pulse Intro

Introduzca el nombre de catálogo de base de datos

(está bien dejar este espacio en blanco) sólo pulse Intro

¿Trabajar con las tablas que ya existen en la base

¿Usar todas las tablas que están en la base de datos?

y

Page 9: JBoss RichFaces. Capítulo 4. La aplicación.

de datos? ¿Quieres borrar y volver a crear las tablas de base de datos y los datos en Import.sql cada vez que se implante ?

¿Borrar la base de datos en cada despliegue?

N y Intro

Muy bien, hemos hecho la configuración, y veremos cómo configurarlo para la conexión a un DBMS MySQL en el siguiente capítulo (cuando vamos a empezar a hacer la aplicación real). Por ahora las respuestas que está bien utilizar la opción predeterminada. Estamos dispuestos a crear el proyecto utilizando los siguientes comandos para Microsoft Windows y Unix / Linux / Mac OS X:

Microsoft Windows Unix/Linux/Mac OS X seam create-project ./seam create-project

Ahora vamos a crear las entidades de la JPA (nuestro modelo de datos de la aplicación) de forma automática mediante los siguientes comandos para Microsoft Windows y Unix/Linux/ Mac OS X:

Microsoft Windows Unix/Linux/Mac OS X seam generate-model ./seam generate-model

Si está utilizando el IDE de Eclipse, usted tiene que importar el proyecto en el área de trabajo (que se describe cómo hacer que en el capítulo 2, Introducción). Con otros IDE (IntelliJ o NetBeans), sólo se puede abrir desde la ubicación en la que he dicho seam-gen para crearlo.

El diagrama de clases El diagrama de clases siguiente muestra las clases entidad JPA generados por seam-gen:

Page 10: JBoss RichFaces. Capítulo 4. La aplicación.

Como puede ver, no se diferencia mucho del diagrama ER-de hecho, cada clase se corresponde con cada tabla en la base de datos. Este es un ejemplo generado de la clase entidad (la entidad ContactGroup). Hemos escrito algunas partes de la clase, sólo para mostrar algunos puntos relevantes de JPA:

@Entity @Table(name = "contact_group", catalog = "adv_contact_manager") public class ContactGroup implements java.io.Serializable { private Integer id; private Contact contact; private String name; private Set<ContactInGroup> contactInGroups = new HashSet<ContactInGroup>(0); // .@Id

.. other fields, constructors, getters and setters ...

@GeneratedValue(strategy = IDENTITY) @Column(name = "id", unique = true, nullable = false) public Integer getId() {

Page 11: JBoss RichFaces. Capítulo 4. La aplicación.

return this.id; } public void setId(Integer id) { this.id = id; } @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "ContactOwner", nullable = false) @NotNull public Contact getContact() { return this.contact; } public void setContact(Contact contact) { this.contact = contact; } @Column(name = "name", nullable = false) @NotNull public String getName() { return this.name; } public void setName(String name) { this.name = name; } @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "contactGroup") public Set<ContactInGroup> getContactInGroups() { return this.contactInGroups; } public void setContactInGroups(Set<ContactInGroup> contactInGroups) { this.contactInGroups = contactInGroups; } }

Es sólo una clase normal (con campos, accesores y modificadores) anotado por JPA (destacamos éstas) que conectan la clase y sus campos con la tabla correspondiente en la base de datos. Usted puede anotar los campos o el accesor (como en este caso). En ambos casos, la anotación tiene los mismos efectos. @NotNull y @Length son anotaciones de Hibernate Validator, que hemos visto en el capítulo 2. Seam-gen pone algunas anotaciones básicas de Hibernate Validator, pero hay que completarlas mediante la edición de las clases de entidad (vamos a ver un ejemplo en el párrafo siguiente). Otra anotación que debes conocer es JPA @OneToMany que administra la relación con otras clases de entidad. Para hacer un ejemplo, la propiedad contactInGroups devuelve todas las instancias ContactInGroup que están conectados a ContactGroup. De manera sencilla, si tengo una instancia de ContactGroup, puedo conseguir todos los contactos de ese grupo solo leyendo esa propiedad.

Algunas modificaciones a las entidades El uso de la JPA también es conveniente ya que tiene más funciones disponibles, como los validadores de Hibernate (hemos visto cómo funcionan en el primer ejemplo) y otras anotaciones útiles que nos ayudan a escribir código limpio.

Page 12: JBoss RichFaces. Capítulo 4. La aplicación.

Seam-gen realiza mucho trabajo por nosotros, pero como toda herramienta automática, no es perfecto y nos gustaría añadir características a las clases generadas después de la generación de proyectos. En este caso, estamos agregando mas validadores Hibernate a nuestras clases de entidad. Éstos son algunos de utilidad incorporada en los:

@Length(min=, max=): Comprueba si la longitud de la cadena coincide con valores mínimo y máximo

@Max(value=): Comprueba si el valor es menor o igual al valor máximo @Min(value=): Comprueba si el valor es superior o igual al valor @NotNull: Comprueba si el valor del campo es nulo @Email: Comprueba si la cadena se ajusta a la especificación de la dirección de correo

electrónico @Range(min=, max=): Comprueba si el valor está entre los valores mínimo y máximo

(incluido) @Future: Comprueba si la fecha está en futuro @Past: Comprueba si la fecha está en pasado @Pattern(regex="regexp", flag=): Comprueba si el que se corresponda con la

expresión regular, habida cuenta de la bandera del partido (ver java.util.regex.Pattern para más información)

@Patterns( {@Pattern(...)} ): Al igual que @Pattern, pero para múltiples expresiones regulares

Usted puede crear sus propios validadores de una manera sencilla. Consulte la documentación Validadores de Hibernate para ver todas las características de este marco. Otra característica útil que nos gustaría añadir a nuestras entidades es el representado por las anotaciones @PrePersist y @PreUpdate. Si un método es anotado con una de estas anotaciones, será invocado antes de la persistencia de la instancia en la base de datos y antes de su actualización. Aquí está el código añadido para la clase de entidad de la sección anterior (la entidad ContactGroup):

/** * This method initializes the values before * the class is persisted */ @PrePersist public void prePersist() { setCreatedOn(new Date()); setLastUpdatedOn(new Date()); } /** * This method initializes the values before * the class is updated */ @PreUpdate public void preUpdate() { setLastUpdatedOn(new Date()); }

Page 13: JBoss RichFaces. Capítulo 4. La aplicación.

Aquí usamos las anotaciones @PrePersist y @PreUpdate que nos permiten configurar automáticamente las propiedades createdOn y lastUpdatedOn (utilizando el setCreatedOn y métodos setUpdatedOn) sin tener que hacer que cada vez que persisten o actualización de una entidad. También los utilizan para hacer algo antes de que la entidad se conserva o actualizada. También puede utilizar @PreRemove para anotar un método que será llamado después de que se elimine la instancia correspondiente de la clase de entidad.

Edición de la página de plantilla Por ahora, nos limitaremos a la edición de esta página para la transformar los componentes h:messages en RichFaces (rich:messages), que como hemos visto, la caja Ajax (rich:messages también tiene el mismo atributo como el de la JSF, por lo que no tiene que modificar nada más). Para poder usarlo, también tenemos que agregar el espacio de nombres RichFaces que hemos visto. Por ahora, así se debe de ver la página template.xhtml (algunas partes se han omitido porque son los mismos que ya antes hemos visto):

<f:view contentType="text/html" xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:a="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich" xmlns:s="http://jboss.com/products/seam/taglib"> <html> <head> ... </head> <body> <div class="body"> <rich:messages id="messages" globalOnly="true" styleClass="message" errorClass="errormsg" infoClass="infomsg" warnClass="warnmsg" rendered="#{showGlobalMessages!='false'}"/> <ui:insert name="body"/> </div> ... </body> </html> </f:view>

En el próximo capítulo, vamos a añadir las funcionalidades de la plantilla de página, que queremos compartir a través de las diferentes páginas. Como puede ver, el atributo rendered del componente rich:messages está controlada por la expresión EL #{showGlobalMessages!='false'}. showGlobalMessage es un parámetro Facelet que se puede pasar a la plantilla (¿recuerda el parámetro projectName pasados al menú, anteriormente?) para forzar no visualizar el componente rich:messages.

Page 14: JBoss RichFaces. Capítulo 4. La aplicación.

La página de menú Esta es una página incluida (como hemos visto) en la plantilla y es un rich:toolBar con dos instancias rich:toolBarGroup (uno en la izquierda y otro con alineación a la derecha):

<rich:toolBar xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:rich="http://richfaces.org/rich"> <rich:toolBarGroup> <h:outputText value="#{projectName}:"/> <s:link view="/home.xhtml" value="Home" propagation="none"/> </rich:toolBarGroup> <rich:toolBarGroup location="right"> <h:outputText value="signed in as: #{identity.username}" rendered="#{identity.loggedIn}"/> <s:link view="/login.xhtml" value="Login" rendered="#{not identity.loggedIn}" propagation="none"/> <s:link view="/home.xhtml" action="#{identity.logout}" value="Logout" rendered="#{identity. loggedIn}" propagation="none"/> </rich:toolBarGroup> </rich:toolBar>

Después de la declaración xmlns (utilizado por Facelets), podemos encontrar los dos grupos con algunos textos y enlaces dentro. El grupo de la derecha contiene el enlace de entrada al sistema si el usuario no está conectado, y la información del usuario y el enlace de desconexión si el usuario se encuentra conectado. Por lo tanto, cuando ningún usuario está conectado, la página es así:

Page 15: JBoss RichFaces. Capítulo 4. La aplicación.

Cuando un usuario está conectado, aparece como sigue:

Como puede ver, la parte en la parte derecha de la barra de menú cambia según el estado de la variable identity.loggedIn.

La página de inicio de sesión Seam-gen genera una página de inicio de sesión estándar que podemos personalizar. Se llama login.xhtml y usted lo puede encontrar en la ruta /view/. Utiliza las características de autenticación de JBoss Seam, por lo que se ampliará para incluir a nuestro código de acceso. Además, utiliza la página template.xhtml que ya hemos visto. Veamos el código:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml"> <ui:define name="body"> <h:form id="login"> <rich:panel> <f:facet name="header">Login</f:facet> <p>Please login here</p> <div class="dialog"> <h:panelGrid columns="2" rowClasses="prop" columnClasses="name,value"> <h:outputLabel for="username"> Username </h:outputLabel>

Page 16: JBoss RichFaces. Capítulo 4. La aplicación.

<h:inputText id="username" value="#{credentials.username}"/> <h:outputLabel for="password"> Password </h:outputLabel> <h:inputSecret id="password" value="#{credentials.password}"/> <h:outputLabel for="rememberMe"> Remember me </h:outputLabel> <h:selectBooleanCheckbox id="rememberMe" value="#{identity.rememberMe}"/> </h:panelGrid> </div> <p> <i>Note - </i> You may login with the username 'admin' and a blank password. </p> </rich:panel> <div class="actionButtons"> <h:commandButton value="Login" action="#{identity.login}"/> </div> </h:form> </ui:define> </ui:composition>

Una vez más, vemos DOCTYPE y el componente Facelets ui:composition que obtiene los contenidos que deben incluirse en otro Facelet. Como puede ver, de hecho, después de las declaraciones xmlns, está la plantilla de atributo que apunta a la página template.xhtml que hemos visto y lo utiliza como una plantilla. ¿Recuerda el punto de inserción en el cuerpo template.xhtml? ¿Cómo insertar código en ese momento? La respuesta es simple: sólo tiene que utilizar la etiqueta <ui:define> y establecer el atributo de nombre como uno de los puntos de inserción:

<ui:define name="body"> <!—- this code will be inserted --> </ui:define>

Lo podemos encontrar en nuestra página login.xhtml. Incluye la parte personalizada de la página login.xhtml, que es el que tiene el formulario de acceso. Podemos ver el código al declarar <h:form> y el componente <rich:panel> dentro de él. Contiene las entradas para nombre de usuario y contraseña (y una casilla Recuérdame). Debajo del panel, existe la etiqueta JSF estándar h:commandButton que llama a la acción de login. No queremos un inicio de sesión Ajax, así que está bien utilizar un componente de acción estándar que se redirigirá a la página de inicio después de la sesión se ha completado. De todos los componentes hay que apuntar a un componente Seam especial llamada identidad, que administra la fase de inicio de sesión. No vamos a editar mucho esta página, lo único que se hará es eliminar la sección Note, ya que no se necesitará:

Page 17: JBoss RichFaces. Capítulo 4. La aplicación.

<p> <i>Note - </i> You may login with the username 'admin' and a blank password. </p>

Así es como aparece la página de inicio:

La página de inicio La página de inicio (home.xhtml) es una página en blanco con un cuadro que muestra Powered by seam y Generated by seam-gen. Por ahora, simplemente borre el código de la caja a fin de obtener una página en blanco, que se llenará en los capítulos siguientes. El código es el siguiente:

<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:s="http://jboss.com/products/seam/taglib" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:rich="http://richfaces.org/rich" template="layout/template.xhtml"> <ui:define name="body"> </ui:define> </ui:composition>

Y esta es la forma en que aparece (se puede ver la barra de menú que viene de la plantilla):

Page 18: JBoss RichFaces. Capítulo 4. La aplicación.

Resumen En este capítulo, hemos creado las bases de nuestro proyecto para tener una idea de las tecnologías de nuestro lado para que sepamos, como construir buenas aplicaciones, mientras que empecemos a ser más productivos y rápidos. Hemos visto el proyecto seam proyecto generado por seam-gen e incluye soporte para Ajax y los componentes ricos (con RichFaces). Además, vimos las plantillas (con Facelets) y la autenticación de JBoss Seam. También hemos empezado a personalizar un poco las entidades (agregando anotaciones Hibernate Validator) y el código XHTML. En el próximo capítulo, vamos a profundizar en el desarrollo de la aplicación utilizando componentes RichFaces.