Está en la página 1de 179

Desarrollo de

Aplicaciones
Web II
DESARROLLO DE APLICACIONES WEB II
2

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 3

Índice
Presentación 5
Red de contenidos 7

Unidad de Aprendizaje 1
JAVA PERSISTENCE API 9
1.1 Tema 1 : Introducción al API de Persistencia JPA 12
1.1.1 : Entidad 12
1.1.2 : Metadata 13
1.1.3 : EntityManager 14
1.1.4 : Unidad de Persistencia 15
1.1.5 : Operaciones básicas 17
1.1.6 : Transacciones 19
1.1.7 : Ciclo de Vida de una Entidad 19

1.2 Tema 2 : OR-Mapping con JPA 23


1.2.1 : Anotaciones 23
1.2.2 : Manejo de la Llave Primaria 28
1.2.3 : Generación de la Llave Primaria 28
1.2.4 : Llave Primaria Compuesta 32
1.2.5 : Objetos Embebidos 35

1.3 Tema 3 : Relaciones entre entidades 38


1.3.1 : Conceptos básicos 38
1.3.2 : Relación Many To One 40
1.3.3 : Relación One to One 42
1.3.4 : Bidireccionalidad de la relación One-To-One 43
1.3.5 : Relación One To Many 44
1.3.6 : Relación Many To Many 46
1.3.7 : Opciones de Fetch 49

1.4 Tema 4 : The Java Persistence Query Language. 51


1.4.1 : Introducción a JP-QL 51
1.4.2 : Consultas dinámicas 56
1.4.3 : Consultas nombradas 58
1.4.4 : Uso de parámetros 60
1.4.5 Ejecución de Queries 61
1.4.6 Sintaxis de JPQL 63

Unidad de Aprendizaje 2
JAVA SERVER FACES 2 69
2.1 Tema 5 : Fundamentos de JSF 72
2.1.1 : Introducción a JSF 72
2.1.2 : Arquitectura de JSF 73
2.1.3 : Ciclo de vida de un request 77
2.1.4 : Facelets 81
2.1.5 : Managed Bean 89
2.1.6 : Lenguaje de Expresiones JSF 92
2.1.7 : Backing Beans 95

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
4

2.2 Tema 6 : Componentes de Interfaz de usuario 97


2.2.1 : Introducción 97
2.2.2 : Arquitectura de Componentes UI 98
2.2.3 Librería Core 102
2.2.4 Librería HTML 108
2.2.5 Librería User Interface 117
2.2.6 Librería de Componentes Compuestos 117

2.3 Tema 7 : Conversiones, Validaciones y Eventos 119


2.3.1 : Introducción 119
2.3.2 : El sistema de Conversión de JSF 119
2.3.3 El sistema de Validación de JSF 122
2.3.4 El sistema de Mensajes de JSF 123
2.3.5 El modelo de Eventos de JSF 131

2.4 Tema 8 : Integración JSF y JPA 127


2.4.1 : JSF y AJAX 127
2.4.2 : Integración JSF + JPA 136
2.4.3 : Empleando otras implementaciones de JSF 137
2.4.4 : Tablas JSF: Facets, dataTable y panelGrid 141
2.4.5 : Mantenimiento de tablas 148

Unidad de Aprendizaje 3
SPRING FRAMEWORK 155
3.1 Tema 9 : Spring Core 157
3.1.1 : Introducción 157
3.1.2 : Arquitectura 161

3.2 Tema 10 : Spring Web 164


3.2.1 : Introducción 164
3.2.2 : Configuración 164

3.3 Tema 11 : Spring Módulos 174


3.3.1 : Spring security 174

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 5

Presentación

El curso de “Proyecto Empresarial” pertenece a la línea de Programación dentro de la


Carrera de Computación e Informática y brinda un conjunto de conocimientos y
herramientas que permitirán a los alumnos poder desarrollar aplicaciones web de n-
capas utilizando los frameworks Java : Java Persistence API ( JPA ), Java Server Faces
( JSF ) y Spring Framework.

El manual del curso ha sido diseñado bajo la modalidad de Unidades de Aprendizaje, las
que desarrollan determinados temas a lo largo de las semanas establecidas para el
dictado del curso. Cada capítulo del manual indica los temas a ser tratados, los logros
que se deben alcanzar y los contenidos que se deben desarrollar. Finalmente, se
encontrará las actividades recomendadas que el alumno deberá desarrollar para
reforzar lo trabajado y aprendido en la clase. Se incluye bibliografía y recursos de
internet que puede colaborar en el logro de un autoaprendizaje efectivo.

El curso es eminentemente práctico, pero requiere horas adicionales de investigación y


práctica por parte del alumno. Se inicia con un los conceptos de “OR-Mapping” con la
especificación JPA (Java Persistence API) y su implementación en EclipseLink: se
abordan las anotaciones, mapeo y relaciones entre entidades así como los fundamentos
básicos de JP-QL para la construcción de consultas. Luego, la segunda unidad del
manual aborda la especificación JSF (Java Server Faces) tratando de abarcar gran
parte de la funcionalidad que proporciona. Finalmente, se aborda en la tercera unidad el
framework de Spring: Arquitectura, Web y Security.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
6

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 7

Red de contenidos

Desarrollo de aplicaciones WEB II

Spring Java Java


Persistence Server
API Faces
(JPA) (JSF)

Tópicos
avanzados de
Spring Core Spring Web JSF

Conversiones,
Validaciones
y Eventos
Introducción a
Spring Módulos
la API de
Persistencia
Componentes
de Interfaz de
usuario
OR-Mapping
con JPA

Arquitectura de
JSF, Configuración
y estructura básica
Relaciones
entre
entidades

Lenguaje de
Consultas
JPQL

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
8

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 9

UNIDAD

1
JAVA PERSISTENCE API
LOGRO DE LA UNIDAD DE APRENDIZAJE
Al término de la unidad, el alumno puede realizar transacciones y consultas
para reportes usando JPQL a nivel empresarial.

TEMARIO
1.1 Tema 1 : Introducción al API de Persistencia JPA
1.1.1 : Entidad
1.1.2 : Metadata
1.1.3 : EntityManager
1.1.4 : Unidad de Persistencia
1.1.5 : Operaciones básicas
1.1.6 : Transacciones
1.1.7 : Ciclo de Vida de una Entidad

1.2 Tema 2 : OR-Mapping con JPA


1.2.1 : Anotaciones
1.2.2 : Manejo de la Llave Primaria
1.2.3 : Generación de la Llave Primaria
1.2.4 : Llave Primaria Compuesta
1.2.5 : Objetos Embebidos

1.3 Tema 3 : Relaciones entre entidades


1.3.1 : Conceptos básicos
1.3.2 : Relación Many To One
1.3.3 : Relación One to One
1.3.4 : Bidireccionalidad de la relación One-To-One
1.3.5 : Relación One To Many
1.3.6 : Relación Many To Many
1.3.7 : Opciones de Fetch

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
10

1.4 Tema 4 : The Java Persistence Query Language.


1.4.1 : Introducción a JP-QL
1.4.2 : Consultas dinámicas
1.4.3 : Consultas nombradas
1.4.4 : Uso de parámetros
1.4.5 Ejecución de Queries
1.4.6 Sintaxis de JPQL

ACTIVIDADES PROPUESTAS

• Reconocer las clases de la API Persistencia JPA


• Los alumnos escriben clases Java, las convierten en Entidades JPA y
trabajan con tablas relacionales.
• Las alumnos desarrollan aplicaciones Java stand-alone haciendo uso de
entidades JPA.
• Implementar inserciones de sentencias JPQL a la base de datos.
• Implementar consultas y transacciones de sentencias JPQL a la base de
datos.
• Implementar inserciones de sentencias JPQL a la base de datos.
• Implementar consultas y transacciones de sentencias JPQL a la base de
datos.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 11

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
12

1.1. INTRODUCCIÓN AL API DE PERSISTENCIA JPA


La técnica que permite acortar las diferencias entre el modelo relacional y el modelo
de objetos se conoce como ORM (Mapeo Relacional a Objetos). La idea básica se
sustenta en que para mapear los conceptos de un modelo al otro (o viceversa) se
requiere de un mediador que maneje de forma automática la transformación.

La historia de JPA se origina en dos frameworks de persistencia bastante utilizados:


en el lado propietario existía TopLink mientras que en el lado “open” estaba Hibernate.
JPA es una especificación basada en el JSR 220 conocido como “Enterprise Java
Bean 3.0” (http://jcp.org/en/jsr/detail?id=220 ).

Al ser una especificación (o un conjunto de API’s) está sujeta a diversas


implementaciones de diversos fabricantes. La idea principal es que sea un Framework
ligero, basado en POJOs y pueda enfrentar desafíos de arquitectura e integración en
aplicaciones empresariales.

Algunas implementaciones de JPA:

Hibernate http://www.hibernate.org/

TopLink http://www.oracle.com/technetwork/middlew
are/toplink/overview/index.html

OpenJPA http://openjpa.apache.org/

EclipseLink http://www.eclipse.org/eclipselink/

1.1.1. Entidad

El concepto de “Entidad” fue introducido por Peter Chen en un documento llamado


“The Entity-relationship model – Howard a unified view of data” publicado en “ACM
Transactions on Database Systems” en el año de 1976 1.

En dicho documento, se describía a las entidades como cosas que tenían “atributos” y
“relaciones” con la expectativa de que dichos atributos y relaciones pudieran ser
almacenados en la base de datos.

En la actualidad, dicha definición es vigente dado que cualquier objeto dentro de una
aplicación JPA puede ser una entidad, hay que definir las características que debe
poseer una “Entidad”:

• Persistencia: las entidades pueden ser manipuladas para recuperase en


memoria o ser grabadas en un almacén de datos.

1
Una copia del documento se puede obtener en el enlace:
http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.123.1085&rep=rep1&type=pdf

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 13

• Identidad: significa que las entidades tienen un identificador que permite


emplearlas de manera inequívoca y diferenciarlas de otras instancias de la
misma entidad. El identificador de la entidad es equivalente a la llave primaria
de una tabla en la base de datos.

• Transaccionalidad: Todas las operaciones (insertar, modificar o eliminar)


deben realizarse dentro de un contexto transaccional debido a que se requiere
de una transacción para que los cambios sean grabados en la base de datos.

• Granularidad: Las entidades son objetos que pertenecen a un dominio de


negocio, poseen un conjunto de estados y por tanto son relevantes para la
aplicación (no se trata de objetos con tipo primitivo, sino de objetos más
complejos).

1.1.2. Metadata

Cada entidad tiene asociado una “metadata” que la describe. Dicha información puede
estar almacenada dentro de la entidad Java o puede existir en un archivo externo: en
ambos casos, esa información no se almacena en la base de datos.

Existen dos maneras de especificar la metadata:

• Usando Anotaciones

• Usando XML

Las anotaciones fueron introducidas en la versión JAVA EE 5 y permiten que la


metadata esté incorporada dentro del código fuente Java.

El uso de las anotaciones requiere que se importe el paquete “javax.persistence.*”


dentro de la clase Java que representa a la Entidad.

El uso de XML es una opción alternativa a las anotaciones, aunque su lectura puede
resultar compleja para proyectos grandes.

Un JavaBean cualquiera como el siguiente

Se puede convertir en entidad, simplemente agregándole las anotaciones:


@Entity
@Id

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
14

No se debe olvidar que al ser un JavaBean, sigue las reglas de este (con los
getter/setter).

1.1.3. EntityManager

La mayoría de llamadas a las API’s de JPA se encapsulan dentro de lo que se conoce


como “Entity Manager” y mediante el cual se puede alcanzar a la base de datos.

Esta encapsulación es implementada dentro de una interface conocida como


EntityManager que es la que ejecuta todo el trabajo de persistencia. Por tanto, una
entidad mientras que no se trabaje con el Entity Manager es un objeto Java simple
como cualquier otro.

Cuando el Entity manager obtiene una referencia a una Entidad, se dice que dicha
entidad está en estado “managed”

El conjunto de entidades en estado “managed” dentro de un Entity Manager se conoce


como “persistence context”.

Los Entity Managers son configurados para trabajar con determinados tipos de
objetos, bases de datos y son implementados por un proveedor (provider) conocido
como “persistence provider”. En términos prácticos este provider es la
implementación de la especificación JPA.

Los Entity Managers se generan a partir de una factoría de tipo


EntityManagerFactory, que genera una especie de plantilla para la persistencia, pero
toma la configuración particular desde una unidad de persistencia conocida como
“persistence unit”, la cual contiene la configuración implícita o explícita (con un
nombre asociado ) para las entidades y para el Entity Manager.

El gráfico2 resume las relaciones entre los conceptos mencionados:

2
FUENTE: “JPA 2: Mastering the Java Persistence API”, pág 23.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 15

Un Entity Manager se obtiene de la siguiente forma:

Nombre de la “persistence unit”


Clase estática Debe ser el mismo que aparece
en el archivo persistence.xml

Variable con el Entity Manager cargado

1.1.4. Unidad de Persistencia

La configuración de una unidad de persistencia se escribe en un archivo llamado


“persistence.xml”, el cual debe estar ubicado dentro del folder META-INF de un
proyecto Java.

Cada unidad de persistencia tiene un nombre, el cual es referenciado por la factoría al


momento de pedirle que genere un EntityManager.

Un archivo persistence.xml puede contener una o más unidades de persistencia,


siendo cada una diferente de la otra.

La estructura básica de un archivo persistence.xml es la siguiente:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
16

Debido a que es un archivo XML, debe tener un DTD:

Luego, viene la definición de la Unidad de persistencia, el proveedor y las clases Java


definidas como entidades:

Nombre de la “persistence unit”

El valor de RESOURCE_LOCAL indica que la conexión a la base de datos se realizará


desde la misma aplicación (No emplea Pool de conexiones).

Después, se definen las propiedades de conexión a la base de datos:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 17

Finalmente se cierran los tags XML:

Observe que las propiedades JDBC (javax.persistence.jdbc.*) han sido estandarizadas


en JPA 2.0. En versiones anteriores de JPA, esas propiedades eran definidas por cada
Persistence Provider.

1.1.5. Operaciones básicas

Para aquellos desarrolladores acostumbrados al SQL en bases de datos relacionales,


la equivalencia es sencilla en JPA:

• SQL INSERT = Método Persist

• SQL SELECT = Método Find ( o también puede usarse el SELECT JPQL )

• SQL UPDATE = Método Merge

• SQL DELETE = Método Remove

El “persist” de una entidad significa crear un objeto en memoria y luego almacenarlo


en la base de datos para recuperarlo posteriormente. Como se ha mencionado,
equivale a insertar uno o más registros en la base de datos.

Se instancia el objeto
Java

Se cargan los valores


de los atributos

Se ejecuta el método “persist”


mediante el EntityManager

Si ocurre un error durante la ejecución del “persist”, se lanza la excepción


PersistenceException, la cual debe será propagada, debiendo ser manejada por el
programa.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II
18

Para ubicar a una Entidad empleando el método “find”, generalmente se requiere solo
una línea de código:

Clase de la Entidad a ser “ubicada”


Evita hacer un “cast”

Llave primaria de la Entidad

variable con el EntityManager cargado

Si la entidad con la llave primara indicada no existe, el EntityManager devolverá NULL.


La aplicación debe verificar el valor antes de usar la variable “emp” en el caso del
ejemplo.

Para eliminar una entidad, se hace uso del método “remove”. Sin embargo se debe
tener en consideración que para eliminar una entidad en JPA, primero debe colocarse
en estado “managed”, es decir, debe cargarse al contexto de persistencia.

Se requiere cargar la entidad

Como se mencionó anteriormente, si la entidad no existe el EntityManager devolverá


NULL, por lo que se debe evaluar dicha condición antes de invocar al método
“remove”.

Si se envía un valor de NULL al “remove”, JPA lanzará la excepción


java.lang.IlegalArgumentException.

Para actualizar atributos de una entidad, se emplea el método “merge”. Se requiere


ubicar a la entidad antes de actualizarla:

En este ejemplo, se está actualizando el apellido del empleado con ID = 8.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 19

1.1.6. Transacciones

El único método que puede estar fuera de una transacción es el “find” dado que no
cambia atributos de las entidades.

En una aplicación Java StandAlone (Java SE), se debe invocar el contexto


transaccional de forma explícita, mientras que en una aplicación Java EE, se asume
que el container proporciona dicho contexto transaccional.

Se inicia una transacción

Se inicia finaliza la
transacción

1.1.7. Ciclo de Vida de una Entidad

JPA proporciona unos métodos denominados “callbacks” (listeners) para ejecutar


acciones en los diferentes estados que pueden suceder dentro del ciclo de vida de una
entidad. Por ejemplo, imagine que desea actualizar una entidad, pero antes de hacerlo
debe verificar que algunos datos estén presentes.

En el gráfico, se puede apreciar que una entidad no existe hasta que se distancia el
objeto y se graba en la base de datos. De ahí, pasa al estado “manejado” o
“administrado” por el EntityManager y, luego de ello, se puede remover, actualizar,
liberar (“detach”) o incluso volver a leer (refrescar).

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 20

Las anotaciones que proporciona JPA para manejar los “Callbacks” son:

• @PostLoad: Se ejecuta luego de un “refresh” a la entidad.


• @PrePersist: Se ejecuta antes de insertar la entidad.
• @PostPersist: Se ejecuta después de haber insertado la entidad.
• @PreUpdate: Se ejecuta antes de un update a la entidad.
• @PostUpdate: Se ejecuta después de un update a la entidad.
• @PreRemove: Se ejecuta antes de eliminar la entidad en la base de datos.
• @PostRemove: Se ejecuta después de haber eliminado a la entidad.

Los métodos “callback” se pueden declarar dentro de la misma entidad o también en


una clase Java separada.

Por ejemplo, si de declaran dentro de la misma entidad:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 21

En cambio, si se prefiere emplear una clase Java externa, sería así:

a) A la Entidad hay que agregarle la anotación @EntityListeners para indicar cuál


es la clase Java que contiene los métodos “callbacks”.
b) Se debe crear una clase Java y escribir los métodos que se requiere manejar
(con las anotaciones del caso).

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 22

Resumen
1. Recordar que JPA es una especificación, por tanto, tiene muchas
implementaciones. El desarrollador debe seleccionar una en particular, siendo las
más conocidas: Open JPA, TopLink, EclipseLink e Hibernate.

2. Diferenciar entre Entidades y Clases Java.

3. Recordar la ubicación del archivo persistence.xml que debe ir siempre dentro del
folder META-INF.

4. Recordar para qué sirve el EntityManager y la persistence-unit.

5. Las operaciones básicas sobre una Entidad: find, persist, merge, remove

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o EclipseLink: http://www.eclipse.org/eclipselink/jpa.php
o Entidades JPA: http://www.agiledata.org/essays/mappingObjects.html

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 23

1.2. OR-MAPPING CON JPA

1.2.1. Anotaciones

Las anotaciones pueden clasificarse en dos grupos:


• Anotaciones lógicas describen el modelo de entidades desde el punto de vista
del modelamiento orientado a objetos. Constituyen una especie de metadata
del modelo.

• Anotaciones físicas están relacionadas con el modelo en la base de datos


(modelo físico) y tienen que ver con tablas, columnas, etc.

Las anotaciones dentro de una clase Java se pueden colocar a nivel de atributos o a
nivel de métodos. Si se colocan a nivel de atributos se denomina “Field Access”
mientras que si se coloca a nivel de métodos se denomina “Property Access”.

Anotación de tipo
“Field Access”
Atributos de la clase

Es equivalente a:

Anotación de tipo “Property


Access”
NOTA: Siempre va en el GETTER

En la especificación de JPA 2.0 se introduce la anotación @Access que permite


combinar los dos modos presentados en el ejemplo. Esta anotación permite sobre
escribir el modo de acceso por defecto, aunque no es muy usual hacerlo.

Para definir una entidad basta con emplear la anotación @Entity y la anotación @Id.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 24

Anotación @Table

Por defecto no es necesario incluir ninguna anotación para referenciar a una tabla.
JPA asume que la tabla se llama igual que la clase Java en donde se define la entidad.

Sin embargo, si se desea especificar un nombre de tabla en particular para asociarlo


con la entidad, es preciso utilizar la anotación @Table con el parámetro “name”
respectivo.

Se puede indicar además el esquema de base de datos con el atributo “schema” (para
aquellos motores de base de datos que lo soporten):

Se debe tener cuidado con el uso de mayúsculas y minúsculas, pues muchos


manejadores de bases de datos no son sensibles a esto.

Anotación @Basic

Cuando se “persiste” una propiedad de una entidad, el “persistente provider” verifica


que el tipo de dato corresponda a un tipo soportado y trata de pasarlo hacia la base de
datos vía el driver JDBC.

Los tipos de datos soportados son:

Tipos primitivos byte, int, short, long, boolean, char, float


double
Clases que encapsulan a tipos Byte, Integer, Short, Long, Boolean,
primitivos Character, Float, Double
Arreglos de bytes y caracteres byte[], Byte[], char[], Character[]
Números java.math.BigInteger, java.math.BigDecimal
Cadenas de caracteres java.lang.String
Tipos de datos que manejan fechas java.util.Date, java.util.Calendar

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 25

Java
Tipos de datos que manejan fecha java.sql.Date, java.sql.Time,
JDBC java.sql.Timestamp
Tipos enumerados Cualquiera
Objetos serializables Cualquiera

Se debe tener cuidado con el comportamiento del driver JDBC cuando los tipos de
datos no coinciden entre lo que se define en la entidad y lo que soporta la base de
datos, pues el driver intentará ejecutar la mejor conversión posible.

La anotación @Basic (que es opcional) se utiliza para indicar de forma explícita que
dicho atributo debe ser almacenado en la base de datos.

Anotación @Transient

Se emplea para marcar aquellos atributos de la entidad que NO deben ser guardados
en la base de datos.

Anotación @Column

Es una anotación de tipo físico, pues indica las características físicas de la columna
en la base de datos.

Si no se especifica para un atributo determinado marcado como persistente, JPA


asume que la columna se llama igual que dicho atributo. En cambio, si la columna
tiene un nombre diferente, se deberá especificar con el uso de la anotación @Column.

Los elementos que acompañan a la anotación @Column son los siguientes:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 26

Elemento Descripción Valor por


defecto
String (Opcional) “”
columnDefinition Es el fragmento de SQL utilizado para generar el DDL de la
columna (depende del manejador de base de datos)
boolean (Opcional) Indica si la columna ser incluirá dentro de una true
insertable sentencia SQL INSERT generada por el Persistence Provider.
int length (Opcional) Indica la longitud de la columna en la tabla y 255
funciona únicamente cuando la columna es un String o cadena
de caracteres.
String name (Opcional) Indica el nombre de la columna. POr defecto se “”
asume que la columna se llama igual que el atributo de la
entidad.
boolean nullable (Opcional) Indica si la columna permite valores nulos. true
int precision (Opcional) Indica la precisión para una columna numérica 0
(válido solo para columnas decimales).
int scale (Opcional) Indica la escala para una columna numérica (válido 0
solo para columnas decimales).
String table (Opcional) Indica el nombre de la tabla en donde se asocial la “”
columna.
boolean unique (Opcional) Se emplea cuando la clave única corresponde a false
una sola columna.
boolean (Opcional) Indica si la columna ser incluirá dentro de una true
updatable sentencia SQL UPDATE generada por el Persistence
Provider.

Ejemplo 1:

Ejemplo 2:

Anotación @Lob

Para el manejo de objetos binarios (imágenes o archivos generalmente) se requieren


accesos especiales en el driver JDBC para efectuar conversiones entre el objeto Java
y la columna en la tabla de la base de datos.

La anotación @Lob sirve para indicar que el atributo de dicha entidad requiere efectuar
las conversiones vía JDBC.

Ahora bien, los campos LOB (acrónimo de Large Object) se pueden clasificar de dos
maneras, siendo el manejo de cada manera un tanto diferente:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 27

Si el objeto es … El tipo java a usar es …


Character Large Objets ( CLOB ) • char[]

• Character[]

• String

Binary Large Objects ( BLOB ) • byte[]

• Byte[]

• tipos serializables

En ambos casos, el driver JDBC es responsable de hacer las conversiones entre el


objeto Java y la base de datos.

Ejemplo:

Anotación

Tipo de dato

Anotación @Temporal

Sirve para especificar tipos de datos basados en el tiempo. Estos tipos de datos se
pueden clasificar en dos ramas: los que vienen del paquete java.sql y los que vienen
del paquete java.util.

En el paquete java.sql, los tipos se trabajan directamente:


• java.sql.Date

• java.sql.Time

• java.sql.Timestamp

En cambio, en el paquete java.util:


• java.util.Date

• java.util.Calendar

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 28

Se debe especificar la anotación @Temporal y además especificar el atributo


“TemporalType” con uno de los tres valores que representan a cada uno de los tipos
java.sql (DATE, TIME o TIMESTAMP).

Ejemplo:

Anotación

Tipo de dato Equivalencia JDBC


java.util.Date
1.2.2. Manejo de la Llave Primaria

Cada Entidad debe tener una llave primaria. La anotación empleada es @Id sobre el
atributo que contiene la llave. Adicionalmente, se puede usar @Column para asociar al
atributo con la columna en la tabla.

Una llave primaria se asume que es “insertable”, pero no puede ser “nullable” o
“updatable” por lo que se debe tener cuidado de no sobre escribir esos atributos salvo
excepciones muy específicas (cuando se manejan relaciones).

Los tipos de datos soportados para una llave primaria son:

Tipos primitivos byte, int, short, long, char


Clases de tipos primitives Byte, Integer, Short, Long , Character
Cadenas de caracteres java.lang.String
Números grandes java.match.BigInteger
Tipos basados en tiempo java.util.Date, java.sql.Date

1.2.3. Generación de la Llave Primaria

También, se conoce como “Generación del ID” y se realiza mediante la anotación


@GeneratedValue. En base a dicha anotación, el “Persistence Provider” genera el ID
para cada entidad, y lo inserta en la columna respectiva.

Se debe tener en cuenta que dependiendo de la estrategia de generación del ID, el


valor obtenido puede que no esté disponible hasta que se ejecute un “flush” o un
“commit” a la transacción.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 29

Existen cuatro estrategias posibles (que son un tipo enumerado de “GenerationType”):


• AUTO

• TABLE

• SEQUENCE

• IDENTITY

ESTRATEGIA “GenerationType.AUTO”

Este tipo de estrategia delega en el “Persistence Provider” la selección de la mejor


forma de generación de los “ID”. Cualquiera sea la forma elegida por el provider, se
confiará en los recursos de la base de datos para la obtención de los ID’s.

En el caso particular de EclipseLink con MySQL, la estrategia AUTO emplea una tabla
denominada “sequence”.

Ejemplo:

ESTRATEGIA “GenerationType.TABLE”

Esta estrategia es la más flexible y portable, pues permite que la aplicación genere
ID’s diferentes de acuerdo con las necesidades.

La tabla requiere de dos columnas, una conteniendo el identificador para generar la


secuencia y la otra columna contiene el último valor generado. Cada fila de la tabla es
un generador diferente para los ID’s.

Un ejemplo sencillo es el siguiente:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 30

Dado que no se ha especificado el nombre de un “generador” ni el nombre de una


tabla, el Persistence provider seleccionará sus propios valores. Lo más común es que
busque (la tabla debe existir en la base de datos) una tabla como la indicada en la
figura.

¿Qué sucede si se desea especificar una tabla en particular? Se debe emplear la


anotación @TableGenerator.

Ejemplo:

El atributo “allocationSize” indica el incremento en la generación del ID (para el caso


del ejemplo va de uno en uno). Por defecto el incremento es 50.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 31

ESTRATEGIA “GenerationType.SEQUENCE”

Esta estrategia depende de las capacidades de la base de datos para manejar objetos
de tipo “secuencia” (caso de Oracle).

Al igual que en la estrategia TABLE, basta con escribir la anotación para que el
“Persistence Provider” seleccione la mejor secuencia dentro de la base de datos.

Ejemplo:

Estrategia

Si se desea especificar una secuencia en particular, debe indicarse el “generator” y la


anotación @SequenceGenerator. Se debe considerar que la secuencia debe existir
previamente en la base de datos (salvo que la opción de generación de DDL esté
habilitada en nuestra aplicación).

Ejemplo (la secuencia es para Oracle):

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 32

ESTRATEGIA “GenerationType.IDENTITY”

Esta estrategia aprovecha las facilidades de la bases de datos para utilizar columnas
de tipo “autoincremento”. Sin embargo, es menos eficiente porque el identificador
generado no está disponible hasta después que ocurra el INSERT.

No requiere una anotación para el “generador” dado que el campo autoincremental es


parte de la definición de la tabla que corresponde a la entidad.

Ejemplo:

Estrategia

1.2.4. Llave Primaria Compuesta

En algunas situaciones, en donde se requiere que la llave primaria de una entidad esté
compuesta de múltiples atributos, JPA proporciona dos formas de soportar esta
necesidad mediante las anotaciones:

• @IdClass
• @EmbeddedId

Se debe tener en cuenta que:

a) En ambos casos, se requiere de una clase Java externa que sea la que maneje
los atributos de la llave primaria.
b) La clase Java que maneja los atributos de la llave primaria, debe implementar
los métodos equals () y hashCode () con el fin que el Persistence Manager
pueda almacenar e identificar las entidades.
c) La clase Java que representa a la llave primaria debe ser pública, implementar
a la interface Serializable y tener un constructor sin argumento.

Ejemplo:

Dada la siguiente tabla “tbmatricula” con una llave primaria compuesta.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 33

La Entidad y la clase Java que maneja la llave primaria pueden representarse así (no
olvidar que se debe generar los métodos getter/setter en ambas clases Java):

Observe que la anotación @IdClass especifica el nombre de la clase Java que maneja
la llave primaria.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 34

Observe, también, que la clase Java que maneja la llave primaria no posee
anotaciones. Sin embargo, debe implementar los métodos nombrados líneas arriba:

El método equals () lo que hace es comparar uno a uno los atributos de la llave
primaria contra los atributos de otra entidad para verificar que no se trate de la misma
entidad.

El método hashCode () lo que hace es devolver un código “hash” de los valores de la


llave primaria.

Para consultar una entidad con una llave primaria compuesta, solo se requiere generar
una instancia de la clase que maneja la llave primaria, cargarle los valores necesarios
y pasar dicha variable al EntityManager.

Ejemplo:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 35

1.2.5. Objetos Embebidos

Un objeto embebido es aquel que es dependiente de una entidad: no tiene identidad


por sí mismo. Entender este concepto es muy útil para el manejo de relaciones entre
entidades.

Si bien, a nivel de Java, los objetos embebidos se administran de forma separada, a


nivel de base de datos, la entidad y la clase embebida se almacenan sobre el mismo
registro de la tabla.

Por ejemplo, en el siguiente gráfico, se tiene la entidad “CUSTOMER” y la tabla


“tbcustomer”. Observe que los datos de la dirección pueden constituir una clase
separada:

Si se convierte la dirección en una clase “Embebida”, quedaría así:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 36

Anotación
@Embeddable

Anotación
@Embedded

Se debe observar que:

a) La Entidad declara un atributo con el tipo de dato de la clase “Address” y a este


atributo le coloca la anotación “@Embedded” para indicar que esa clase es
“embebida”.
b) La clase “Address” NO tiene anotaciones que indiquen que es una entidad.
Únicamente tiene la anotación “@Embeddable” para indicar que hay “otra”
clase que la incluye (o que la referencia).
c) Ambas clases tienen sus getter/setter.
d) Ambas clases deben definirse en el archivo persistente.xml.
e) Finalmente, es importante saber que solo se puede ejecutar series sobre la
clase marcada como “Entidad”.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 37

Resumen
1. Una clase Java se convierte en Entidad al agregar la anotación @Entity. Además,
existen otras anotaciones que permiten el mapeo contra columnas de la tabla en
la base de datos.

2. Existen cuatro maneras de generar la secuencias para ID’s:


• AUTO
• TABLE
• SEQUENCE
• IDENTITY

3. Recordar el uso de la anotación @Temporal para tipos de datos que manejan


tiempo.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o Anotaciones: http://www.objectdb.com/api/java/jpa/annotations/orm

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 38

1.3. RELACIONES ENTRE ENTIDADES

1.3.1. Conceptos básicos

Roles

Las relaciones entre entidades tienen tres diferentes perspectivas:

a) La primera es el punto de vista desde un lado de la relación.

b) La segunda en el punto de vista desde el otro lado de la relación.

c) La tercera es la perspectiva global que mira ambos lados de la relación.

Estos “lados” son conocidos como “roles”. Tal es así que en cada relación hay dos
entidades que se relacionan mutuamente de tal manera que cada una cumple un rol
dentro de la relación. Es más, una entidad puede jugar muchos roles dentro de un
modelo.

Direccionalidad

Existen maneras de crear, remover y actualizar las relaciones para darles


mantenimiento. Si una entidad tiene relación con otra, existirá un atributo que sirve
para identificar la relación y referirse a la entidad relacionada identificando así el rol
que juega en la relación.

Cuando las entidades se referencian mutuamente se dice que la relación es bi-


direccional. Ejemplo: El empleado sabe en qué Proyecto trabaja y el Proyecto con oce
quiénes son sus miembros (las flechas indican el sentido de la dirección).

Si una entidad apunta únicamente a otra, la relación es unidireccional. El empleado


conoce su Dirección, pero la inversa no necesariamente es cierta (la flecha indica el
sentido de la relación).

Ahora bien, la relación Bidireccional puede ser descompuesta en dos relaciones uni-
direccionales. Cada relación tendrá un origen (“source” o rol de referencia) y un
destino (“target” o rol referido). Se debe tener en cuenta esto, pues el origen y destino
varían según la perspectiva que estemos usando para analizar la relación.

Cardinalidad

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 39

La cardinalidad de una relación sirve para determinar cuántas instancias de una


entidad existen en cada lado de una misma relación.

Cada rol dentro de la relación tendrá su propia cardinalidad, la cual indicará cuando
exista una sola o muchas instancias.

Por ejemplo, muchos empleados pueden trabajar en el mismo departamento (se


muestra una relación de muchos a uno):

Ordinalidad

Un rol puede especificarse de forma más detallada para indicar si puede o no estar
presente en una relación. La ordinalidad sirve para indicar si la entidad “target”
necesita ser especificada cuando la entidad “source” es creada.

Debido a que la ordinalidad es un valor lógico (verdadero o falso) es más práctico


referirse a ella como “opcionalidad” de la relación.

Mapeo de Relaciones

Existen básicamente dos formas de asociación:

• Las basadas en valores simples.

• Las basadas en colecciones de valores.

Dentro de esas formas de asociación, existen cuatro formas de “mapeo”:

• Relación One-To-One (valores simples)

• Relación Many-To-One (valores simples)

• Relación One-To-Many (colecciones de valores)

• Relación Many-To-Many (colecciones de valores)

A nivel de Base de Datos, la relación entre entidades significa que una tabla referencia
a otra tabla: aparece el concepto de “Foreign Key” para indicar aquellos campos de
una tabla que hacen referencia a la “Primary Key” de otra tabla.

A nivel de JPA las columnas que forman la “Foreign Key” se conocen como “Join
Columns” y emplean la anotación @JoinColumn para indicar dicha funcionalidad.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 40

1.3.2. Relación Many To One

Es la relación más típica que podemos encontrar en el mundo real.

En UML se requiere que la clase “source” tenga un atributo del tipo de la clase”target”
para poder navegar hacia ella.

Ejemplo: Si varios Empleados pueden trabajar en un Departamento, la relación de


entidades se puede modelar como se muestra a continuación:

Tenga en cuenta que:

a) La clase “source” tienen un atributo que corresponde al tipo de la clase “target”


(observe el atributo “departamento”).

b) A dicho atributo se le debe colocar la anotación @ManyToOne.

Ahora falta llevar la relación al modelo de base de datos siguiente:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 41

Las tablas físicas están relacionadas mediante la columna “DPTO_ID” en la tabla


“tbempleado” que apunta a la columna “DEPT_ID” en la tabla “tbdepartamento”.
Entonces, la “Join Column” de la relación es la columna “DPTO_ID”.

El lado que tiene a la “Join Column” se conoce como el “OWNER SIDE” de la relación,
mientras que el lado que no tiene a la “Join Column” se conoce como “INVERSE
SIDE”.

En este ejemplo, el lado OWNER es la tabla “tbempleado” y el lado INVERSO es la


tabla “tbdepartamento”.

La anotación @JoinColumn siempre se debe colocar en el lado “OWNER” de la


relación.

La entidad “Employee” debe quedar así (observe la anotación @JoinColumn):

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 42

Si no se coloca la anotación @JoinColumn, JPA asume el nombre por defecto, el cual


está formado por el nombre del atributo en la entidad owner seguido de un guión bajo
(“_”) y concatenado con el nombre de la columna PK en la tabla inversa.

1.3.3. Relación One to One

La relación “Uno a Uno” es casi igual a la relación “Muchos a Uno” con la sola
excepción que una instancia de la entidad “source” puede apuntar a una única
instancia de la entidad “target”. Estrictamente hablando, eso significa que la entidad
“target” no puede ser compartida por otras instancias de la entidad “source”.

A nivel de base de datos esta relación implica un criterio de “unicidad” o llave única en
la “Foreign Key” de la entidad “source”.

Obviamente se requiere definir la relación en la Entidad “Employee”: para ello se hace


uso de la anotación @OneToOne y también se requiere usar @JoinColumn (en este
caso, la columna de Join es “PARKING_ID”). La entidad “Employee” quedará así:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 43

1.3.4. Bidireccionalidad de la relación One-To-One

En algunas situaciones se requiere considerar la relación inversa entre las entidades,


también conocida como bidireccionalidad de la relación. La decisión es un criterio de
modelamiento, más no una obligación a nivel de programación.

Para lograr esto, se requiere que la entidad “target” tenga un atributo de la clase
correspondiente a la entidad “source”. Dicho atributo debe tener la anotación
@OneToOne con el elemento “mappedBy” que indique cual es el atributo de la clase
“source” que contiene la relación y apunta a la entidad “target”.

Ejemplo: en el caso de la entidad “ParkingSpace” (“es el “target” de la relación) se


tendría el siguiente atributo:

Y en el caso de la entidad “Employee” (que es el “owner” de la relación) tendríamos:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 44

Debe tenerse en cuenta dos reglas:

a) La anotación @JoinColumn se coloca en la entidad que mapea a la tabla que


contiene la columna de join (o a la entidad que es “owner” de la relación).

b) El elemento “mappedBy” debe colocarse a la anotación @OneToOne de la


entidad “inversa” o “target” de la relación.

1.3.5. Relación One To Many

Cuando una entidad se asocia con una “colección” de otras entidades estamos ante
una relación de “uno a muchos”.

En el ejemplo del Empleado vs. El Departamento, la relación es bidireccional por


naturaleza. En una relación bidireccional, siempre existen dos “mapeos”: uno por cada
relación.

A nivel de base de datos, las tablas siguen siendo las mismas.

Y a nivel de entidades, la entidad “Employee” es la misma.

Como se tiene que implementar el lado inverso de la relación entre Empleado y


Departamento, se debe modificar la entidad “Department” para agregar la relación
inversa “One-To-Many”: se debe “mapear” una colección de entidades “Empleado”
usando la anotación @OneToMany.

Adicionalmente, como este es el lado inverso de la relación, se debe usar el atributo


“mappedBy” para indicar cuál es el atributo dentro de la entidad “Employee” que
contiene la llave de la relación:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 45

NOTA: En este caso se está usando una colección indicado el tipo de los elementos
que almacena dicha colección: Collection<Type>. Esto genera una dependencia al
compilar por lo que no es recomendable.

La otra forma de colocar la relación es especificando el atributo “targetEntity” sin


especificar el tipo de dato contenido en la colección:

Esquemáticamente las dos relaciones se ven así:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 46

Es importante tener en cuenta que:

a) El lado “many-to-one” siempre es el lado “owner” de la relación. En


consecuencia, la anotación @JoinColumn debe estar en dicho lado.

b) El lado “one-to-many” es el lado “inverso”, por lo que el elemento “mappedBy”


debe ser utilizado en este lado.

c) Si no se especifica el “mappedBy”, JPA considera que es una relación


unidireccional de tipo one-to-many por lo que requiere el uso de una tabla de
Join. Tener en cuenta que esto puede ocasionar errores al desarrollar
aplicaciones.

1.3.6. Relación Many To Many

Cuando una o más entidades se asocian con una “colección” de otras entidades y
dichas entidades tienen relaciones sobrepuestas con las mismas entidades “target”, se
dice que estamos frente a una relación de tipo “Mucho-a-Muchos”.

Por ejemplo: Un “Empleado” pueden trabajar en múltiples “Proyectos” y cada


“Proyecto” puede tener a muchos “Empleados”.

De los ejemplos anteriores podemos manejar las siguientes entidades:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 47

La relación “Muchos-a-Muchos” se puede expresar en las dos entidades (“source” y


“target”) utilizando la anotación @ManyToMany. Teniendo en cuenta que:

a) Cuando la relación “Many-To-Many” es bidireccional, ambos lados de la


relación deben tener la anotación @ManyToMany.

b) No existen columnas de join en cada lado de la relación: la única forma de


implementar esta relación es utilizando una tabla de join, por lo que no existe
manera de determinar CUAL es el lado “owner” de la relación, en
consecuencia, se debe asumir que uno de los lados es el “owner”.

c) Al igual que en las relaciones bidireccionales anteriormente tratadas, el lado


que no sea “owner” debe utilizar el “mappedBy”, en caso se omita este
elemento, JPA deducirá que se trata de dos relaciones unidireccionales
separadas.

En el ejemplo, la anotación @ManyToMany debe colocarse en ambas entidades:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 48

El modelo de base de datos es:

A nivel de base de datos, una “Join Table” consiste simplemente de dos “Foreign Key”
o columnas de join que referencian (cada una) a un lado de la relación.

La anotación @JoinTable se usa para configurar la tabla de join de la relación:

a) Cada columna de Join se distingue dependiendo del papel dentro de la


relación: lado owner o lado inverso.

b) La columna de Join que pertenece al lado “owner” se describe usando el


elemento “joinColumns”.

c) La columna de Join que pertenece al lado “inverse” se describe usando el


elemento “inverseJoinColumns”.

En el ejemplo, falta indicar la JoinTable de la siguiente forma (asumiendo que


Employee es el owner de la relación).

Tenga en cuenta que el elemento “name” dentro de @JoinColumn especifica el


nombre de la columna en la tabla de Join, mientras que el elemento

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 49

“referencedColumnName” indica la columna que es “Primary Key” en la tabla que se


encuentra al extremo de la relación (sea owner o inversa).

Y en el lado inverso de la relación se pone el elemento “mappedBy”:

1.3.7. Opciones de Fetch

Las entidades y sus atributos pueden ser cargados de dos formas:

• LAZY: Cuando se cargan de forma “perezosa”, es decir, se cargan en el


momento en que se requieren.

• EAGER: Cuando se cargan de forma “proactiva”, es decir, al momento de


cargar la entidad “owner” de la relación.

En términos de JPA, se usa el elemento “fetch” acompañando a la anotación de la


relación e indicando el valor de FetchType.LAZY o FetchType.EAGER.

En una relación de valores simples el FetchType por defecto es EAGER.

En una relación de colecciones de valores, el FetchType por defecto es LAZY.

En una relación bidireccional, el FetchType puede ser EAGER en un sentido y LAZY


en el otro dependiendo del tipo de navegación que se desea.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 50

Resumen
1. Recordar que en JPA, existen cuatro tipos de relaciones entre entidades:

• One To One

• One To Many

• Many To One

• Many To Many

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o JPA: http://www.javaworld.com/javaworld/jw-01-2008/jw-01-jpa2.html

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 51

1.4. THE JAVA PERSISTENCE QUERY LANGUAGE

JPA soporta dos formas para expresar consultas que recuperan entidades desde una
base de datos:

• El lenguaje de consultas (queries), conocido como Java Persistence Query


language (JPQL), es un lenguaje independiente del manejador de base de
datos que trabaja con entidades en lugar de usar tablas.

• La API de criterios, que sirve para construir consultas basadas en objetos Java
en lugar de escribir los queries en strings.

1.4.1. Introducción a JPQL

Los antecedentes de JPQL se pueden encontrar en la especificación de EJB 2.0 con el


lenguaje EJB-QL en el cual se introdujo una forma de navegar entre los Beans y sus
relaciones, así como filtros y funciones agregadas.

Los queries operan dentro de una unidad de persistencia y pertenecen a una de las
siguientes clasificaciones:

a) SELECT, son queries que recuperan una o más entidades, filtrando los
resultados si fuera necesario.

b) AGGREGATE, los queries de este tipo son variaciones de los queries del tipo
SELECT, con la salvedad que agrupan resultados para producir información
sumarizada (de ahí la necesidad de usar la cláusula GROUP BY).

c) UPDATE, son queries que se emplean para actualizar un conjunto de


entidades.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 52

d) DELETE, son queries que se utilizan para remover un conjunto de entidades.

Al utilizar los queries se debe considerar que las entidades son referenciadas por su
nombre. Si una entidad no tiene asignado un nombre de forma explícita, JPA asume el
nombre de la clase como nombre por defecto: este nombre se conoce como “abstract
schema name” de la entidad dentro del contexto del query.

También, es importante resaltar que para los queries es indiferente el uso de


mayúsculas y minúsculas salvo en dos casos: nombre de entidades y nombres de
atributos de cada entidad.

Dada una entidad como la siguiente (entidad “Employee”):

El query más sencillo que se pueden ejecutar es el siguiente:

Observe que la notación es muy similar al SQL normal, pero con ligeras diferencias:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 53

a) En JPQL, lo que sigue a la cláusula “FROM” es el nombre de la entidad, es


decir, no se coloca el nombre de la tabla (recordar que la Entidad “mapea” a
una tabla).

b) En JPQL, es obligatorio que las entidades sean “calificadas” con un “alias”: en


el caso del ejemplo, el alias es “e”. Este “alias” se conoce como “variable de
identificación”.

c) El alias indicará que el resultado será uno o más entidades del tipo
correspondiente a la entidad.

d) El tipo de resultado de un Query no puede ser una Colección. Debe ser un tipo
simple o una Entidad.

A partir del uso del “alias” para la entidad, se puede utilizar la notación “dot” (el punto
“.”) para referenciar campos persistentes de la entidad. Por ejemplo, si queremos
seleccionar únicamente los nombres de los empleados sería así:

En este caso, como el campo “nombre” es un String, el resultado del query devolverá
uno o más Strings. De la misma forma puede trabajarse para cualquier otro atributo,
sea una lista, colección o campos simples.

El seleccionar algunos campos de la entidad (al igual que en SQL) recibe el nombre de
“proyección”. Se debe tener en cuenta su uso si es que se van a descartar (no usar)
varios atributos de la entidad al momento de generar reportes (dada la sobrecarga que
se genera en el framework JPA).

En el siguiente ejemplo, se puede seleccionar una entidad que no está en la cláusula


FROM:

Observe que “departamento” es una campo de la entidad “Employee”, pero a la vez es


una Entidad (dada la relación establecida @ManyToOne). Por tanto, el resultado de
ese query será una entidad “Department” obtenida a partir de la relación.

FILTROS

Al igual que en SQL, se puede filtrar los resultados a obtener utilizando la cláusula
WHERE y la notación “dot”.

JPQL incluye operadores como IN, LIKE y BETWEEN, funciones como SUBSTRING y
LENGTH además de soportar subqueries.

Ejemplo:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 54

En este ejemplo, el filtro lo constituye el atributo “nombre” de la entidad “Department”


que está vinculada con la entidad “Employee”.

JOIN ENTRE ENTIDADES

Al igual que en SQL, si se desea navegar entre las relaciones de las entidades y
retornar elementos de la colección, se debe ejecutar un JOIN entre entidades.

Se puede ejecutar el JOIN al más puro estilo del tradicional SQL indicando los criterios
de JOIN en la cláusula WHERE.

Sin embargo, JPQL proporciona la facilidad de especificar el JOIN dentro de la


cláusula FROM con la finalidad de expresar el JOIN en términos de la relación
existente entre las entidades: JPA se encargará de armar la sentencia SQL
equivalente.

Un JOIN ocurre si se cumple cualquiera de las siguientes condiciones en el SELECT:

1) Dos o más declaraciones de variables son listadas en la cláusula FROM y


aparecen en la cláusula SELECT.

2) El operador JOIN es empleado para extender a una variable de identificación


usando “expression path”.

3) Un “path expression” en cualquier parte del query navega a través de un campo


de asociación en la misma o en otra entidad.

4) Una o más condiciones WHERE comparan atributos de variables de


identificación diferentes.

Se debe tener en cuenta que ante la ausencia de condiciones de JOIN entre


entidades, se generará un producto cartesiano entre la primera entidad y cada
ocurrencia de la segunda entidad.

INNER JOIN

Un “inner join” entre dos entidades se puede especificar de cualquiera de la maneras


indicadas anteriormente. Sin embargo, la forma preferida es mediante el uso del
operador JOIN en la cláusula FROM.

La sintaxis básica es:

[INNER] JOIN <path_expression> [AS] <identifier>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 55

Ejemplo 1: se asume que “phones” contiene una relación JPA entre “Employee” y
“Phone”

Ejemplo 2: múltiples Joins (los joins se interpretan de izquierda a derecha desde el


FROM)

OUTER JOIN

Un “outter join” entre dos entidades produce un ámbito en el cual solo un lado de la
relación es requerido para completar el resultado. Por ejemplo, un outer join entre
“Empleado” y “Departamento” mostrará todos los empleados y los departamentos a los
que han sido asignados, pero con la salvedad que el “Departamento” será retornado
únicamente si existe dentro de la relación (a diferencia de un inner join).

Su sintaxis es la siguiente:

LEFT [OUTER] JOIN <path_expression> [AS] <identifier>

Ejemplo 1:

FETCH JOIN

Este tipo de Join sirve para ayudar a los programadores a optimizar los accesos a la
base de datos. Permite que los queries especifiquen una o más relaciones que deben
ser navegadas y pre-cargadas por el mecanismo de recuperación de datos de tal
forma que no se ejecuten “lazy load” en tiempo de ejecución. En otras palabras,
reduce la cantidad de accesos a la base de datos.

Ejemplo:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 56

QUERIES AGREGADOS

La sintaxis es muy similar a SQL: se requiere el uso del agrupamiento con GROUP BY

Es opcional el uso del filtro mediante la cláusula HAVING.

JPA incluye cinco funciones agregadas:

• AVG: Promedio aritmético.

• COUNT: Cantidad de repeticiones.

• MIN: Menor valor.

• MAX: Mayor valor.

• SUM: Suma de valores

Ejemplo:

En este ejemplo se obtienen todos los departamentos, la cantidad de empleados de


cada departamento, el sueldo máximo y el sueldo promedio teniendo en consideración
solo aquellos departamentos que tengan más de 5 empleados.

QUERIES

Existen dos formas para definir “queries” en JP-QL:

• La primera forma es definirlo dinámicamente en tiempo de ejecución como una


cadena de caracteres que se construye de acuerdo al flujo de la aplicación.
Esto implica compilar el “query” cada vez.

• La segunda forma es definir el “query” vía anotación o XML y referenciarlo por


el nombre cada vez que se requiera (algo similar a IBATIS). A diferencia de la
forma anterior, los “queries nombrados” son estáticos, pero son mucho más
eficientes para ser ejecutados.

1.4.2. Consultas dinámicas

Un query se puede definir de forma dinámica simplemente pasando una cadena de


caracteres con la sentencia JPQL al método createQuery () del EntityManager.

Ahora bien, se puede indicar el resultado esperado o se puede omitir y de esta forma
tendremos un query sin tipo definido (“unTyped query”).

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 57

Para aquellas aplicaciones que utilizan muchos queries, se debe considerar el costo
de “compilar” la sentencia JPQL:

1) Se ejecuta un “parse” de la cadena JPQL en un árbol de sintaxis para verificar


que esté correctamente escrito.

2) Para cada entidad dentro de la expresión se obtiene la metadata.

3) Se genera la sentencia SQL equivalente.

Se debe tener en consideración (al igual que en JDBC) las implicancias de concatenar
un query y luego pasarlo al EntityManager para evitar la inyección de código SQL
malicioso. Por ello es preferible usar parámetros. También, para aquellos queries
empleados con mayor frecuencia, es preferible usar los queries nombrados
(NamedQueries).

Un ejemplo con TypeQuery:

La sentencia JP-QL
TypedQuery

Clase que retorna el query

La clase Order.java tiene un método


toString()

Un ejemplo con Query:

La sentencia JP-QL

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 58

Query

La clase Order.java tiene un método


toString()

1.4.3. Consultas nombradas

Este tipo de query sirve para organizar y mejorar el desempeño de una aplicación.

Se define empleado la anotación @NamedQuery, la cual se coloca dentro de la


definición de una Entidad: la anotación define no solamente el nombre del query sino
también la sentencia JPQL en sí.

Se recomienda escribir los queries de manera ordenada de tal forma que ayuden a la
visibilidad y lectura de los mismos dentro de la definición de la entidad.

El nombre del query (atributo “name”) debe ser único dentro de toda la unidad de
persistencia. Si se hace caso omiso a esta restricción, los resultados pueden ser
imprevisibles en tiempo de ejecución.

Se puede definir múltiples queries nombrados empleando la anotación


@NamedQueries, la cual es un arreglo que acepta varias anotaciones
@NamedQuery.

Ejemplo: El mismo query del ejemplo anterior, pero ahora definido en la clase
Order.java

Nombre del Query

Query JPQL

Se invoca así:
Se especifica que es “NamedQuery”

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 59

Se especifica el nombre del Query

Si deseamos definir varios NamedQueries en la entidad, se tendría que hacer así:

Query JPQL #1
Anotación

Query JPQL #2

Y se puede invocar así:

Se especifica el nombre del Query

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 60

1.4.4. Uso de parámetros


Los parámetros enviados a un “query” permiten la reutilización de sentencias de forma
tal que las consultas ejecutadas con diferentes parámetros en cada invocación,
retornen diferentes resultados. Es preferible enviar parámetros a las consultas en lugar
de estar construyendo una nueva cadena de caracteres por cada invocación, pues así
se evita compilar repetidas veces los “queries”.

PARÁMETROS NOMBRADOS

Se utilizan cuando dentro de la sentencia JPQL, los parámetros van precedidos por el
símbolo de “:” seguido del nombre del parámetro.

Al momento de ejecutar el query, el programador debe especificar el nombre del


parámetro (empleando el método setParameter) y el valor a ser cargado para
reemplazarlo dentro de la sentencia JPQL.

Los parámetros nombrados proporcionan claridad al código de la sentencia JPQL


(cuando se utilizan nombres adecuados), por lo que son preferidos respecto a los
parámetros ordinales.

Ejemplo usando parámetros nombrados:

La sentencia JP-QL

Note el uso de “named


parameters”

Colocando los valores

PARÁMETROS ORDINALES

Se utilizan cuando dentro de la sentencia JPQL, los parámetros van precedidos por el
símbolo de “?” seguido del número del parámetro.

Al momento de ejecutar el query, el programador debe especificar el número del


parámetro y el valor a ser cargado para reemplazarlo dentro de la sentencia JPQL.

Ejemplo con parámetros ordinales:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 61

La sentencia JP-QL

Observe el uso de
parámetros ordinales

Se cargan los valores

1.4.5. Ejecución de Queries

JPA proporciona tres formas de ejecutar queries:

a) Para queries que retornan un único valor se aplica el método getSingleResult


().

b) Para queries que retornan una lista de valores se aplica el método


getResultList ().

c) Para queries que ejecutan sentencias de delete/update se aplica el método


executeUpdate ().

Se debe tener presente que:

a) Por defecto, los queries devuelven listas desordenadas.

b) Cuando se aplica el método getResultList (), el tipo de dato retornado es una


Collection (si no hay resultados, se devuelve una Collection vacía). Sin embargo, la
variable Java que recibe los resultados debe ser de tipo List. Ejemplo:

c) Cuando se aplica el método getSingleResult (), si no existen resultados se


devuelve la excepción NoResultException (la aplicación deberá controlar la
excepción). La ocurrencia de esta excepción no genera un rollback de la
transacción en curso.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 62

d) Cuando se aplica el método getSingleResult (), si existen muchos resultados (en


lugar de uno) se devuelve la excepción NoUniqueResultException (la aplicación
deberá controlar la excepción). La ocurrencia de esta excepción no genera un
rollback de la transacción en curso.

e) Cualquier query de tipo SELECT puede especificar además el uso de modos de


bloqueo para los registros seleccionados con el fin de no impactar en la base de
datos los indicadores de rendimiento. Esto se ejecuta vía el método setLockMode
().

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 63

1.4.6. Sintaxis de JPQL

Término Descripción

entityName Nombre de la Entidad. Por defecto es el nombre de la clase.

variable Identificador que sigue las reglas de Java.

state_field_exp Término utilizado para apuntar hacia un campo de la entidad.


Por ejemplo: Si “Alumno” está representado por la variable “a”,
se puede apuntar a los campos como: a.código, a.nombre.

single_rel_exp Término utilizado para apuntar hacia un campo de una entidad,


pero que resuelve relaciones de tipo one-to-one o many-to-
one.

Por ejemplo: Si “Alumno” está representado por la variable “a”,


se puede apuntar a los campos como: a.cursos, a.cursos.notas.

multi_rel_exp Término utilizado para apuntar hacia un campo de una entidad,


pero que resuelve relaciones de tipo one-to-many o many-to-
many.

Por ejemplo: Si “Alumno” está representado por la variable “a”,


se puede apuntar a los campos como: a.teléfonos

rel_field Término compuesto de una variable y una de los campos


relacionados sin navegar por relaciones intermedias.

Por ejemplo: Si “Alumno” está representado por la variable “a”,


se puede usar a.ciclo

constructor_method Constructor para una clase que no es Entidad.

Input_param Variable que representa a un parámetro de entrada y debe ser


asignado antes que el query sea ejecutado.

literal Valor de un tipo particular (por ejemplo un string como “hola” o


un int como 99).

pattern_value Un string que representa un valor SQL válido.

Por ejemplo: “%PEREZ”

escape_char Un carácter que representa una secuencia de escape.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 64

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 65

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 66

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 67

Resumen
1. Diferenciar las clases Query y TypedQuery.

2. Recordar que el método createQuery del EntityManager sirve para la creación de


consultas dinámicas.

3. Recordar que el método createNamedQuery del EntityManager sirve para la


creación de consultas “nombradas”, las cuales se definen como anotación
(utilizando @NamedQuery) dentro de la entidad respectiva.

4. Las anotaciones @NamedQuery y @NamedQueries se utilizan para definir


consultas “nombradas”.

5. El método setParameter sirve para asignar un valor a un parámetro de una


sentencia JPQL. Existen dos formas: por parámetro nombrado y por parámetro
ordinal.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o JPQL: http://www.objectdb.com/java/jpa/query/parameter

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 68

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 69

UNIDAD

2
JAVA SERVER FACES 2
LOGRO DE LA UNIDAD DE APRENDIZAJE
Al término de la unidad, el alumno, construye una aplicación Web utilizando el
modelo MVC y toda la funcionalidad provista por el framework JSF (Java
Server Faces) en Primefaces en la capa Vista y JPA en la capa controlador

TEMARIO
2.1 Tema 5 : Fundamentos de JSF
2.1.1 : Introducción a JSF
2.1.2 : Arquitectura de JSF
2.1.3 : Ciclo de vida de un request
2.1.4 : Facelets
2.1.5 : Managed Bean
2.1.6 : Lenguaje de Expresiones JSF
2.1.7 : Backing Beans

2.2 Tema 6 : Componentes de Interfaz de usuario


2.2.1 : Introducción
2.2.2 : Arquitectura de Componentes UI
2.2.3 Librería Core
2.2.4 Librería HTML
2.2.5 Librería User Interface
2.2.6 Librería de Componentes Compuestos

2.3 Tema 7 : Conversiones, Validaciones y Eventos


2.3.1 : Introducción
2.3.2 : El sistema de Conversión de JSF
2.3.3 El sistema de Validación de JSF
2.3.4 El sistema de Mensajes de JSF
2.3.5 El modelo de Eventos de JSF

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 70

2.4 Tema 8 : Integración JSF y JPA


2.4.1 : JSF y AJAX
2.4.2 : Integración JSF + JPA
2.4.3 : Empleando otras implementaciones de JSF
2.4.4 : Tablas JSF: Facets, dataTable y panelGrid
2.4.5 : Mantenimiento de tablas

ACTIVIDADES PROPUESTAS

• Implementar proyectos con la estructura JSF

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 71

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 72

2.1. FUNDAMENTOS DE JSF

2.1.1. Introducción a JSF

Java Server Faces (JSF) es el estándar “oficial” en la capa web para la plataforma
Java EE. JSF incluye un conjunto de componentes predefinidos para la interfaz gráfica
web (UI), un modelo de programación basado en eventos y la habilidad para añadir
componentes desarrollados por terceros.

El objetivo de la tecnología Java Server Faces (JSF) es construir aplicaciones web de


forma similar a cómo se construyen aplicaciones standalone con Java Swing, AWT
(Abstract Window Toolkit), SWT (Standard Widget Toolkit) o cualquier otra API similar.
JSF fue creado mediante el trabajo de la organización JCP (Java Community Process)
mediante la especificación JSR 127 iniciada a mediados del año 2001 y finalizada en
Marzo del 2004. Su principal objetivo es facilitar el desarrollo de interfaces gráficas
para las aplicaciones web por medio de los siguientes caminos:

• Proporciona un desarrollo basado en componentes, independientes del cliente.


De esta manera se incrementa la productividad del desarrollador.

• Simplifica el acceso y administración de los datos capturados o enviados a la


interfaz de usuario.

• Maneja de forma automática el estado de la interfaz de usuario entre múltiples


peticiones HTTP.

• Proporciona un “framework” amigable mediante el uso de patrones de


arquitectura para las aplicaciones web.

En resumen, toma los mejores elementos de los frameworks que le precedieron (CGI,
Servlet, JSP, Struts, Spring MVC) y los combina en un conjunto de API’s estándares
para el desarrollo de interfaces de usuario.

La versión actual es JSF 2.0 y está soportada por las siguientes especificaciones:

• JSR 127 : Java Server Faces ( http://www.jcp.org/en/jsr/detail?id=127 )

• JSR 252: Java Server Faces 1.2 ( http://www.jcp.org/en/jsr/detail?id=252 )

• JSR 276: Design-Time Metadata for JavaServer Faces Components


(http://www.jcp.org/en/jsr/detail?id=276 )

• JSR 314: Java Server Faces 2.0 (http://www.jcp.org/en/jsr/detail?id=314 )

Al ser JSF una especificación, se pueden encontrar implementaciones de diferentes


fabricantes, lo cual permite no vincularse con ningún proveedor en particular y tener la
total libertad de seleccionar aquel que más se acomode a nuestras necesidades.

Algunas implementaciones de JSF 2.0 son:


• Proyecto Mojarra (La implementación de referencia de SUN Microsystems
ahora propiedad de Oracle Corp.). Se puede consultar en el siguiente enlace:
https://javaserverfaces.dev.java.net/

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 73

• Oracle ADF Faces, que extiende la funcionalidad de JSF proporcionando


muchas funcionalidades Ajax.
• MyFaces (Fundación Apache http://myfaces.apache.org/ ).
• Rich Faces, alojado por Jboss (Grupo RedHat) en el siguiente enlace:
http://jboss.org/richfaces .
• ICE Faces, que contiene diversos componentes para interfaces de usuario más
enriquecidas. Se puede obtener información en el enlace:
http://www.icefaces.org/main/home/ .
• jQuery4jsf que contiene componentes basados en el Framework JavaScript
jQuery. Es un proyecto alojado por Google Code en el siguiente enlace:
http://code.google.com/p/jquery4jsf/

2.1.2. Arquitectura de JSF

Los objetivos de diseño de JSF y la manera en que los cumple se aprecian en el


cuadro siguiente:

Objetivo de Diseño Forma de Implementación


Objetivo #1: JSF proporciona una API basada en
Crear un framework estándar de componentes que se pueden usar para
componentes UI que pueda ser potenciado ensamblar aplicaciones web.
por herramientas de desarrollo y que a su
vez permita crear UI de alta calidad y Los componentes UI estándar proporcionados
manejar la incorporación de dichas UI’s a la por la especificación, están acompañados de
aplicación. “tag libraries” de tipo “core” y “html” (con
Objetivo #2: funcionamiento muy similar a JSTL)
Definir un conjunto ligero de clases Java
para los componentes UI, el estado de los
componentes y el manejo de eventos.
Objetivo #3:
Proporcionar un conjunto común de
componentes UI incluyendo los elementos
estándares para formularios HTML. Dichos

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 74

componentes deben poder servir para


definir nuevos componentes.
Objetivo #4: JSF proporciona un mecanismo de fácil empleo
Proporcionar un modelo de JavaBeans mediante el cual los componentes UI en el lado
para controlar los eventos en el lado cliente web están débilmente acoplados (mediante un
y conectarlos a la aplicación. Lenguaje de expresiones similar a JSTL) a los
POJO’s del servidor ( conocidos como
“Managed beans” )

Los “managed Beans” se declaran en el archivo


faces-config, xml o se usan anotaciones.

El control de la conversación se realiza en el


“JSF request process Lifecycle”.
Objetivo #5: El “JSF request process lifecycle” también
Definir API’s para validación de datos de permite manejar las validaciones y conversiones
entrada. dependiendo de los eventos que ocurren en la
aplicación.

JSF permite construir validaciones


personalizadas.
Objetivo #6: JSF proporciona el manejo de “resource
Especificar un modelo para el manejo de bundles” así como de localización (L10N). Los
i18N en los componentes UI. componentes UI automáticamente reconocen
estas características una vez que el “bundle” ha
sido configurado.
Objetivo #7: JSF proporciona API’s bastante flexibles
Proporcionar una generación automática basadas en tecnologías de “rendering” que
del formato apropiado de salida hacia un pueden ser “enchufadas” bajo demanda. Por
cliente determinado. ejemplo, si el cliente es un iPhone el “render” de
Objetivo #8: la página será HTML específico para dicho
Soportar accesibilidad equipo.

JSF confía plenamente en las tecnologías existentes de Java EE. Eso significa que
una aplicación JSF es básicamente una aplicación desarrollada bajo los estándares
Java EE con algunas configuraciones específicas:

Configuración #1: Dentro del “deployment descriptor” (archivo web.xml) de la


aplicación, se debe registrar el servlet controlador (llamado “Faces Controller”). Tener
en cuenta que en algunos contenedores web como GlassFish v3 no se requiere el
archivo web.xml.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 75

En caso de que el archivo web.xml no exista o no se encuentre, el “Faces Controller”


mapea los urls siguientes de forma automática:

• /faces/*

• *.jsf

• *.faces

También se puede agregar los siguientes “mappings” en el web.xml:

Configuración #2: Opcionalmente se puede tener un archivo de configuración de JSF


llamado faces.config.xml el cual está ubicado al mismo nivel que el web.xml

El archivo contiene la configuración de todos los elementos de una aplicación JSF,


aunque también pueden emplearse “anotaciones” en el código java para evitar el uso
de este archivo. Un ejemplo del contenido del archivo faces-config.xml es:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 76

Estas reglas se
conocen como JSF
Navigation Model

Configuración #3: Si se está ejecutando la aplicación en un contenedor web que no


soporta a JSF, las librerías del framework deben colocarse en el folder “lib” de la
aplicación:

La construcción de páginas se realiza con “Facelets XHTML” empleando para ello “tag
libraries”. Se puede declarar las librerías usando “XML namespaces” o usando la
forma tradicional:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 77

En resumen, una aplicación JSF es como cualquier aplicación web que incluye los
siguientes elementos:
• Las páginas web.
• Las librerías de etiquetas (o tags) para insertar componentes UI a las páginas.
• Un conjunto de “backed beans”, que son componentes que definen las
propiedades y funcionalidad de los componentes de UI.
• Archivos de configuración para el modelo navigacional (aunque es opcional).
• El indispensable archivo descriptor web.xml
• Archivos desarrollados por los programadores: convertidores, validadores,
listeners.
• Opcionalmente algunas etiquetas personalizadas para objetos UI
personalizados.

2.1.3. Ciclo de vida de un request

El ciclo de vida de una petición JSF es la secuencia de eventos que suceden cuando
se hacen peticiones HTTP con una aplicación JSF (la interacción entre el navegador
web y la aplicación).

La primera vez que se ejecuta la petición, JSF crea un árbol de componentes UI en


memoria. Para las siguientes peticiones el árbol es rápidamente construido de nuevo:
si se capturan valores en un formulario, estos son procesados y validados.

Si la validación es correcta, los valores capturados son cargados al modelo.

Luego, se procesan los eventos y se reportan los errores que pudieran ocurrir.

Si todos los eventos han sido procesados y el modelo ha sido actualizado


correctamente, se envía una respuesta final (render) al cliente. El manejo del ciclo de
vida de manera automática lleva un control de los cambios en los estados de tal forma
que el cliente siempre refleje los cambios en el lado servidor.

El ciclo completo se muestra en el gráfico:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 78

Una explicación detallada del ciclo:

FASE 1: Restore View


El concepto de “Faces View” es la representación en el lado servidor 3 (a manera de
espejo) de la interfaz de usuario que se muestra en el navegador.

En esta fase, se restaura una “vista” existente de alguna transacción anterior o se


genera una nueva en función a la petición HTTP entrante.

Si la petición es nueva, se genera una “vista” que se almacena en un objeto conocido


como “Faces Context”, el cual sirve como almacenamiento para los datos de la
petición http durante el manejo del ciclo de vida.

La vista generada sigue una estructura de árbol como la siguiente 4:

FASE 2: Apply Request Values

En esta fase, se ejecuta todo el trabajo de procesar los pares de datos (conocidos
como “value-pair parameters”) que llegan en el request desde la página mostrada en el
lado cliente: el parámetro y su valor.

De esta manera, cada elemento del árbol que representa a la “Faces View” se carga
con el valor respectivo como se muestra en el gráfico 5:

3
A diferencia de una estructura de árbol DOM que se forma en el navegador, en el caso de la “Faces
View”, se genera en el lado del servidor.
4
Gráfico tomado de “Java Server Faces 2.0: The Complete Reference, pág 40.
5
Gráfico tomado de “Java Server Faces 2.0: The Complete Reference, pág 41.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 79

Se debe especificar que existen dos tipos de componentes UI:

• Aquellos que pueden aceptar valores: campos de texto, cajas de chequeo, etc.

• Aquellos que permiten ejecutar acciones: botones y enlaces.

Es bueno saber que se puede alterar el curso normal de las fases para casos
especiales. Para ello se debe configurar el atributo “immediate” en un componente UI.

También es bueno especificar que existen 3 tipos de interfaces usadas:

• ValueHolder : implementada por todos los componentes UI que tienen el


atributo “value”

• EditableValueHolder: implementada por todos los componentes UI de un


formulario, que poseen valores editables.

• ActionSource: implementada por los componentes que generan acciones.

FASE 3: Process Validations

En esta fase se ejecuta la conversión y validación de los datos recibidos. JSF invoca
al método processValidators () en la instancia raíz de UIViewRoot el cual se propaga
recursivamente hacia los componentes UI del árbol.

Cuando cada método processValidators () de cada componente es invocado, se


ejecutan las conversiones y/o validaciones especificadas.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 80

Si ocurre algún error de conversión o validación, la propiedad “valid” se marca en


“false” y se encola un objeto “FacesMessage” en el FacesContext. Estos objetos serán
mostrados posteriormente en la vista del lado cliente.

FASE 4: Update Model Values

En esta fase, los datos se promueven hacia un objeto Java conocido como “Managed
Bean”.

El mecanismo es similar a las fases anteriores: en la instancia UIViewRoot se ejecuta


el método processUpdate () el cual se propaga en cascada. Solo los componentes
definidos como tipo UIInput pueden enviar datos a un objeto Managed Bean.

Al final la fase, todos los atributos del objeto “managed bean” tienen cargados los
valores de la “Faces View” como se muestra en el gráfico 6:

FASE 5: Invoke Application

Es en esta fase en la que cualquier código personalizado se puede ejecutar.

FASE 6 Render Response

En esta fase se ejecutan métodos encodeXXX () para enviar el componente al


cliente. Los encode los que hacen es seleccionar el mejor tipo de lenguaje de marcas
apropiado para el cliente: HTML, WML, XML, etc.

6
Gráfico tomado de: “Java Server Faces 2.0: The Complete Reference”, pág 43.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 81

Adicionalmente, se graba el estado actual de la “Faces View” para que esté disponible
en los subsiguientes requests.

Java Server Faces permite además que se pueda codificar “phase listeners” para
controlar la ejecución de código en algún punto exacto del ciclo de vida del request.
Para ello se debe:

• implementar la interface PhaseListerner.

• registrar la clase en el archivo faces-config.xml o usar anotaciones.

2.1.4. Facelets

La tecnología denominada “Facelets View Declaration Language” (VDL) fue


desarrollada como una extensión de JSF por Jacob Hookom e incorporada a la
especificación JSF 2.0. El objetivo fue reemplazar el uso de JSP (aunque se mantiene
el reconocimiento de los JSP por motivos de compatibilidad).

Los Facelets permiten a los desarrolladores declarar componentes UI en diferentes


tecnologías de presentación utilizando para ello plantillas (templates) HTML.

La meta de diseño principal fue permitir la composición de una vista a partir de


diferentes páginas físicas separadas 7.

Algunos conceptos importantes en esta tecnología:

a) Página (page): Se define así a la totalidad de la página web que es mostrada al


usuario. Se asocia con una viewId en el modelo de navegación.
b) Fragmento de página (page fragment): se generan y utilizan como si fueran
páginas, siendo la principal diferencia que los fragmentos no son páginas web
completas, sino que se emplean para “armar” páginas completas.
7
Patrón de diseño “Composite View”

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 82

c) Página de Plantilla (page template): son formatos reutilizables que se emplean


para construir páginas y/o fragmentos. Si existen porciones de página que son
comunes en muchas páginas web, se pueden crear plantillas para dichas
porciones.
d) Facet: son áreas dentro de la pantilla en donde el contenido puede ser
agregado por los desarrolladores cuando generan las páginas. Los facets
pueden tener un contenido por defecto.

En la tecnología JSP, los “templates” era codificados mediante el uso de:

• jsp:incluye

• <%@include %>

En la tecnología JSTL se utilizaba <c: import />

Las páginas en Facelets se generan usando XHTML. La idea de usar XHTML es


hacer portables a las páginas entre diversos ambientes de desarrollo.

Además, Facelets requiere el uso de “XML namespaces” para soportar las siguientes
librerías de tags:
• JSF HTML Tag Library.
• JSF Core Tag Library.
• JSTL Core Tag Library.
• JSTL Functions Tag Library.
• JSF Facelets Tag Library.

El encabezado de la página debe ser similar a esto (dependiendo de las librerías a


utilizar):

Las páginas en Facelets deben tener extensión .xhtml

En el archivo web.xml de la aplicación debe configurarse los siguientes “context


param”:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 83

El primer parámetro define que la extensión “.xhtml” es el sufijo por defecto de todas
las páginas que manejan contenido JSF.

El segundo parámetro indica que la implementación de JSF ignore los comentarios


XML en las páginas Facelets.

Una comparativa 8 entre JSP y Facelets:

Una gran característica de los Facelets (no disponible en JSP) es el poder generar
“templates”. Un “template” es una página XHTML que emplea algunos tags de
Facelets para definir varias “divisiones” lógicas de la vista como por ejemplo:
cabecera, pie de página y contenido. La idea es tener partes reusables de código sin
tener que repetir el mismo código en diferentes páginas.

8
Tomada del Libro: “Java Server Faces 2.0: The Complete Reference” , pág 58

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 84

Existen dos perspectivas para desarrollar “Templates” 9:

• Template File: es el archivo conteniendo la “plantilla” o estructura de


composición (formato) a generar. El contenido de este archivo está compuesto
por:

a. El contenido que debe ser mostrado a todos los clientes se escribe


directamente en el archivo.

b. El contenido que se puede reemplazar en cada archivo cliente se marca


con el tag <ui: insert>.

c. El “template” nunca debe ser accedido directamente por los clientes.

• Template Cliente file: es el archivo que corresponde con una viewId. Emplea
una o más páginas para generar el contenido basado en el Template File. Este
archivo contiene:

a. La especificación del “template file” mediante el tag <ui:composition>

b. La especificación del contenido a reemplazar con el tag <ui: define>


(que se asocia al tag <ui: insert> del “template file”).

Esquemáticamente se puede ver así:

9
Muy similar a Apache Tiles

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 85

La tecnología de Facelets proporciona tags en la librería denominada “ui” cuyo


namespace es http://java.sun.com/jsf/facelets :

Tag Descripción
ui:composition Se usa en archivos que funcionan como
“Template Client”.
Este tag le dice a JSF que los tags
internos deben incorporarse a la jerarquía
de UIComponent
Especifica el “template” a emplear.
El texto que se encuentre fuera de los tags
<ui: composition> no se toma en cuenta
para el render de la página.
ui:decorate Se diferencia del anterior en que el
contenido dentro del tag es incluido en la
página antes que recortado (como en el
caso del ui:composition)
Es muy útil cuando se tiene una serie de
elementos de una página que requieren la
misma apariencia.
ui:define Se usa en archivos que funcionan como
“Template Client”.
Define una región que será insertada
dentro de la composición (ui: composition).

ui:insert Se usa en archivos que funcionan como


“Templates” únicamente para indicar en
que parte del archivo se insertará el
correspondiente <ui: define> del template
cliente.
ui:include Al combinarse con <ui: param> permite la
inclusión personalizada de páginas.
Puede estar presente tanto en el
“Template” como en el “Template Client”.
ui:param Se usa exclusivamente dentro del <ui:
include> para definir parejas de valores
(nombre y valor) disponibles vía
expresiones EL.
TAGS QUE NO SON PARTE DE LOS TEMPLATES
ui:component Sirve para asociar tags del código a un
determinado UIComponent dentro del
árbol.
ui:fragment Similar a ui: component con la diferencia
que enmascara una serie de componentes
dentro de un componente padre antes de
incluirlo en el árbol de la vista.
ui:remove Se emplea para “comentar” un fragmento
de los tags y evitar que se muestren en la
vista.
ui:debug Permite que al presionar una tecla se
active una ventana mostrando el árbol de
componentes, las variables activas y cierta

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 86

información para depurar la aplicación.


Se debe configurar context-param en el
web.xml con el valor:
javax.faces.FACELETS_DEVELOPMENT
Si no se especifica “hockey”, el valor por
defecto es “CTRL-SHIFT-D”

Ejemplo de Template:

• Observe las primeras líneas de código y anote las declaraciones en el tag


<html>: se declaran los “namespaces” de las librerías.
• Observe los bloques con el tag <ui: insert>. Lo que está dentro del bloque es el
valor por defecto de esa zona (si es que el viewID no reemplazara nada).
• Observe la línea 9 para ver el uso de “resources folders”. En este caso, la
aplicación busca un folder “resources” y dentro de este, busca el nombre de la
library que está como parámetro (“css”).
• Los tags <ui: include> permiten incorporar contenido que se encuentra en otros
archivos, dentro del template o de la viewId.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 87

Ejemplo de viewID o página cliente:

• Observe las declaraciones del tag <html> en las primeras líneas.


• En la línea 10 se declara el <ui: composition> para indicar cuál es el archivo de
“layout” con el que trabaja esta página.
• Los bloques <ui: define> sirven para reemplazar el contenido de cada bloque
dentro de la zona de la plantilla identificada con el mismo nombre.
• Tenga en cuenta que el contenido que se encuentre fuera de los tags <ui:
composition> no aparecerá en los clientes.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 88

Ejemplo de tag <ui: decorate>:

En este caso se mostrará tanto el texto anterior como posterior al tag.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 89

2.1.5. Managed Bean

Al igual que el Framework Spring que proporciona la noción de “Inversión de Control


(IoC), JSF también proporciona una robusta habilidad para ello con las facilidades de
los “Managed Beans”.

Una “Managed Bean” es una clase Java que representa información de un formulario
web.

Para ello hace uso de los POJO’s (Plain Old Java Objects), que son objetos que
almacenan datos de la aplicación pero que no implementan o extienden ninguna
interfaz o clase específica de algún Framework.

Un POJO declarado dentro de una aplicación JSF se convierte en un “Managed Bean”


al cual nunca se le generará utilizando el método “new” de una clase Java. En lugar
de ello, el contenedor JSF inicializará el objeto únicamente cuando la aplicación lo
requiera (Lazy initialized).

Cualquier clase Java que siga las reglas de los Java Beans puede ser registrada como
una “Managed Bean”. Debe tenerse en cuenta que hay dos maneras de configurar los
“managed bean”:

• Usando anotaciones dentro del programa Java. Es la forma más recomendada


pues permite un código más cohesionado y fácil de mantener. Se emplea la
anotación @ManagedBean antes de la definición de la clase (desde JSF 2.0).

• Usando XML dentro del archivo faces-config.xml. Se emplea el tag


<managed-bean> para efectuar la declaración.

Un “managed Bean” típicamente tiene 3 partes:


a) Las propiedades del Bean: generalmente un getter y un setter por cada
atributo. Los métodos setter son invocados automáticamente por el JSF
cuando el formulario web es enviado.
b) Métodos para controlar acciones: Generalmente es solo un método, pero
podrían ser varios si es que el formulario posee múltiples botones de envío.
c) Un lugar para los datos resultantes: No es invocado automáticamente por JSF.
Debe ser llenado por el método controlador en base a los resultados de la
lógica de negocio.

Un ejemplo de una aplicación sencilla JSF: Se presenta un formulario donde se debe


ingresar un nombre y presionar el botón de “saludar”. La aplicación responde con una
página de saludo.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 90

El “Managed Bean” es bastante sencillo:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 91

Y la página de respuesta:

Como se ve en el ejemplo, el “Managed Bean” está marcado para funcionar en el


ámbito @SessionScoped. Sin embargo, los ámbitos pueden ser:

Ámbito Descripción Puede referenciar


a otros managed
Beans del ámbito
none Los Managed Beans con éste none
@NoneScoped ámbito no se generan ni
(sólo JSF 2.0) almacenan en ningún ámbito.

Ellos son generados bajo


demanda por otros Managed
Beans.

Su tiempo de vida depende del


Managed Bean que lo invocó.
request Pueden ser generados y están none, request,
@RequestScoped disponibles durante una view, session,
petición HTTP simple. application

Esto significa que el Bean


sobrevive a la navegación hacia

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 92

otra página.
view Permanecen disponibles none, view,
@ViewScoped durante el tiempo que el usuario session,
(sólo JSF 2.0) permanezca en la misma vista. application

Al salir de dicha vista, los


Managed Beans son
eliminados.
session Se almacenan en la sesión none, session,
@SessionScoped HTTP. Esto significa que los application
valores de sus atributos son
almacenados a lo largo de
múltiples peticiones HTTP para
un usuario.
application Retienen sus valores a lo largo none,
@ApplicationScoped de la vida de una aplicación, por application
lo que están disponibles para
TODOS los usuarios.
Custom El bean se almacena en un
@CustomScoped(value="#{so Mapa y el desarrollador tiene el
meMap}") control del ciclo de vida del
mismo.

2.1.6. Lenguaje de Expresiones JSF

El lenguaje de expresiones utilizado en JSF 1.0 y 1.1 era una extensión del JSP
Standard Tag Library (JSTL). La principal extensión que se introdujo en EL con JSF y
que no está presente en versiones anteriores es el concepto de “expresiones diferidas”
(deferred expresiones).

• En JSP, todas las expresiones que aparecen entre ${…} se evalúan


inmediatamente tan pronto como la página en “renderizada”.
• JSF introduce el procesamiento del ciclo de vida del request que controla lo
que sucede cuando se ejecuta un submit. Para ello, se introduce el concepto
de “expresión diferida” para permitir que las expresiones sean utilizables tanto
durante el rendering de la página como durante el submit.
• Este concepto permite que una expresión entre símbolos # {…} como por
ejemplo # {usuario.nombre} sirva tanto para mostrar un valor al usuario como
también para recibir el valor ingresado por el usuario.

El objetivo de tener un Lenguaje Unificado de Expresiones (EL) es proporcionar una


manera fácil de acceder a los objetos desde cualquier punto de la aplicación. En
general EL:
• Evita la necesidad de referir al objeto padre (request, sesión o application).
• Evita usar directamente los métodos get/set del objeto.
• Permite navegar de forma arbitraria en la jerarquía de objetos JavaBeans
(usando la notación .dot).

Por ejemplo:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 93

Esta expresión es una forma abreviada de invocar al método “getFirstName ()” de una
Managed Bean llamado “userBean”:
• La primera parte (en este caso “userBean”) es la “BASE” que indica el ámbito
donde buscar.
• La segunda parte (en este caso “firstName”) es la propiedad, la cual puede
navegarse usando la notación .dot.

Una facilidad que brinda E.L. es la invocación directa a métodos públicos y no


estáticos de los managed beans. Por ejemplo:

NOTA: Para que E.L. sea lo más simple posible, no está permitido el envío de
parámetros a los métodos.

JSF busca los objetos en un orden jerárquico comenzando por los objetos implícitos
para luego buscar en los managed beans de la aplicación. El siguiente cuadro resume
los objetos implícitos que pueden constituir la “BASE”:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 94

NOTA:
1) Las propiedades de los objetos que son de tipo Map se acceden usando:
# {MapObject [´key´]}
2) El objeto”Flash” es un tipo de almacenamiento temporal que permite que los
datos estén presentes en el siguiente request.

OPERADORES E.L.
Además de los corchetes (para Map) y del punto (.) existen otros operadores como se
muestra en la tabla siguiente:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 95

2.1.7. Backing Beans

Para implementar los backing beans en JSF, se debe crear una clase Java por cada
página JSF y registrar dicha clase como una managed bean. Lo usual es que la clase
Java se llame igual que la página.

Se recomienda que los backing beans se declaren en el ámbito del “request”.

En general, los backing beans se encargarán de armar toda la “tubería” necesaria


entre la página y el modelo, porque:
• Contienen las propiedades correspondientes a los campos de entrada del
formulario.
• Contienen “action methods” y “action listener” que corresponden a los
componentes UI.
• Contienen declaraciones de instancias de componentes UI que se vinculan a
los componentes UI utilizados en la página.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 96

Resumen
1. JSF es una especificación, por tanto tiene varias implementaciones de diversos
fabricantes.

2. Básicamente tiene 4 librerías: core, html, user interface y composite que pueden
ser complementadas con librerías de otros fabricantes.

3. El lenguaje de expresiones requiere la sintaxis: # {…} y permite la referencia a


propiedades de “managed beans” como también a métodos.

4. JSF tiene dos formas de navegación: la implícita y la explícita ( que requiere el


uso del archivo faces-config.xml )

5. JSF permite el empleo de “plantillas” mediante el uso de los tags d ela librería “ui”.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o Facelets:http://www.mkyong.com/jsf2/jsf-2-templating-with-facelets-example/
o JSF: http://www.mkyong.com/jsf2/jsf-2-0-hello-world-example/

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 97

2.2. COMPONENTES DE INTERFAZ DE USUARIO

2.2.1. Introducción

Los componentes UI Java Server Faces son elementos configurables y reutilizables


que componen la interfaz de usuario de las aplicaciones Java Server Faces.

Un componente se define como una pieza de software con reglas de uso bien
definidas que permitan que pueda ser utilizado por otros componentes.

Un componente de interfaz de usuario (UI Component) es un tipo específico de


componente que muestra contenido que puede ser modificado por el usuario a lo largo
del tiempo. Este contenido puede ir desde un simple campo de ingreso de datos o
botones, hasta elementos más complejos como árboles o datagrids.

La tecnología Java Server Faces proporciona un conjunto de clases de componentes


UI, que especifican toda la funcionalidad del componente, cómo mantener su estado,
mantener una referencia a objetos del modelo, y dirigir el manejo de eventos y su
representación para un conjunto de componentes estándar.

Estos componentes son completamente extensibles, lo que significa que podemos


extenderlas para crear nuestros propios componentes personalizados. Es más, la
tecnología JSF es tan flexible que proporciona una arquitectura de componentes que
incluye:

• Un conjunto de clases UIComponent para especificar el estado y


comportamiento de componentes UI.
• Un modelo de representación (“rendering”) que define cómo representar los
componentes de diferentes formas.
• Un modelo de conversión que define cómo conectar conversores de datos a un
componente.
• Un modelo de validación que define cómo registrar validadores con un
componente.
• Un modelo de eventos (“events”) y oyentes (“listeners”) que define cómo
manejar los eventos de los componentes.

Todas las clases de componentes UI de Java Server Faces descienden de la clase


UIComponentBase, que define el estado y el comportamiento por defecto de un
UIComponent. Las clases auxiliares como Renderer, tag Handlers, Validador,
Converter, etc técnicamente no son Componentes UI porque no colaboran en la
representación visual del componente.

Los Componentes UI además tienen un conjunto de archivos como imágenes, hojas


de estilo y JavaScripts que generalmente son responsables de la apariencia y
comportamiento de componente dentro de una página web. La especificación JSF se
refiere a dichos archivos como “recursos”.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 98

2.2.2. Arquitectura de Componentes UI

Los componentes UI se pueden clasificar en dos tipos:


• Aquellos que inician una acción como por ejemplo los botones.
• Aquellos que proporcionan datos como los campos de ingreso.

En JSF, los componentes se pueden ubicar en una de las dos clasificaciones


mencionadas en base a las interfaces que implementan según la especificación JSF
(para el primer caso es la interface ActionSource2 y para el segundo caso es la
interface ValueHolder o la interface EditableValueHolder). La razón para el uso de
interfaces es utilizar la más alta abstracción posible con el fin de encapsular las
capacidades de todos los componentes UI. De esta manera es mucho más fácil
entender todos los componentes JSF simplemente comprendiendo las interfaces que
se implementan.

Se debe indicar que los componentes, además de las interfaces mencionadas, pueden
implementar otras interfaces para definir un comportamiento particular.

El siguiente cuadro resume esta clasificación:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 99

Interfaz Características de un componente que Algunos componentes ( y las


implementa la interfaz subclases ) que implementan la
interfaz
EditableValueHolder Tiene un “valor” que puede ser • UIInput
editado por el usuario y enviado al • UISelectBoolen
servidor. • UISelectMany
La edición del valor puede • UISelectOne
deshabilitarse temporalmente. • UIViewParameter
ActionSource2 Ocasiona la ejecución de un • UICommand
ActionEvent cuando el usuario
presiona “click” sobre el
componente.
PartialStateHolder Tiene un “estado” que necesita Cada componente
mantenerse entre peticiones UIComponent y cada
HTTP. componente de ayuda (Helper
class )
ValueHolder Tiene un “valor” que no puede ser • UIOutput
editado por el usuario.
Es diferente al componente cuya
capacidad de edición puede ser
deshabilitada.
NamingContainer Proporciona un ámbito de • UIForm
nombres para sus componentes • UINamingContainer
hijos. • UIData

ClientBehaviorHolder Soporta el comportamiento del Todos los componentes HTML


cliente como por ejemplo Ajax estándares.

La jerarquía de clases de los componentes 10 dentro del paquete


javax.faces.component es la siguiente (donde la flecha continua significa “herencia” y
la discontinua significa “implementación”):

10
Fuente: Libro “Java Server Faces 2.0: The Complete Reference”, pág 140.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 100

Si bien esta jerarquía “encapsula” al componente, no describe la forma en que dicho


componente será mostrado al usuario.

Un ejemplo de algunos componentes UI:


• UICommand: Representa un control que dispara actions cuando se activa.
• UIForm: Encapsula un grupo de controles que envían datos de la aplicación.
Este componente es similar a la etiqueta HTML <form>.
• UIGraphic: Muestra una imagen.
• UIInput: Toma datos de entrada del usuario. Esta clase es una subclase de
UIOutput.
• UIOutput: Muestra la salida de datos en un página.
• UIPanel: Muestra una tabla.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 101

• UISelectItem: Representa un solo ítem de un conjunto de ítems.


• UISelectItems: Representa un conjunto completo de ítems.
• UISelectBoolean: Permite a un usuario seleccionar un valor booleano en un
control. Esta clase es una subclase de UIInput.
• UISelectMany: Permite al usuario seleccionar varios ítems de un grupo de
ítems. Esta clase es una subclase de UIInput.
• UISelectOne: Permite al usuario seleccionar un ítem de un grupo de ítems.
Esta clase es una subclase de UIInput.

Además, JSF proporciona un conjunto de componentes UI para HTML que facilitan el


desarrollo de aplicaciones web específicamente para clientes HTML (navegadores).
Dicho conjunto de componentes reside en el paquete javax.faces.component.html y
derivan de la misma jerarquía de clases mostrada, con la característica específica de
trabajar para clientes HTML.

Normalmente, el desarrollador no trabajará con los componentes directamente sino


que aprovechará las características proporcionadas por el “Renderer” de JSF: un
Renderer es una clase responsable de tomar una instancia del UIComponent y
generar la salida a ser mostrada según las características específicas del cliente.

Como se mencionó en el tema del ciclo de vida de un request JSF, el árbol de


componentes UI (que se conoce como “Vista”) es manejado por el ViewHandler. Sin
embargo, el StateManager se encarga de preservar el árbol de componentes entre los
subsiguientes requests. Para ello, se guarda el estado completo de los componentes
utilizando un mecanismo especificado en el web.xml de la aplicación:

Los parámetros a colocarse pueden ser:


• server: significa que el estado de la aplicación debe almacenarse en el servidor
entre cada request. Este es el comportamiento por defecto, por lo que no es
necesario colocarlo en el web.xml.
• client: significa que el estado de la aplicación se almacena en el cliente. Se
almacena como una marca dentro de la página de forma tal que aparezca
escondida y sea enviada como un campo oculto (tipo “hidden”).

La librería de componentes estándares está compuesta por cuatro librerías:

• La librería CORE: se asocia al namespace “f:” y proporciona utilidades para


validación, conversión, internacionalización, etc. La librería core no es
específica para clientes HTML dado que ninguno de sus componentes tiene
una representación visual en el lado cliente.
• La librería HTML: se asocia al namespace “h:” y está diseñada
específicamente para clientes HTML dado que proporciona un conjunto de
objetos comunes a muchas aplicaciones web: botones, campos de texto, etc.
• La librería de tags para Plantillas FACELET: asociada al namespace “ui:”
permite agregar funcionalidades de plantillas y formatos. Fue introducida en
JSF 2.0.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 102

• La librería de tags para Componentes Compuestos: introducida también con


JSF 2.0, se registra bajo el namespace “cc:” y agrega la habilidad para definir
un “contrato de uso” con componentes compuestos.

2.2.3. Librería Core

El namespace con el que se declara es http://java.sun.com/jsf/core y se le asigna el


prefijo “f”.

Se listan las principales funcionalidades de cada tag. Para el detalle de los atributos
soportados, por favor consultar la documentación de JSF.

Tag <f: actionListener>


Permite al desarrollador registrar de forma declarativa una instancia de ActionListener
sobre un Componente UI.

Un ActionListener es un manejador de evento que responde a eventos que suceden


en la página JSF.

Tag <f: ajax>


Permite al desarrollador agregar de forma declarativa, comportamiento Ajax al
componente asociado.

Tag <f: attribute>


Agrega un atributo con un nombre específico y un valor string a un componente dentro
del tag si es que dicho componente no contiene un atributo con dicho nombre.

Los valores se almacenan en un Map que es parte del componente de tal forma que
los valores persisten cuando se administra el estado de dicho componente.

Tag <f: convertDateTime>


Se utiliza para convertir valores String a valores java.util.Date.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 103

Tag <f: convertNumber>


Se utiliza para convertir valores String a valores java.lang.Number.

Este tag maneja una serie de patrones para formateo de los valores.

Tag <f: converter>


Este tag crea una instancia de la clase Java registrada con el ID especificado, la cual
debe implementar a la interfaz javax.faces.convert.Converter. Luego, asocia esta
instancia con el componente UI más cercano.

Tag <f: event>


Permite que el desarrollador registre de manera declarativa un
ComponentSystemEventListener en un componente UI.

Soporta dos atributos:


• listener: cuyo valor debe ser un “Method Expression” que se refiere a un
método con la misma firma que el método “processEvent” de la interfaz
ComponentSystemEventListener.
• type: especifica el nombre del evento.
➢ preRenderComponent
➢ preRenderView
➢ postAddToView
➢ preValidate
➢ postValidate

Ejemplo:

Tag <f: facet>


Representa un componente anidado que mantiene una relación “especial” con el tag
que lo encierra.

Tag <f: loadBundle>

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 104

Este tag permite manejar el modelo de i18N especificando un recurso (bundle) para el
“locale” de la vista actual. El contenido del “bunle” es cargado en un Map.

Tag <f: metadata>


Este tag encapsula un conjunto de elementos que se utilizan para especificar la
metadata para una vista Facelet. En consecuencia debe ser un tag hijo del tag f: view.

En el siguiente ejemplo, se especifica que el valor del parámetro que viene en el


request HTTP con el nombre “foo” será automáticamente recuperado y cargado dentro
de la propiedad “bean.foo”.

Tag <f:param>
Se utiliza para sustituir parámetros cuando se emplea dentro de un tag
<h:outputFormat> o para agregar valores “query-string” a un URL cuando se utiliza
dentro de <h:commandLink> o <h:outputLink>

Tag <f: phaseListener>


Sirve para registrar una instancia de PhaseListener sobre el UIViewRoot en donde se
encuentra anidado el tag.

Tag <f: selectItem>


Agrega un componente hijo de tipo UISelectItem al componente UIComponent más
cercano.
Ejemplo:

Tag <f: selectItems>


Este tag ubica al componente padre UIComponent más cercano y crea un nuevo
UISelectItems vinculándolo a dicho componente padre.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 105

Ejemplo 1: “ColoresMap” es un mapa (Map) a partir del cual se carga un listado de


colores.

Ejemplo 2: Ahora la lista de colores se toma desde una Collection.

Tag <f: setPropertyActionListener>


Este tag permite colocar un valor directamente en un atributo de un backing bean.

Ejemplo:

Tag <f: subview>


Sirve para crear una subvista. Es útil con JSP pero no tiene mayor trascendencia en
facelets. Sirve como contenedor para todos los componentes UIComponents usados
dentro de una página anidada que se incluye vía <jsp: include> o vía JSTL con <c:
import>.

Ejemplo:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 106

Tag <f: validateBean>


Este tag se integra al JSR 303 que especifica el “Bean Validation API”. El uso de este
tag causada que una instancia de javax.faces.validator.BeanValidator se registre en
el componente padre.

Ejemplo:

Tag <f: validateDoubleRange>


Sirve para generar validaciones sobre el componente padre. Soporta atributos de
máximo y mínimo.

Ejemplo:

Tag <f: validateLength>


Sirve para generar validaciones sobre Strings en el componente padre. Soporta
atributos de máximo y mínimo.

Ejemplo:

Tag <f: validateLongRange>


Sirve para generar validaciones sobre el componente padre. Soporta atributos de
máximo y mínimo.

Ejemplo:

Tag <f: validateRegex>


Este tag crea una instancia de javax.faces.RegularExpression y la asocia al
componente padre para efectuar las validaciones.

Ejemplo:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 107

Tag <f: validateRequired>


Este tag genera una instancia de javax.faces.Required y lo asocia al componente
padre.

La funcionalidad es la misma que si se configura el atributo “required” en “true” para


un componente editable.

Ejemplo:

Tag <f: validator>


Genera un validador y lo asocia al componente padre.

Ejemplo:

Tag <f: valueChangeListener>


Registra un Listener asociado a la instancia del component padre.

Ejemplo:

Tag <f: verbatim>


Este component es útil para JSP, pero no tiene mayor propósito con JSF Faceleters.
Crea y registra una instancia hija de UIOutput en el componente asociado más
cercano.

Sirve para anidar contenido en HTML, XML o cualquier otro lenguaje de marcas.

Ejemplo:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 108

Tag <f: view>


Sirve para crear una vista. La vista sirve como contenedor para todos los
componentes JSF utilizados en una página.

Tag <f: viewParam>


Permite que de forma declarative se registren parámetros como metadata asociada a
la vista padre por lo que debe ser un componente hijo del tag <f: metadata>. El
objetivo es soportar vistas “favoritas” que puedan ser invocadas vía método GET.

Ejemplo:

2.2.4. Librería HTML

El namespace con el que se declara es http://java.sun.com/jsf/html y se le asigna el


prefijo “h”.

Tag <h: body>


Es el tag encargado de mostrar los códigos HTML <body> y </body> en una vista.

Tag <h: head>


Es el tag encargado de mostrar los códigos HTML <head> y </head> en una vista. Se
utiliza para que JSF pueda incluir hojas de estilo y javascripts generados por los tags
<h: outputScript> y <h: outputStylesheet>

Tag <h: form>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 109

Es el tag que muestra un formulario para captura de datos. Todos los tags que se
encuentren en el interior serán enviados con el formulario. Configura un atributo
“action” apuntando a un URL que define la acción a ejecutar y el atributo “method”
configurado en “POST”.

Tag <h: outputScript>


Este tag muestra el tag HTML <script> con el atributo “src” determinado por los
valores de “name” y “library” ingresados.
La especificación de JSF 2.0 requiere que los recursos de la aplicación web sean
colocados debajo del folder “resources”.

Tag <h: outputStyleSheet>


Este tag muestra el tag HTML <link> con el atributo “href” determinado por los valores
de “name” y “library” ingresados. Además, muestra el atributo “rel” con los valores de
“stylesheet” y “text/css”.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 110

Tag <h: inputText>


Muestra un campo de entrada de datos con el tag HTML <input> y el atributo “type”
configurado en “text”.

Tag <h: inputTextarea>


Muestra un campo de entrada de datos con múltiples líneas usando el tag HTML
<textarea>.

Tag <h: inputSecret>


Este tag muestra una caja de ingreso de datos del tipo “password”, es decir, los
valores no se muestran al usuario.

Tag <h: inputHidden>


Este tag genera un campo “oculto” dentro de la página. El componente no se visualiza
al momento del “render” en el cliente.

Tag <h: outputLabel>


Este componente muestra una etiqueta de texto usando el tag HTML <label> y puede
de manera opcional, ser especificada para un campo de ingreso (con el atributo “for”).

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 111

Tag <h: outputLink>


Este componente muestra un enlace usando el tag HTML <a> con el atributo “href”
configurado con el valor del componente.

Si se desea enviar parámetros en el link se puede usar la forma siguiente:

Tag <h: outputFormat>


Muestra un texto formateado. El texto se muestra dentro de un tag HTML <span> si es
que se indica el atributo “id” o algún atributo de estilo.

Tag <h: outputText>


Muestra el valor del componente como texto dentro de una página.

Tag <h: commandButton>


Este componente muestra un botón con el tag HTML <input> y el “type” configurado a
“submit”, “reset” o “image”.

Puede ser asociado a un “backing bean” o a un ActionListener para manejar eventos.


La etiqueta del botón se especifica con el atributo “value” o con el “url” de la imagen.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 112

Adicionalmente, soporta la obtención del texto desde un Bundle para efectos de


manejar i18N.

• El tag emplea el método POST para enviar la data al servidor.


• El atributo “type” puede ser “submit” o “reset”.
• El atributo “action” se asocia a un método de algún backing bean.

Tag <h: button>


Este component es similar a <h: link> y fue introducido en JSF 2 para permitir el
soporte a vistas Facelets que puedan ser marcadas como favoritas (bookmarks).

Se presenta un problema si los navegadores tiene el javaScript deshabilitado debido a


que el tag genera un evento “onclick” para manejar la navegación vía
“window.location.href”.

Ejemplo:

Este código genera el siguiente HTML:

Tag <h: message>


Este componente muestra los mensajes generados por JSF para el componente
identificado por el atributo “for”.

Tag <h: messages>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 113

Muestra todos los mensajes almacenados.


Si el atributo “globalOnly” está en “true”, muestra los mensajes sin el identificador de
componente.
Utiliza celdas HTML de una tabla si es que se configura el atributo “layout” en “table”.

Tag <h: graphicImage>

Este componente sirve para mostrar una imagen utilizando el tag HTML <img> con el
valor del atributo “src” apuntando al valor del componente (value) o al atributo “url”.

En JSF 2 se agregan los atributos “library” y “name” para soportar imágenes desde
librerías de recursos.

Otra forma es usando el atributo “url”:

Tag <h: selectOneListBox>


Este componente muestra un <select> HTML cuyo tamaño de lista es igual a la
cantidad de elementos <option>. Solo permite la selección de un elemento.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 114

Tag <h: selectOneMenu>


Este componente muestra un <select> HTML cuyo atributo “name” es el ID del
componente y el atributo “size” es 1.

Cada opción del menú se muestra como un elemento <option>. Si la opción se marca
como deshabilitada, se agrega el atributo “disabled”.

Tag <h: selectOneRadio>


Este component muestra una table HTML con un conjunto de “radio buttons” entre los
cuales el usuario puede escoger.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 115

Tag <h: selectBooleanCheckbox>


Este componente muestra un elemento HTML <input> de tipo “checkbox”.

Tag <h: selectManyCheckbox>


Muestra una tabla con un conjunto de “checkboxes”.

Tag <h: selectManyListBox>


Muestra un tag HTML de tipo <select> pero permitiendo selecciones múltiples.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 116

Tag <h: selectManyMenu>


Muestra un tag HTML de tipo <select> permitiendo selecciones múltiples. El tamaño
de visualización es 1 (atributo “size”).

Este componente está diseñado para situaciones en las que se necesita mostrar un
menú de opciones al usuario para permitirle seleccionar múltiples opciones pero
utilizando un menú que solo muestra una opción a la vez.

La principal diferencia entre los “select” y los “menús” en JSF es el atributo “size”. Los
“menús” siempre tienen el “size” en 1 mientras que las listas pueden tener el tamaño
variable.

NOTA: Este componente no se visualiza correctamente en todos los navegadores.

Tag <h: panelGrid>

Es un contenedor tabular para otros componentes y es visualizado como una tabla


HTML. Los componentes hijos son visualizados como celdas dentro de la tabla.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 117

Tag <h: panelGroup>


Este componente crea un contenedor para agrupar a un conjunto de componentes
bajo un padre. Al visualizar los componentes hijos, se usa el tag HTML <span>.

Tag <h: dataTable>


Este componente genera un contenedor tabular para otros componentes hijos.

Tag <h: column>


Este tag sirve como “hijo” del tag <h: dataTable>.

2.2.5. Librería User Interface

El namespace con el que se declara es http://java.sun.com/jsf/facelets y se le asigna


el prefijo “ui”.

Sus tags han sido explicados en el tema de Facelets y Templates.

2.2.6. Librería de Componentes Compuestos.

El namespace con el que se declara es http://java.sun.com/jsf/composite y se le


asigna el prefijo “composite”.

Esta librería solo se declara y utiliza en páginas que requieren el empleo de


componentes compuestos JSF.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 118

Resumen
1. La librería CORE: se asocia al namespace “f:” y proporciona utilidades para
validación, conversión, internacionalización, etc.

2. La librería HTML: se asocia al namespace “h:” y está diseñada específicamente


para clientes HTML.

3. La librería de tags para Plantillas FACELET: asociada al namespace “ui:” permite


agregar funcionalidades de plantillas y formatos. Fue introducida en JSF 2.0.

4. La librería de tags para Componentes Compuestos: introducida también con JSF


2.0, se registra bajo el namespace “cc:”.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o JSF: http://javaserverfaces.java.net/users.html

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 119

2.3. INTEGRACIÓN JSF Y JPA

2.3.1. Introducción

JSF proporciona componentes para manejar los aspectos de conversión y validación


en el desarrollo de aplicaciones:

• Conversión: la realizan los “Converters” y garantiza que los datos sean del tipo
esperado. Los converters implementan la interfaz
javax.faces.convert.Converter.
• Validación: la realizan los “validators” para garantizar que los datos sean
válidos en función a las restricciones de la aplicación. Los validators son
implementaciones de la interfaz javax.faces.validator.Validator.

Es importante conocer que los “converters” al realizar una transformación de datos,


requieren ser asociados tanto a componentes de entrada como de salida. Mientras
que los “validators” solo se asocian a componentes de entrada.

Adicionalmente, JSF proporciona un sistema de mensajes que permite a los


desarrolladores controlar la visualización de los mensajes de conversión y validación
en las páginas, de una manera flexible utilizando uno o más tags de tipo <h:
message> o <h: messages>.

2.3.2. El sistema de Conversión de JSF

En la fase denominada “Apply Request Value” es justamente donde se ejecuta la


conversión de los valores que llegan desde el formulario hacia el tipo de dato
apropiado. Si la conversión es exitosa, los valores pasan a ser validados.

Todos los objetos que cumplan la función de “converters” deben implementar a la


interfaz javax.faces.convert.Converter.

Esta interfaz tiene dos métodos:

Donde:
• El parámetro “context” es la instancia “FacesContext” del request.
• El parámetro “component” es el componente cuyo valor será convertido.
• El parámetro “value” es el valor a ser convertido.

El método getAsObject es invocado durante el procesamiento de entrada, para


convertir los valores String que llegan en el request, al tipo de dato deseado.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 120

El método getAsString es invocado durante la fase de salida para mostrar los valores
en formato de String en cualquiera de las tecnologías de rendering que soporta el
cliente.

Si se lanza una excepción de tipo ConverterException, el componente se marca


como inválido y se coloca un mensaje en el FacesContext.

Los convertidores estándares son:

Todos los “converters” se puede llamar usando el tag <f: converter> y especificando
el ID, a excepción de DateTimeConverter y NumberConverter que tienen sus propios
tags: <f: convertDateTime> y <f: convertNumber>.

La forma implícita de conversión se realiza cuando JSF conoce el tipo de dato del
valor. Por ejemplo, asumiendo que “age” es un atributo de tipo Integer del managed
bean “user”, en el siguiente caso la conversión es implícita:

La forma explícita es cuando se usan los tres tags que proporciona la librería core de
JSF.

Tag #1: <f: convertDateTime>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 121

Donde:
• El “dateStyle” puede ser: short, medium, long, full o default.
• El valor de “type” puede ser: date, time o both (default).
• El valor de “binding” es una expresión que apunta a un método de una clase
que implementa la interfaz javax.faces.convert.Converter.

Tag #2: <f: convertNumber>

Donde:
• “type” puede ser number, currency o percentage.
• “currencyCode” es el código ISO 4217 de las monedas. Por ejemplo, “USD” es
para los dólares americanos y “EUR” para el euro. Para la moneda peruana se
tiene el código “PEN”.
• “currencySymbol” se puede especificar para indicar el símbolo de la moneda a
utilizar (pero se debe tener en cuenta que esto es válido con JDK 1.4 o
superior). El atributo “currencyCode” toma preferencia sobre este.
• “groupingUsed” es un flag boolean que sirve para indicar cuando se debe usar
un delimitador.
• El valor de “binding” es una expresión que apunta a un método de una clase
que implementa la interfaz javax.faces.convert.Converter.

Tag #3: <f: converter>

Donde:
• “converter-id” es el valor registrado en el archivo faces-config.xml de la
aplicación.
• El valor de “binding” es una expresión que apunta a un método de una clase
que implementa la interfaz javax.faces.convert.Converter.

Para vincular un Componente UI con un converter, simplemente hay que anidar el


converter dentro del tag:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 122

2.3.3. El sistema de Validación de JSF

La interfaz javax.faces.validator.Validator es el núcleo del sistema de validaciones


de JSF. Todos los objetos que cumplan la función de validadores deben implementar
esta interfaz.

Dicha interfaz tiene un único método:

Este método es invocado durante la fase de “Apply Request Values” si el componente


está marcado como “Inmediato” o durante la fase de “Process Validations” en caso
contrario.

Antes de invocar al método, JSF marca al componente como “inválido”.

El método lanza la excepción ValidatorException si ocurre un error durante la


validación: se almacena un mensaje en el FacesContext.

En caso no ocurran errores, el componente recién se marca como “válido”´.

A diferencia de los “converters”, los “validators” se registran por validator-id debido a


que el concepto de validación no está asociado al tipo del objeto.

Adicionalmente, JSF proporciona la facilidad de usar el atributo “required” en los tags.


Si esta propiedad está presente, se ejecutan las validaciones.

Los validadores estándares son los siguientes:

Validator-ID Tag Handler Descripción


javax.faces.DoubleRange f:validateDoubleRange Valida que el tipo de
dato sea
java.lang.Double y se
encuentre dentro del
rango especificado.
javax.faces.Length f:validateLength Valida que el tipo de
dato sea String y que
tenga la longitud mínima
especificada en el
parámetro.
javax.faces.LongRange f:validateLongRange Valida que el tipo de
dato sea java.lang.Long
y se encuentre dentro
del rango especificado.
javax.faces.Bean f:validateBean Sirve para indicar que el
valor sea validado por el
framework de validación

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 123

EE.
javax.faces.RegularExpression f:validateRegex Permite el uso de
expresiones regulares
javax.faces.Required f:validateRequired Tiene la misma
funcionalidad que el
atributo “required”:
campo obligatorio.

Para que JSF no valide campos que están vacíos se debe agregar lo siguiente al
web.xml:

Los validadores se pueden asociar a los componentes UI de dos maneras: usando


tags de la librería core o utilizando el MethodBinding.

• Usando los tags de la librería core: <f:validateDoubleRange>,


<f:validateLongRange> y <f:validateLength>

• Usando el MethodBinding:

En este caso, se asocia a un método del managed bean “user”:

2.3.4. El sistema de Mensajes de JSF

Los mensajes de error generados en la validación o en la conversión fluyen hacia el


usuario mediante la clase javax.faces.application.FacesMessage, el contexto
FacesContext y los componentes UIMessage y UIMessages.

La clase FacesMessage encapsula los mensajes que describen los problemas de


conversión y validación. Posee tres propiedades interesantes:
• severity: que puede ser INFO, WARN, ERROR, FATAL.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 124

• summary: contiene los mensajes de forma comprensible para el usuario.


• detail: contiene los mensajes de forma comprensible para el usuario.

La instancia de FacesContext mantiene dos colecciones de instancias


FacesMessage que pueden ser accedidas por diferentes formas del método
getMessages ():
• Una de mensajes asociados con un componente.
• La otra de mensajes que no están asociados con el componente.

El método getMessages () de la instancia FacesContext:


• Sin argumentos retorna un Iterator de todos los mensajes (estén asociados o
no con el componente).
• Con el argumento clientId retorna solo los mensajes asociados con ese
clientId. Si el clientId es NULL, retorna los mensajes que no están asociados
con un valor específico de clientId.

¿EN QUÉ MOMENTO SE GENERAN LOS MENSAJES?

Existen tres momentos dentro del ciclo de vida del request cuando los componentes
generan instancias de FacesMessage y las agregan al FacesContext:
1. Cuando falla una conversión.
2. Cuando falla una validación.
3. Cuando los datos, una vez convertidos y validados no pueden ser actualizados
en el modelo durante la fase denominada “Update Model Values”.

En el caso de la conversión, un error significa el lanzamiento de la excepción


ConverterException. La severidad de éste error siempre es ERROR. El converter
tiene dos opciones:
1. No envía parámetros al ConverterException, en cuyo caso, se genera un
FacesMessages con el mensaje “conversión failed”.
2. Se envía como parámetro una propiedad “message”, cuyo valor se utiliza como
la propiedad “detail” de FacesMessage.

En el caso del validador, un error significa el lanzamiento de la excepción


ValidatorException, el cual siempre envía un FacesMessage en su constructor. La
severidad de la excepción siempre está a nivel de ERROR.

En el caso de la actualización del modelo, cuando se lanza una excepción EL, se


examina el mensaje de la excepción. Si no es null, se crea un FacesMessage con el
mensaje como atributo “summary”. Si es null, se crea un FacesMessage con un
mensaje de error genérico.

¿CÓMO SE AGREGAN LOS MENSAJES?

Se tiene que agregar al FacesContext.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 125

¿CÓMO SE VISUALIZAN LOS MENSAJES?

Existen dos componentes estándares que permiten visualizar los mensajes:


UIMessages y UIMessage. En base a esos componentes, el kit de HTML tiene dos
“renderers”: javax.faces.Messages y javax.faces.Message respectivamente, de
manera tal que los tags a emplear son: <h: messages> y <h: message> que se
encuentran en la librería html.
a) Mostrando mensajes para un componente específico: al tag <h: message> se
le debe proporcionar el atributo “for” para indicar el “componentId” acerca del
cual se mostrarán los mensajes. De esta manera, el desarrollador puede
colocar los mensajes en cualquier lugar de la página.
b) Mostrando mensajes para todos los componentes: si se coloca el tag <h:
messages> en algún lugar de la página, todos los mensajes que se encuentran
en el FacesContext son mostrados a menos que se configure el atributo
“globalOnly” (en cuyo caso solo se muestran los mensajes que no están
asociados a un determinado componente). Además, se puede especificar el
atributo “layout” con los valores de “list” (los mensajes se muestran como
una lista HTML sin orden alguno) o “table” (los mensajes se muestran como
tabla HTML).
c) Personalizando los mensajes: el contenido de los mensajes por defecto puede
ser poco claro para efectos de una aplicación. Es posible proporcionar un
“Resource Bundle” (archivo .properties) con los mensajes que se desea
manejar y de esa forma sobre escribir los mensajes por defecto de JSF.

Para ello se debe agregar el siguiente bloque al archivo faces-config.xml:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 126

Tener en cuenta que este archivo requiere que los tags vayan en cierto orden
(debido al DTD). En este ejemplo se está indicando que el archivo de mensajes
se llama “MyMessages.properties” y que los idiomas soportados son español e
inglés.

Además, se debe tener en cuenta que para sobre escribir los mensajes por
defecto, el archivo de mensajes debe tener como “key” los messagesID del
framework y como “value”, los textos que se desea para la aplicación.

Algunos de los messageID estándares que pueden ser sobre escritos son:

• javax.faces.component.UIInput.CONVERSION
• javax.faces.component.UIInput.REQUIRED
• javax.faces.component.UISelectOne.INVALID
• javax.faces.component.UISelectMany.INVALID
• javax.faces.converter.BigDecimalConverter.DECIMAL
• javax.faces.converter.BigIntegerConverter.BIGINTEGER
• javax.faces.converter.BooleanConverter.BOOLEAN
• javax.faces.converter.ByteConverter.BYTE
• javax.faces.converter.CharacterConverter.CHARACTER
• javax.faces.converter.DateTimeConverter.DATE
• javax.faces.converter.DateTimeConverter.TIME
• javax.faces.converter.DateTimeConverter.DATETIME
• javax.faces.converter.DateTimeConverter.PATTERN_TYPE
• javax.faces.converter.DoubleConverter.DOUBLE
• javax.faces.converter.FloatConverter.FLOAT
• javax.faces.converter.IntegerConverter.INTEGER
• javax.faces.converter.LongConverter.LONG
• javax.faces.converter.NumberConverter.CURRENCY
• javax.faces.converter.NumberConverter.PERCENT
• javax.faces.converter.NumberConverter.NUMBER
• javax.faces.converter.NumberConverter.PATTERN
• javax.faces.converter.ShortConverter.SHORT
• javax.faces.converter.STRING
• javax.faces.validator.NOT_IN_RANGE
• javax.faces.validator.DoubleRangeValidator.MAXIMUM
• javax.faces.validator.DoubleRangeValidator.MINIMUM
• javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE
• javax.faces.validator.DoubleRangeValidator.TYPE
• javax.faces.validator.LengthValidator.MAXIMUM
• javax.faces.validator.LengthValidator.MINIMUM
• javax.faces.validator.LongRangeValidator.MAXIMUM
• javax.faces.validator.LongRangeValidator.MINIMUM

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 127

• javax.faces.validator.LongRangeValidator.NOT_IN_RANGE
• javax.faces.validator.LongRangeValidator.TYPE

Se puede editar el archivo “messages.properties” que se encuentra en el jar de las


API’s de JSF y ver todas las llaves disponibles.

2.3.5. El modelo de Eventos de JSF

JSF proporciona un modelo de programación basado en eventos que es muy similar al


que se utiliza en el desarrollo de aplicaciones Swing o AWT. Esto permite un mejor
control de interfaces de usuario complejas debido a que los componentes de dicha
interfaz publican cambios en sus estados (eventos) hacia un conjunto de objetos que
actúan como “listeners” y que ejecutan las tareas requeridas.

Hay dos tipos de eventos:


• Los eventos de aplicación
• Los eventos de ciclo de vida

Los eventos pueden ser publicados a lo largo del ciclo de vida de una aplicación JSF.
Este ciclo de vida puede ser dividido en tres etapas:
• inicio (start-up).
• ejecución de procesamiento del ciclo de vida del request. La mayor parte del
tiempo, la aplicación se ejecuta en esta etapa.
• finalización (shutdown).

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


PROYECTO EMPRESARIAL 128

Los eventos publicados durante la etapa de procesamiento del ciclo de vida de los
request se muestran en el siguiente gráfico:

Los eventos que ocurren durante el start-up son:


• PostConstructApplicationEvent

Los eventos que ocurren durante el Shutdown son:


• PreDestroyApplicationEvent

Los eventos que ocurren en cualquier momento del ciclo de vida de la aplicación:
• ExceptionQueuedEvent
• PostConstructCustomScopeEvent
• PreDestroyCustomScopeEvent
• PostConstructViewMapEvent
• PreDestroyViewMapEvent
• PostAddToViewEvent
• PreRemoveFromViewEvent

EVENTOS DE APLICACIÓN

Tipo de Evento Momento en el que se procesa


Al completar la fase denominada “Invoke
ActionEvent Application” a menos que se use el flag
“immediate” con el valor “true” en cuyo
caso se procesa al final de la fase “Apply
Request Value”.
Al finalizar la fase de “Process
ValueChangeEvent Validations” a menos que el flag
“immediate” esté en “true”, en cuyo caso
se procesa al final de la fase “Apply
Request Value”.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


PR OY EC T O E MP R ES A R I AL 129

En general, para manejar eventos Faces se puede escribir una clase “listener” que
implemente la interfaz apropiada (javax.faces.event.ActionListener) y que se vincule al
componente (en este caso, al UIComponent).

Para “Action Events” sin embargo, se puede escribir: o un método en una clase
“Action” o un método en una clase “Listener”. La explicación es la siguiente:

a) Un “action method” es un simple método Java que tiene lugar en un “managed


bean”, no tiene argumentos y retorna un String. Estos “action methods” son
manejados por un ActionListener, que por defecto toma el valor del String y lo
envía al NavigationHandler con el fin de determinar el siguiente paso de
navegación.

Un “action method” se asocia a un UIComponent con el atributo “action”.


Ejemplo:

b) Si no se requiere navegación, se utilizan los “action listener method”, que es un


método que simplemente se ejecuta y que no devuelve resultados (retorna
void). Se asocia a un UIComponent con el atributo “actionListener”.

Los “Value Change Events” son eventos que se emplean para indicar que el valor
de un componente UI ha cambiado. Generalmente, se emplea para componentes que
implementan las interfaces ValueHolder o EditableValueHolder.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 130

Al igual que los “action events”, los “value change events” pueden manejarse de la
misma manera.

Sin embargo, debe tenerse presente que el evento ocurre cuando se hace el submit
del formulario. Es más, el evento sucede en la fase de “Process Validations”. Un
siguiente envío del formulario sin alterar el valor, no genera que se dispare el evento
debido a que no ha cambiado el valor del campo.

Si se agrega el atributo “immediate” y se configura en “true”, se puede disparar el


evento de cambio en la fase de ”Apply Request Values”.

Para personalizar los Listeners se debe tener en cuenta que:


• Si se implementa la interfaz ActionListener se debe anidar dentro del
componente UI el siguiente tag:

• Si se implementa la interfaz ValueChangeListener se debe anidar dentro del


componente UI el siguiente tag:

EVENTOS DE FASE
Los eventos de fase (o “Phase Events”) se procesan entre cada fase del
procesamiento de ciclo de vida de un request.

Se puede crear un Listener simplemente implementando la interfaz PhaseListener.


Esta interfaz posee tres métodos que deben ser implementados:
• beforePhase()
• afterPhase()
• getPhaseId()

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 131

Los métodos beforePhase () y afterPhase () se ejecutan para todas las fases del ciclo
de procesamiento de un request, por tanto, si se desea ejecutar alguna lógica especial
en determinada fase, se deberá obtener el ID de la fase y en base a condiciones,
controlar el flujo del código.

El método getPhaseId () sirve para determinar a qué fase está asociado el listener.
Cuando se usa para cualquier fase retorna el valor ANY_PHASE:

Finalmente, el listener debe registrarse en el faces-config.xml:

EVENTOS DE SISTEMA

Este tipo de eventos fueron introducidos con la especificación JSF 2.0 y proporcionan
mayores detalles que los ofrecidos por los eventos de fase.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 132

Resumen
1. Dentro del procesamiento del ciclo de vida de un request, lo primero que se
ejecuta es la conversión de datos que llegan desde el request. SI todo funciona
bien, recien se ejecuta la validación de estos.

2. Un conversor personalizado implementa la interfaz javax.faces.convert.Converter.


El método getAsObject se aplica cuando se reciben los datos del request y el
método getAsString se aplica para devolver la visualización al cliente.

3. Un validador personalizado implementa la interfaz javax.faces.validator.Validator.


Tiene un único método validate en donde se debe escribir la lógica de validación
deseada.

4. Los mensajes de error se muestran con los tags <h: message> y <h: messages>.
Para personalizarlos, se requiere definir el archivo de recursos en el faces-
config.xml

5. Los eventos más utilizados en JSF están relacionados con la pulsación de


botones o el cambio de valores en la página: ActionEvent y ValueChangeEvent.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o JSF: https://javaserverfaces.java.net/

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 133

2.4. INTEGRACIÓN JSF Y JPA

2.4.1. JSF y AJAX

JSF se constituye en el mejor framework que se integra y facilita el uso de las


capacidades de Ajax.

El concepto de AJAX corresponde a un conjunto de tecnologías (Hojas de estilo,


JavaScript, Document Object Model, etc.) que permiten ejecutar llamadas asíncronas
al servidor y procesar la respuesta modificando el árbol DOM que se almacena en el
navegador.

JSF proporciona dos maneras de trabajar con AJAX, la primera forma es mediante un
tag nuevo identificado como <f: ajax> mediante el cual no hay que preocuparse
acerca del uso de javaScript. La segunda forma es el uso de una API de JavaScript
llamada jsf: ajax.request () que proporciona un puente estándar para las peticiones
de tipo Ajax.

TAG <f: ajax>

JSF proporciona un tag para el manejo de llamadas AJAX: <f: ajax>, que al igual que
otros tags de la librería core, no puede ser empleado aisladamente. Es decir, debe ser
anidado o debe contener a otros tags que se asocien con un Componente UI.

Los atributos que acepta este tag pueden dividirse en dos:

Atributos que actúan sobre el “server-side”


Atributo Valor
execute Lista de ID’s separada por comas, expresión que se
evalúa como lista o palabra reservada.

Indica los valores a ser enviados en el POST.


render Lista de ID’s separada por comas, expresión que se
evalúa como lista o palabra reservada.

Indica la porción de la vista (subtree) a ser renderizada.


listener Expresión que invoca a un método Java. Dicho método
tiene la siguiente firma:
void método( AjaxBehaviourEvent abe )

Si el valor no es nulo, el método es invocado durante la


fase denominada “Invoke Application” en el
procesamiento del ciclo de vida del request.
immediate True/false o alguna expresión que devuelva uno de esos
valores.
disabled True/false o alguna expresión que devuelva uno de esos
valores. Si es “true”, el tag está deshabilitado.

Atributos que actúan sobre el “client-side”


Atributo Valor
event String que contiene uno de los nombres de eventos

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 134

soportados.

Cuando sucede el evento, se envía un request de tipo


POST hacia el servidor.
onevent Nombre (o Expresión que devuelve un nombre) de una
función JavaScript que acepta un argumento y que
maneja el status del request/response.
onerror Nombre (o Expresión que devuelve un nombre) de una
función JavaScript que acepta un argumento y que
maneja el status del request/response.

Si no es específica y el modo “Development” está


configurado, solo la implementación JSF Mojarra muestra
un diálogo de alerta.

Por default, todos los componentes UI de captura de datos disparan el evento


“valueChange”.

Ejemplo:

JAVASCRIPT ESTÁNDAR

Todas las implementaciones de JSF 2 deben contener una librería denominada


“javax.faces” la cual contiene un Script llamado “jsf.js” que expone una serie de
API’s estándares para ejecutar las invocaciones Ajax.

Existen dos objetos principales dentro del javaScript: ajax y útil. El objeto “ajax” tiene
las funciones siguientes:

Función JavaScript Significado


addOnError(callback) Proporciona la misma implementación
que el atributo “onerror” del tag <f:ajax>
addOnEvent(callback) Proporciona la misma implementación
que el atributo “onevent” del tag <f:ajax>
request(source, event, options) Proporciona la misma implementación de
la parte del request del tag <f:ajax>
response( request, context ) Proporciona la misma implementación de
manejo del response que el tag <f:ajax>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 135

La función más importante es “request”, la cual toma tres parámetros:


• source: es el elemento DOM que dispara el requerimiento Ajax. Normalmente
su valor es “this”.
• event: es opcional y corresponde al evento DOM que dispara el requerimiento
Ajax. Se usa normalmente para recuperar información adicional sobre el evento
(por ejemplo que tecla fue presionada).
• options: también es opcional. Contiene una lista de llaves y valores según la
relación siguiente:

➢ execute: lista de ID’s (separadas por comas) a ser procesada durante el


request.
➢ render: lista de ID’s (separadas por comas) a ser reemplazados durante el
response.
➢ onevent: Función JavaScript a ser invocada para el evento.
➢ onerror: Función JavaScript a ser invocada si hay un error.
➢ params: parámetros a ser incluidos en el request.

Las opciones más importantes son “execute” y “render” y bajo JSF 2 permiten el
concepto de “vista parcial”: es un mecanismo que permite que el procesamiento de
ciclo de vida de un request se ejecute sobre uno o más componentes. Solo los
componentes identificados en el request sufren el proceso de validación, conversión y
actualización del modelo. De igual forma, en el “render”, solo los componentes
indicados sufren la actualización en el árbol DOM sin tener que refrescar toda la
página.

Adicionalmente, en lugar de identificar cada uno de los componentes para el “execute”


y el “render”, se puede emplear algunos “toquen”:

Token Significado
@all Todos los componentes de la vista

@none Ningún componente ( es el default para el render )

@this Es el componente que dispara el evento (valor por defecto


para execute)

@form Todos los componentes del formulario

Para poder utilizarla la librería JavaScript es preciso incorporar en la página Faces el


siguiente tag:

Este tag le dice a JSF que coloque el script en la cabecera de la página.

Luego, al componente UI se le define el atributo correspondiente al evento que se


desea manejar:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 136

En este caso, se define el evento “onkeypress”: cada vez que se pulse una tecla, dicho
valor aparecerá en el campo con id “outNombre”.

2.4.2. Integración JSF + JPA

Las entidades JPA también pueden funcionar como “Managed Beans” simplemente
agregando las anotaciones @ManagedBean y la anotación de ámbito respectivo (por
ejemplo @RequestScoped).

Es aconsejable emplear JSF 2 con EJB 3.0 y JPA para que el contenedor de EJB’s
controle las transacciones. Sin embargo, se puede utilizar directamente JPA pero se
debe tener en cuenta que hay que manejar la persistencia y las transacciones de
forma manual.

• Enterprise Java Beans (EJB) es una arquitectura de componentes Java en el


lado servidor que permite el desarrollo rápido y simplificado de aplicaciones
portables, distribuidas, transaccionales y seguras basadas en la plataforma
Java EE.

• Java PErsistence API (JPA) es un framework basado en Java que permite


manejar datos relacionales en aplicaciones que emplean Java SE o Java EE.

En todo caso, si se emplea la tecnología de EJB 3.0, se requiere contar con un


servidor de Aplicaciones como WebSphere de IBM, Oracle WebLogic o JBoss, dado
que Apache Tomcat no soporta contenedores de EJB.

Al igual que con Struts 2, se requiere el archivo persistence.xml dentro del folder
META-INF y las librerías de la implementación de JPA (para el curso es
EclipseLink).

Un ejemplo de managed bean con JPA:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 137

Observe que se controla la excepción en caso no existan datos: se coloca un mensaje


en el contexto de JSF para emplear luego el tag <h: messages /> en la página de
login.

2.4.3. Empleando otras implementaciones de JSF

Como se había mencionado, JSF es una especificación, la cual está soportada por
diversas implementaciones. Cada implementación proporciona un conjunto de tags
que presentan determinada funcionalidad, la cual debe ser evaluada según las
necesidades del proyecto.

Lo bueno de trabajar con las implementaciones es que en la mayoría de casos, todas


pueden coexistir dentro de una página.

Una implementación ligera que contiene un único archivo .jar, no requiere


configuración y no tiene dependencias (a diferencia de Apache MyFaces) es
PrimeFaces ( http://www.primefaces.org ).

PrimeFaces proporciona un conjunto de componentes muy interesantes con un gran


diseño y funcionalidad a la vez que le otorga un tratamiento especial al tema de Ajax
como veremos en el siguiente ejemplo.

Descargar la librería (para JSF 2) desde el URL de Primefaces (


http://www.primefaces.org/downloads.html ) y configurar el Build Path del proyecto.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 138

No olvidar de configurar también el CLASSPATH del servidor. Si el servidor es


Tomcat, debe quedar así:

A continuación, se muestra el encabezado de la página XHTM. Note que la librería de


PrimeFaces está identificada como “p”:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 139

Y el fragmento de código que emplea Tags de PrimeFaces:

El proceso es bastante sencillo: se debe ingresar un ID que será verificado cuando el


usuario presione el enlace de verificación. Este ID será validado disparando la acción
denominada “nickAction” del Managed Bean utilizando AJAX.

El tag p: ajaxStatus controlará el procesamiento de la petición AJAX y mostrará u


ocultará la figura “ajax-loading.gif”

El código del ManagedBean:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 140

Y Lo que se debe visualizar en el navegador. Observe el diseño más elaborado.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 141

2.4.4. Tablas JSF: Facets, dataTable y panelGrid.

Tag <f: facet />


Este tag establece que el componente anidado tiene una relación especial con el
componente padre.

Un “facet” representa una sección identificada con un nombre (el único atributo que
tiene es “name”) dentro de un componente UI que actúa como contenedor.
Normalmente se puede observar su utilización con componentes UI complejos (como
PanelGrid o DataTable).

Por ejemplo, los títulos que forman el encabezado de una tabla, en estricto, no forman
parte de la relación con el componente padre, por tanto, son candidatos a ser
definidos como “facets”. Durante el “rendering” del componente padre, todos los tags
“facet” son mostrados también.

Ejemplo:

Esto mostrará algo similar a esto (asumiendo que el valor de “beanLogin.clave” es


“TEST1”

Tag <h: column />


Este tag sirve como un “hijo” inmediato del tag <h: dataTable>. Sirve para la definición
de columnas y puede ser equipado con “facets” llamados “header” y “footer” para
crear encabezados y pies en las tablas.

Los atributos que soporta son:

Atributo Tipo Descripción


binding Expresión que La referencia a una instancia de opcional
retorna un valor un componente UI.
id String Identificador del componente. opcional
rendered boolean Indica si el componente se opcional
mostrará durante la fase “Render

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 142

Response”. Por defecto es “true”.


footerClass String Lista (separada por comas) de los opcional
estilos que se aplicarán al footer
de esta tabla.
headerClass String Lista (separada por comas) de los opcional
estilos que se aplicarán al header
de esta tabla.

Tag <h: dataTable />


Este tag permite solucionar aquella situación en la cual el controlador genera una lista
de datos de tamaño variable y el desarrollador se enfrenta al problema de generar la
página de salida sin tener la obligación de usar scripting o hacer iteraciones.

Este tag genera una tabla HTML a partir de una colección de objetos, donde los
componentes anidados (tag <f: column>) son responsables de mostrar las columnas
de la tabla. Las columnas pueden contener cualquier tipo de componente.

El cuerpo de la tabla se muestra dentro del tag HTML <tbody>.

Los datos se muestran en celdas y las filas se van agregando a medida que se
completa la cantidad de columnas definidas.

Los eventos que soporta el componente son: onclick, ondblclick, onkeydown,


onkeypress, onkeyup, onmousedown, onmousemove, onmouseout, onmouseover,
onmouseup.

Los atributos de formato/agrupamiento son:

Atributo Tipo Descripción


bgcolor String El color de fondo de la tabla Opcional
HTML generada
border int El tamaño (en pixels) del borde Opcional
de la tabla HTML generada
cellpadding int El atributo “cellpadding” de la Opcional
tabla HTML generada
cellspacing int El atributo “cellspacing” de la Opcional
tabla HTML generada
first int Primera fila a ser mostrada (inicia Opcional
en cero )
frame String Especifica en qué lado del frame Opcional
se mostrará la tabla:
• none
• above
• below
• hsides
• vsides
• lhs
• rhs
• box
• border
rendered boolean Indica si el componente se Opcional
mostrará durante la fase “Render

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 143

Response”. Por defecto es “true”.


rows int Determina cuantas filas se Opcional
mostrarán en la tabla HTML
generada
rules String Atributo “rules” pasado a la tabla Opcional
HTML generada. Indica si se
muestra la trama de celdas (como
en excel):
• none
• groups
• rows
• cols
• all
summary String Atributo “summary” que se envía Opcional
a la tabla HTML generada.
Genera una descripción pero no
es visible en la mayoría de
navegadores.
var String Es una variable EL que permite Opcional
iterar sobre los datos. Representa
el valor actual en una iteración
sobre el atributo “value”.
width String Es el atributo “width” pasado a la Opcional
table HTML generada (en pixels
es un número entero y en
porcentaje lleva el símbolo
respectivo).

Los atributos “core” que soporta son:

Atributo Tipo Descripción


binding Expresión que La referencia a una instancia de opcional
retorna un valor un componente UI
id String Identificador del componente opcional
title String El título del componente. Se pasa opcional
a la tabla HTML generada
value String El valor del componente opcional

Los atributos de estilo:

Atributo Tipo Descripción


columnclasses String Lista (separada por comas) de opcional
los estilos que se aplicarán a las
columnas.
Los estilos CSS se aplican
repetidamente a las columnas de
un componente panelGrid
footerclass String El estilo aplicado a la última fila opcional
de la tabla.
headerclass String El estilo aplicado a la primera fila opcional
de la tabla.
rowclasses String Lista (separada por comas) de opcional

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 144

los estilos que se aplicarán a las


filas.
Los estilos CSS se aplican
repetidamente a las filas de un
componente panelGrid
style String Estilo(s) “en línea” que se opcional
aplicará al componente
panelGrid.
styleclass String Estilo(s) CSS que se aplicará al opcional
componente panelGrid.

La sintaxis básica es:

Donde el tipo de dato de “value” puede ser: Array, List, ResultSet, Result (JSTL),
DataModel (JSF).

Ejemplo 1:

Asumiendo que el Managed Bean denominado “company1” tienen un atributo


“programmers” que devuelve un arreglo de Programadores. Se puede obtener la
siguiente pantalla:

Ejemplo 2: Ahora usando encabezados y definiendo “facets” (tag <f: facet>)

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 145

Genera la siguiente pantalla:

Ejemplo 3: Usando estilos


Note que el encabezado de la tabla tiene un estilo. Así también, las filas pares e
impares se manejan con estilos diferentes (obviamente la Hoja de estilos debe estar
definida como recurso en la aplicación).

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 146

Se mostrará una pantalla similar a la siguiente:

Tag <h: panelGrid />


Este tag genera una tbla HTML que sirve como contenedor para otros componentes.
Los componentes hijos son visualizados como celdas.

Los eventos que soporta: onclick, ondblclick, onkeydown, onkeypress, onkeyup,


Onmousedown, onmousemove, onmouseout, onmouseover y onmouseup.

Algunos de los atributos:

Atributo Tipo Descripción


bgcolor String El color de fondo de la tabla Opcional
HTML generada
border int El tamaño (en pixels) del borde Opcional
de la tabla HTML generada
cellpadding int El atributo “cellpadding” de la Opcional
tabla HTML generada

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 147

cellspacing int El atributo “cellspacing” de la Opcional


tabla HTML generada
columns int Número de columnas a ser Opcional
generadas en la tabla HTML
frame String Especifica en qué lado del frame Opcional
se mostrará la tabla:
• none
• above
• below
• hsides
• vsides
• lhs
• rhs
• box
• border
rendered boolean Indica si el componente se Opcional
mostrará durante la fase “Render
Response”. Por defecto es “true”.
rules String Atributo “rules” pasado a la tabla Opcional
HTML generada. Indica si se
muestra la trama de celdas (como
en excel):
• none
• groups
• rows
• cols
• all
summary String Atributo “summary” que se envía Opcional
a la tabla HTML generada.
Genera una descripción, pero no
es visible en la mayoría de
navegadores.
width String Es el atributo “width” pasado a la Opcional
table HTML generada (en pixels
es un número entero y en
porcentaje lleva el símbolo
respectivo).

Los atributos “core” que soporta son:

Atributo Tipo Descripción


binding Expresión que La referencia a una instancia de opcional
retorna un valor un componente UI.
id String Identificador del componente. opcional
title String El título del componente. Se pasa opcional
a la tabla HTML generada.

Los atributos de estilo:

Atributo Tipo Descripción

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 148

columnclasses String Lista (separada por comas) de opcional


los estilos que se aplicarán a las
columnas.
Los estilos CSS se aplican
repetidamente a las columnas de
un componente panelGrid.
footerclass String El estilo aplicado a la última fila opcional
de la tabla.
headerclass String El estilo aplicado a la primera fila opcional
de la tabla.
rowclasses String Lista (separada por comas) de opcional
los estilos que se aplicarán a las
filas.
Los estilos CSS se aplican
repetidamente a las filas de un
componente panelGrid
style String Estilo(s) “en línea” que se opcional
aplicará al componente
panelGrid.
styleclass String Estilo(s) CSS que se aplicará al opcional
componente panelGrid.

DATAMODEL

Un DataModel es una abstracción arbitraria alrededor de alguna tecnología que puede


ser usada para adaptar una variedad de fuentes de datos para ser empleados por
componentes JSF de tal forma que soporten el procesamiento fila por fila por parte de
los componentes hijos.

La colección de datos se modelo como una colección de filas de objetos, las cuales
pueden ser accedidas por un cursor (que inicia en cero) conocido como “row index”. La
API proporciona una serie de mecanismos para posicionar los cursos y recuperar los
objetos.

2.4.5. Mantenimiento de tablas

Se presenta un ejemplo sencillo de mantenimiento usando tablas.

Crear una clase “Item.java” que tenga la siguiente estructura (no olvidar los
getter/setter)

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 149

Crear una clase “Bean.java” (que es el managed bean de la aplicación) que tenga la
siguiente estructura. Observe que se utiliza la clase DataModel:

Ahora, codificar los métodos:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 150

Y el método que controla la edición:

No olvidar los getter/Setter de “ítem”, “model” y “list”.

Ahora codificar el FaceLet.

La primera parte de la página es:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 151

Hasta aquí, se debe mostrar los datos y los botones de edición y borrado.

Ahora, codificar la parte de edición:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 152

El resultado final es una pantalla similar a la siguiente, que permite la edición,


eliminación y adición de elementos en una tabla.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 153

Resumen
1. JSF 2 soporta Ajax de dos formas: la primera es mediante el uso de la API de
JavaScript: jsf,ajax.request(); la segunda forma es mediante el tag <f:ajax>

2. La API de JavaScript proporciona un “puente” para el manejo de las peticiones


ajax y permite un cierto nivel de control.

3. El tag <f: ajax> permite que el programador se olvide del JavaScript.

4. Para integrar JSF con JPA, sólo debe configurarse los archivos requeridos por
JPA. El resto de temas se manejan con la unidad de persistencia y el
EntityManager.

5. JSF proporciona una manera fácil de visualizar datos sin tener que realizar
iteraciones en la página, mediante el uso del tag <h:dataTable>

6. Las tablas se pueden refrescar con Ajax o se puede convertir en tablas editables.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o AJAX: http://java.dzone.com/articles/ajax-jsf-joined

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 154

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 155

UNIDAD

3
SPRING FRAMEWORK
LOGRO DE LA UNIDAD DE APRENDIZAJE
Al término de la unidad el alumno implementa una aplicación web utilizando
Spring, donde podrá integrar Spring, JSF y JPA en su aplicación.

TEMARIO
3.1 Tema 9 : Spring Core
3.1.1 : Introducción
3.1.2 : Arquitectura

3.2 Tema 10 : Spring Web


3.2.1 : Introducción
3.2.2 : Configuración

3.3 Tema 11 : Spring Módulos


3.3.1 : Spring security

ACTIVIDADES PROPUESTAS

• Implementar proyectos con la estructura Spring Framework.


• Implementar proyectos Integrando Spring, JSF y JPA.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 156

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 157

3.1. SPRING CORE

3.1.1. Introducción

En la actualidad, el desarrollo de aplicaciones empresariales, aunque es más sencillo


ya que hay muchas herramientas, APIs, y Frameworks; los cuales aunque son
opcionales, el aprender a usarlos nos ayudará a desarrollar nuestras aplicaciones en
menos tiempo y a que estas sean más robustas y contengan menos errores.

También se vuelve más complicado porque nuestras aplicaciones deben ser capaces
de conectarse con otras aplicaciones y servicios. Además, como desarrolladores,
somos los responsables de coordinar cada una de las partes de nuestra aplicación
para que todo funcione correctamente.

Por si no fuera suficiente, debemos tomar en cuenta que debemos darle


mantenimiento a nuestras aplicaciones, y que en algunos casos será necesario que
cambiemos módulos o capas enteras de la misma para mejorarla; como por ejemplo
sustituir nuestras consultas JDBC con Hibernate en los casos en los que sea prudente.

Afortunadamente existen frameworks que nos ayudan haciéndose cargo de todas o


casi todas las “complicaciones” mencionadas anteriormente. Spring es el más popular
de estos super-frameworks Java. Nos proporciona varios módulos los cuales abarcan
la mayor parte de las cosas que debemos hacer en cualquiera de las capas de
nuestras aplicaciones, desde plantillas para trabajar con JDBC o invocación de Web
Services y JMS, pasando por sus propias soluciones, ORM o MVC (web), hasta
integración con otros frameworks, como Struts 2, Hibernate, JSF, etc. Todo esto de
una forma elegante y haciendo uso de muchos buenos principios de programación.
Además Spring maneja la infraestructura de la aplicación, por lo que nosotros solo
deberemos preocuparnos de la lógica de la misma (y de la configuración de Spring).

Spring es, como lo definen sus autores, un framework ligero para construir
aplicaciones empresariales. Aunque Spring se encuentra dividido en distintos módulos,
cada uno de los cuales se encarga de partes diferentes de nuestra aplicación, no deja
de ser un monstruo, ya que es tan grande que alguien podría nunca usar todos estos
módulos en aplicaciones pequeñas o medianas; pero en aplicaciones grandes o
realmente grandes puede ahorrarnos mucho trabajo ya que puede coordinar todas las
partes de la aplicación. Esta separación en módulos nos permite usar solo las partes
que necesitamos, sin tener la carga de los que no usemos.

Spring está diseñado para no ser intrusivo, esto significa que no es necesario que
nuestra aplicación extienda o implemente alguna clase o interface de Spring (si no lo
queremos), por lo que nuestro código de lógica quedará libre y completamente
reutilizable para un proyecto sin Spring, o por si debemos quitarlo de una aplicación
que ya lo esté usando. Gracias a esto es posible usar un POJO o un objeto Java para
hacer cosas que antes solo podían hacerse con EJBs. Sin embargo, la utilidad de
Spring no es solo para el desarrollo de aplicaciones web, o no solo en el servidor.
Cualquier aplicación Java puede beneficiarse del uso de Spring.

El núcleo de Spring está basado en un principio o patrón de diseño llamado Inversión


de Control (IoC por sus siglas en inglés). Las aplicaciones que usan el principio de IoC
se basan en su configuración (que en este caso puede ser en archivos XML o con
anotaciones como en Hibernate) para describir las dependencias entre sus
componentes, esto es, los otros objetos con los que interactúa. En este caso

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 158

“inversión” significa que la aplicación no controla su estructura; permite que sea el


framework de IoC (en este caso Spring) quien lo haga.

Por ejemplo, supongamos que tenemos una clase “AlmacenUsuario”, que depende de
una instancia de una clase “UsuariosDAO” para realizar su tarea. “AlmacenUsuario”
crea una instancia de “UsuariosDAO” usando el operador “new” u obtiene una de
algún tipo de Fábrica. Usando la técnica de IoC, una instancia de “UsuariosDAO”, o
una subclase de esta, es proporcionada a “AlmacenUsuario” en tiempo de ejecución
por el motor de Spring. En este caso “UsuariosDAO” también podría ser una interface
y Spring se encargará de proporcionarnos una instancia de una clase que implemente
esa interface. Esta inyección de dependencia en tiempo de ejecución ha hecho que a
este tipo de IoC se le dé el nombre más descriptivo de inyección de dependencia (DI
por sus siglas en inglés). El concepto importante es que los componentes no saben
cuál implementación concreta de otros componentes están usando; solo ven sus
interfaces.

El uso de interfaces y DI son mutuamente benéficos, ya que hace más flexible y


robusta nuestra aplicación y es mucho más fácil realizar pruebas unitarias. Pero la
complejidad de escribir código que maneje las dependencias entre los componentes
de una aplicación diseñada para usar interfaces puede llegar a ser mucho y esto,
además, hace que los desarrolladores tengamos que escribir aún más código.

Afortunadamente, usando DI reducimos la cantidad de código extra que debemos


escribir, para un diseño basado en interfaces, casi a cero.

En el contexto de DI, Spring actúa como un contenedor que proporciona las instancias
de las clases de nuestra aplicación todas las dependencias que necesita, pero en una
forma no intrusiva y automática. Todo lo que debemos hacer es crear un archivo de
configuración que describa las dependencias; Spring se hará cargo del resto.

Como dije antes: Spring es un contenedor ya que no solo crea los componentes de
nuestra aplicación, sino porque contiene y maneja al ciclo de vida y configuración de
estos componentes. En Spring, podemos declarar cómo debe ser creado cada uno de
los objetos de nuestra aplicación, cómo deben ser configurados, y cómo deben
asociarse con los demás.

La implementación de DI de Spring se enfoca en el acoplamiento débil: los


componentes de nuestra aplicación deben asumir lo menos posible acerca de otros
componentes. La forma más fácil de lograr este bajo acoplamiento en Java es
mediante el uso de Interfaces. Como cada componente de la aplicación solo está
consciente de la interface de otros componentes, podemos cambiar la implementación
del componente sin afectar a los componentes que usan el nuevo componente.
Hablaré un poco más de esto cuando veamos los ejemplos.

El uso de DI tiene como beneficios, además de lo que ya he mencionado arriba, los


siguientes:

Reduce el código pegamento: Esto quiere decir que reduce dramáticamente la


cantidad de código que debemos escribir para unir los distintos componentes. Aunque
algunas veces este código puede ser tan simple como usar el operador “new” para
instanciar un nuevo objeto, otras pueden ser más complejas, como realizar una
búsqueda de dicha dependencia en un repositorio a través de JNDI, como en el caso
de los recursos remotos. En esto caso, el uso de DI puede reducir de forma dramática
la cantidad de código pegamento (o glue code) proporcionando búsquedas
automáticas.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 159

Externaliza dependencias: Como es posible colocar la configuración de dependencias


en archivos XML podemos realizar una reconfiguración fácilmente, sin necesidad de
recompilar nuestro código. Gracias a esto es posible realizar el cambio de la
implementación de una dependencia a otra (como en el ejemplo de Hibernate que
mencioné antes)

Las dependencias se manejan en un solo lugar: Toda la información de dependencias


es responsabilidad de un solo componente, el contenedor de IoC de Spring, haciendo
que este manejo de dependencias más simple y menos propenso a errores.

Hace que las pruebas sean más fáciles: Nuevamente, como nuestras clases serán
diseñadas para que sea fácil el reemplazo de dependencias, podemos proporcionar
mocks o dummies, que regresen datos de prueba, de servicios o cualquier
dependencia que necesite el componente que estamos probando.

Como podemos ver, el uso de DI nos proporciona muchos beneficios, pero no sin sus
correspondientes desventajas. En particular, es difícil ver qué implementación
particular de una dependencia está siendo usada para qué objeto, especialmente para
alguien que no está familiarizado con esta forma de trabajo.

Spring está dividido en alrededor de 20 módulos y colocados en los siguientes grupos:

Contenedor Central (Core Container)


• Acceso a Datos / Integración
WEB
• AOP (Programación Orientada a Aspectos)
• Instrumentación
Pruebas

Estos grupos se muestran en la siguiente imagen:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 160

• Inyección de dependencias mediante constructor

En el siguiente ejemplo, podemos ver como el objeto declara sus dependencias en el


constructor. Podemos observar que no hay código que se encargue de buscar esa
dependencia o crearla, simplemente la declara. Esto nos ayuda a tener clases Java
mucho más limpias a la vez que ayuda a facilitar el Testing, ya que, en un entorno de
Tests, podríamos intercambiar ese objeto por un Mock sin cambiar el código (mediante
la configuración de Spring).

Para informar a Spring de cuál es la dependencia que tiene que inyectar en


GeneradorPlaylist, podemos hacerlo mediante XML o anotaciones. En el siguiente
ejemplo, vamos a ver como se configuraría mediante XML:

• Inyección de dependencias mediante "Setter"

Spring, también, permite inyectar la dependencia mediante los Setter (métodos set*()).
Cada forma de inyectar las dependencias tiene sus ventajas y sus desventajas,
aunque la mayoría de los desarrolladores prefiere inyectar las dependencias mediante
los métodos Set.

Para indicarle a Spring qué queremos que inyecte la dependencia, podemos hacerlo
mediante anotaciones o XML. Vamos a ver cómo sería mediante anotaciones.

Mediante la anotación @autowired, le indicamos a Spring que se tiene que encargar


de buscar un Bean que cumpla los requisitos para ser inyectado. En este caso, el
único requisito es que sea del tipo BuscadorCanciones. En caso de que hubiese más

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 161

de un Bean que cumpliese esos requisitos, tendríamos que decirle a Spring cuál es el
Bean correcto.

3.1.2. Arquitectura

Spring podría potencialmente ser única para todas sus aplicaciones empresariales, sin
embargo, Spring es modular, lo que le permite seleccionar y elegir los módulos que se
aplican a usted, sin tener que poner el resto. Después de la sección da detalles acerca
de todos los módulos disponibles en Spring Framework.

El Spring Framework proporciona cerca de 20 módulos que se pueden utilizar en base


a los requisitos establecidos.

Contenedor Core:

El Core Container consiste en el Core, Beans, Contexto y módulos de lenguaje de


expresión cuyo detalle es el siguiente:

El módulo Core proporciona las partes fundamentales de la estructura, incluyendo las


características de inyección COI y de dependencia.

El módulo bean proporciona BeanFactory que es una sofisticada implementación del


patrón de fábrica.

El módulo de contexto se basa en la sólida base proporcionada por los módulos del
núcleo y Frijoles y es un medio para acceder a los objetos definidos y configurados. La
interfaz ApplicationContext es el punto central del módulo de contexto.

El módulo de lenguaje de expresión proporciona un poderoso lenguaje de expresión


para consultar y manipular un gráfico de objetos en tiempo de ejecución.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 162

Acceso a datos / integración:

La capa de acceso a datos / integración consiste en la JDBC, ORM, OXM, JMS y


módulos de transacción cuyo detalle es el siguiente:

El módulo de JDBC proporciona una capa de abstracción JDBC-que elimina la


necesidad de hacer JDBC tedioso codificación relacionada.

El módulo ORM provee capas de integración para APIs de mapeo objeto-relacional


populares, incluyendo JPA, JDO, Hibernate, y iBatis.

El módulo de OXM ofrece una capa de abstracción que soporta implementaciones de


mapeo objeto / XML para JAXB, Castor, XMLBeans, JiBX y xstream.

El módulo de servicio de mensajería Java JMS contiene características para producir


y consumir mensajes.

El módulo de Transaction apoya la gestión de transacciones programáticas y


declarativas de clases que implementan interfaces especiales y para todos tus POJOs.

Web:

La capa Web consiste en la Web, módulos Web-portlet cuyo detalle es el siguiente


Web-Servlet, Web-Struts, y:

El módulo Web proporciona funciones de integración básicas de web como la


funcionalidad de carga de archivos de varias partes y la inicialización del contenedor
IoC usando oyentes servlet y un contexto de aplicación orientado a la web.

El módulo Web-Servlet contiene el modelo-vista-controlador (MVC) la ejecución de la


primavera para las aplicaciones web.

El módulo Struts contiene las clases de apoyo para la integración de una capa web
Struts clásicos dentro de una aplicación de Spring.

El módulo Portlets proporciona la implementación MVC para ser utilizado en un


entorno de módulo de función y refleja la funcionalidad del módulo de Web-Servlet.

Varios:

Hay algunos otros módulos importantes como AOP, Aspectos, Instrumentación,


módulos Web y de color cuyo detalle es el siguiente:

El módulo de AOP ofrece implementación de programación orientada a aspectos que


le permite definir el método-interceptores y puntos de corte para desvincular
limpiamente código que implementa la funcionalidad que debe ser separada.

El módulo Aspectos proporciona integración con AspectJ que es otra vez un marco de
programación potente y madura aspecto orientado (AOP).

El módulo de Instrumentación proporciona clases y las implementaciones de


cargador de clases que se utilizan en ciertos servidores de aplicaciones.

El módulo de Test apoya la prueba de los componentes de Spring con frameworks


JUnit o TestNG.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 163

Resumen
1. El módulo ORM provee capas de integración para APIs de mapeo objeto-
relacional populares, incluyendo JPA, JDO, Hibernate, y iBatis.

2. El módulo de AOP ofrece implementación de programación orientada a aspectos


que le permite definir el método-interceptores y puntos de corte para desvincular
limpiamente código que implementa la funcionalidad que debe ser separada.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o Spring-Arquitectura: http://www.tutorialspoint.com/spring/spring_architecture

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 164

3.2. SPRING WEB

3.2.1. Introducción

El framework (MVC) modelo-vista-controlador Spring Web está diseñado en torno a un


DispatcherServlet que envía solicitudes a los handlers, con signaciones de controlador
configurable, vista la resolución, localidad, zona horaria y la resolución de tema, así
como soporte para cargar archivos. El controlador predeterminado se basa en
@Controller y @RequestMapping, ofreciendo una amplia gama de métodos de
manipulación flexibles. Con la introducción de Spring 3.0, el @Controller también le
permite crear sitios Web REST full Web y aplicaciones, a través de las anotaciones
@PathVariable y otras características.

Spring’s view es extremadamente flexible. Un controlador es normalmente responsable


de la preparación de un mapa modelo con los datos y la selección de un nombre de la
vista, pero también puede escribir directamente en la secuencia de respuesta y
completar la solicitud. Resolución de nombre de vista es altamente configurable a través
de la extensión de archivo o Aceptar tipo de contenido de encabezado de negociación, a
través de nombres de los beans, un archivo de propiedades, o incluso una aplicación
ViewResolver personalizado. El modelo (M en la MVC) es un Map de interfce, que
permite la abstracción completa de la tecnología de vista. Usted puede integrar
directamente con las tecnologías de representación de la plantilla basada como JSP,
Velocity y Freemarker, o directamente generar XML, JSON, Atom, y muchos otros tipos
de contenido. El modelo Map simplemente se transforma en un formato apropiado, tal
como atributos de la petición JSP, un modelo de Velocity Template.

3.2.2. Configuración

Debido a la explosión de las aplicaciones móviles cada día nos encontramos con una
mayor necesidad de utilizar frameworks web que generen paginas HTML sencillas de tal
forma que luego puedan decorarse con otras tecnologías tipo Bootstrap ,JQuery mobile
o similares. A este tipo de categoría pertenece el framework Spring MVC que cada día
es más utilizado en las empresas. La siguiente comparativa es interesante para ver que
cuota de mercado tiene cada framework.

Como podemos ver, aunque JSF es el standard Spring MVC, hoy por hoy, es el
framework web más utilizado. Recordemos que un modelo de FrontController funciona
de la siguiente manera:

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 165

pom.xml
</pre>
<dependencies>
<dependency>
<groupId>org.apache.geronimo.specs</groupId>
<artifactId>geronimo-servlet_3.0_spec</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
</dependencies>
<pre>

Realizado este paso, se configura el framework Spring dentro de nuestra aplicación


web. Para ello, deberemos añadir el siguiente bloque de código en nuestro web.xml.

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee

http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"

version="3.0">

<display-name>Spring MVC</display-name>
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/application-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

El fichero web.xml da de alta un nuevo servlet denominado DispatcherServlet que es el


que realiza las tareas de controlador frontal de la aplicación y captura todas las
peticiones ya que su url-pattern es “/”. Este controlador se apoya en el fichero clásico de
Spring Framework que se encargará de gestionar los distintos flujos de la aplicación a
traves del uso de beans.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 166

El código del fichero application-context.xml:

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">

<bean name="/Lista"
class="com.arquitecturajava.ListaController"/>
<bean name="/Formulario"
class="com.arquitecturajava.FormularioController"/>
</beans>

En nuestro caso, vamos a optar por un primer ejemplo muy básico que usa dos beans
que gestionan las distintas urls a las que accedemos utilizando el patrón MVC2.

En estas dos clases, veremos lo siguiente:

Código ListaController:
package com.arquitecturajava;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 167

public class ListaController implements Controller {

public ModelAndView handleRequest (HttpServletRequest request,


HttpServletResponse response) throws Exception {

return new ModelAndView("/WEB-INF/jsp/Lista.jsp");


}
}

Código Formulario Controller :


package com.arquitecturajava;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

public class FormularioController implements Controller {

public ModelAndView handleRequest (HttpServletRequest request,


HttpServletResponse response) throws Exception {

return new ModelAndView("/WEB-INF/jsp/Formulario.jsp");


}
}

Como podemos ver, nuestras clases implementan el interface Controller y tienen un


método muy similar al método ejecutar (handleRequest) que nos redirige a una URL en
concreto.

Una vez que tenemos claro cómo funcionan los controladores que hemos definido es
momento de ver el contenido de los ficheros JSP a los que hacen referencia. Lista.jsp

</pre>
<html>
<head>

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 168

<meta http-equiv="Content-Type" content="text/html; charset=UTF-


8">
<title>Lista de Personas</title>
</head>
<body>
<ul>
<li>Pedro</li>
<li>Maria</li>
</ul>
<a href="Formulario">Ir a formulario</a>
</body>
</html>
<pre>

Formulario.jsp

</pre>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-
8">
<title>Lista de Personas</title>
</head>
<body>
<form action="Lista">
Nombre<input type="text" name="nombre" /></br>
Apellidos<input type="text" name="apellidos" /></br>
<input type="submit" value="Aceptar"/>

</form>
</body>
</html>
<pre>

Si solicitamos la url /Lista Spring MVC, nos devolverá el contenido el fichero Lista.jsp.

Spring MVC Anotaciones

Se muestra en este ejemplo anotaciones de Spring. Lo primero que vamos a hacer es


añadir un ViewResolver a nuestro fichero application-context.xml.

<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolv
er">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 169

Se trata de un bean sencillo que parametriza la URL de las distintas vistas que
cargamos. A partir de este momento, nuestros controladores podrán devolver algo
como lo siguiente:

return new ModelAndView ("Lista");

Spring MVC y @Controller

A partir de Spring 2.5, se permite el uso de un sistema de anotaciones que simplifica la


forma de trabajar. Para usar este sistema, deberemos, en primer lugar, añadir una
nueva dependencia a nuestro pom.xml.

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>

Esta dependencia nos permitirá modificar el fichero application-context.xml y añadir


una etiqueta

<context:component-scan base-package="com.arquitecturajava"/>

Esta etiqueta se encarga de decirle a Spring en qué packages debe buscar clases
anotadas para su registro. En nuestro caso, en “com.arquitecturajava”, una vez
realizada esta operación, creamos una clase PersonaController dentro del package.

package com.arquitecturajava;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PersonaController {
@RequestMapping("/Lista")
public String Lista() {
return "Lista";
}
@RequestMapping("/Formulario")
public String Formulario() {
return "Formulario";
}
}

Disponemos de un controlador que agrupa un conjunto de acciones.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 170

@Controller: Anotación que registra el controlador para Spring MVC

@RequestMapping: Anotación que se encarga de relacionar un método con una


petición http.

El uso de anotaciones no implica que únicamente tengamos un único controlador sino


que nos permite agrupar un conjunto de urls que estén asociadas a nivel de negocio
en un controlador específico. La aplicación soportará n controladores.

Spring MVC y el Modelo

Por ahora, lo único que hemos hecho es construir el controlador. Luego, el controlador
suele enviar datos a la vista a través de un modelo. Vamos a modificar
PersonaController para que tenga una lista de Personas y nos las envíe a Lista.jsp. El
primer paso será añadir la clase Persona.

package com.arquitecturajava;
public class Persona {
private String nombre;
private String apellidos;
public Persona(String nombre, String apellidos) {

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 171

super();
this.nombre = nombre;
this.apellidos = apellidos;
}
//omitimos equals y hashcode eclipse

public String getNombre() {


return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getApellidos() {
return apellidos;
}
public void setApellidos(String apellidos) {
this.apellidos = apellidos;
}
}

Realizada esta operación, el siguiente paso será modificar el controlador para que
genere una lista de Personas.

package com.arquitecturajava;

import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class PersonaController {

@RequestMapping("/Lista")
public String Lista(Model modelo) {
List<Persona> milista= new ArrayList<Persona>();
Persona persona1= new Persona ("pedro","perez");
Persona persona2=new Persona ("maría","gonzalez");
milista.add(persona1);
milista.add(persona2);

modelo.addAttribute("listaPersonas",milista);
return "Lista";
}
@RequestMapping("/Formulario")
public String Formulario() {
return "Formulario";
}
}

Como podemos observar, ahora, el método lista soporta un objeto de tipo Model. Es
en este objeto en el cual nosotros añadimos la lista. Realizado este paso, nos quedará
modificar la página JSP para que nos muestre una lista utilizando JSTL. Para ello,
antes deberemos añadir la dependencia a Maven.

<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 172

</dependency>

Finalmente, mostramos la página JSP que se encarga de mostrar la lista de personas.

<%@ page language="java" contentType="text/html; charset=UTF-8"


pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Lista de Personas</title>
</head>
<body>
<ul>
<c:forEach items="${listaPersonas}" var="persona">
<li>${persona.nombre}, ${persona.apellidos}</li>
</c:forEach>
</ul>
<a href="Formulario">Ir a formulario</a>
</body>
</html>

Para finalizar, cargamos la página en un navegador y nos mostrará la lista.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 173

Resumen
1. @Controller: Anotación que registra el controlador para Spring MVC

2. @RequestMapping: Anotación que se encarga de relacionar un método con una


petición http.

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o Spring web: http://docs.spring.io/spring/docs/current/spring-framework-


reference/html/mvc.htmlXX:

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 174

3.3. SPRING MÓDULOS

3.3.1. Spring security

La aplicación construida se debe configurar para que quede protegida por Spring
Security. Para ello, el primer paso que debemos realizar es dar de alta en el fichero
web.xml la ruta en donde tenemos ubicado el fichero de configuración de Spring.

Una vez que tenemos configurado el fichero web.xml, el filtro de SpringSecurity se


encargará de bloquear el acceso a toda la aplicación.

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 175

Vamos a ver el código fuente del web.xml para clarificar dudas:

web.xml

<?xml version="1.0" encoding="UTF-8"?>


<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>web01</display-name>
<!-- ruta fichero -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/springSecurity.xml
</param-value>
</context-param>
<!-- listener carga Spring-->
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<!-- filtro de Spring security-->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

SpringSecurity.xml

<?xml version="1.0" encoding="UTF-8"?>


<bean:beans xmlns:bean="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/security"

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 176

xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-
3.2.xsd">
<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_Usuario" />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="manuel" password="1234" authorities="ROLE_Usuario" />
</user-service>
</authentication-provider>
</authentication-manager>
</bean:beans>

El fichero define varios conceptos fundamentales:

El grupo de recursos protegidos (URLs)

<http auto-config="true">
<intercept-url pattern="/**" access="ROLE_Usuario" />
</http>

En este caso, está toda la aplicación protegida /** y solo se permite el acceso al role
“ROLE_Usuario”.

AutenticationManager o gestor de autentificación que decide cuando un usuario


es válido. Este gestor está íntimamente relacionado con el concepto de
AutenticationProvider o proveedor de autentificación.

<authentication-manager>
<authentication-provider>
<user-service>
<user name="manuel" password="1234" authorities="ROLE_Usuario" />
</user-service>
</authentication-provider>

Este último el AutenticationProvider define la forma en la que un usuario se ha


de validar. Puede ser contra una base de datos, puede ser contra un Ldap, puede ser
contra un fichero o puede personalizarse. En nuestro caso, estamos utilizando un
servicio en memoria que solo permite el acceso al siguiente usuario.

<user name="manuel" password="1234" authorities="ROLE_Usuario" />

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 177

El siguiente diagrama clarifica la relación entre los elementos.

Realizada esta operación, ejecutamos “maven package” y nos empaquetará la


aplicación de tal forma que si la desplegamos en un servidor (Tomcat por ejemplo) e
intentamos acceder a la página de bienvenidos, Spring Security nos bloqueará el
acceso y mostrará la siguiente pantalla.

Introducimos de usuario manuel y de clave 1234, y el framework nos dará acceso a la


página protegida.

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA


DESARROLLO DE APLICACIONES WEB II 178

CARRERA DE COMPUTACIÓN E INFORMÁTICA CIBERTEC


DESARROLLO DE APLICACIONES WEB II 179

Resumen

1. Puede agregar, en el web.xml, el parámetro del archivo de configuración del


Security.

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/springSecurity.xml
</param-value>
</context-param>

2. También, puede agregar el siguiente Filtro.

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>
org.springframework.web.filter.DelegatingFilterProxy
</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:

o Adictos al trabajo:
http://www.adictosaltrabajo.com/tutoriales/tutoriales.php?pagina=introSpring
Security

o Download Spring Security: http://projects.spring.io/spring-security/

CIBERTEC CARRERA DE COMPUTACI ÓN E INFORMÁTICA