Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Aplicaciones
Web II
DESARROLLO DE APLICACIONES WEB II
2
Í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
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
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
Presentación
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.
Red de contenidos
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
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
ACTIVIDADES PROPUESTAS
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
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”:
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
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.
• Usando Anotaciones
• Usando XML
El uso de XML es una opción alternativa a las anotaciones, aunque su lectura puede
resultar compleja para proyectos grandes.
No se debe olvidar que al ser un JavaBean, sigue las reglas de este (con los
getter/setter).
1.1.3. EntityManager
Cuando el Entity manager obtiene una referencia a una Entidad, se dice que dicha
entidad está en estado “managed”
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.
2
FUENTE: “JPA 2: Mastering the Java Persistence API”, pág 23.
Se instancia el objeto
Java
Para ubicar a una Entidad empleando el método “find”, generalmente se requiere solo
una línea de código:
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.
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.
Se inicia finaliza la
transacción
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).
Las anotaciones que proporciona JPA para manejar los “Callbacks” son:
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.
3. Recordar la ubicación del archivo persistence.xml que debe ir siempre dentro del
folder META-INF.
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
1.2.1. Anotaciones
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:
Para definir una entidad basta con emplear la anotación @Entity y la anotación @Id.
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.
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):
Anotación @Basic
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.
Ejemplo 1:
Ejemplo 2:
Anotación @Lob
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:
• Character[]
• String
• Byte[]
• tipos serializables
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.
• java.sql.Time
• java.sql.Timestamp
• java.util.Calendar
Ejemplo:
Anotación
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).
• TABLE
• SEQUENCE
• IDENTITY
ESTRATEGIA “GenerationType.AUTO”
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.
Ejemplo:
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
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.
Ejemplo:
Estrategia
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
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:
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.
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.
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:
Anotación
@Embeddable
Anotación
@Embedded
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.
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
o Anotaciones: http://www.objectdb.com/api/java/jpa/annotations/orm
Roles
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
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
Cada rol dentro de la relación tendrá su propia cardinalidad, la cual indicará cuando
exista una sola o muchas instancias.
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.
Mapeo de Relaciones
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.
En UML se requiere que la clase “source” tenga un atributo del tipo de la clase”target”
para poder navegar hacia ella.
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”.
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”.
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”.
Cuando una entidad se asocia con una “colección” de otras entidades estamos ante
una relación de “uno a muchos”.
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.
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”.
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.
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
JPA soporta dos formas para expresar consultas que recuperan entidades desde una
base de datos:
• La API de criterios, que sirve para construir consultas basadas en objetos Java
en lugar de escribir los queries en strings.
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).
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.
Observe que la notación es muy similar al SQL normal, pero con ligeras diferencias:
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).
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:
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.
INNER JOIN
Ejemplo 1: se asume que “phones” contiene una relación JPA entre “Employee” y
“Phone”
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:
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:
QUERIES AGREGADOS
La sintaxis es muy similar a SQL: se requiere el uso del agrupamiento con GROUP BY
Ejemplo:
QUERIES
Ahora bien, se puede indicar el resultado esperado o se puede omitir y de esta forma
tendremos un query sin tipo definido (“unTyped query”).
Para aquellas aplicaciones que utilizan muchos queries, se debe considerar el costo
de “compilar” la sentencia JPQL:
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).
La sentencia JP-QL
TypedQuery
La sentencia JP-QL
Query
Este tipo de query sirve para organizar y mejorar el desempeño de una aplicación.
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.
Ejemplo: El mismo query del ejemplo anterior, pero ahora definido en la clase
Order.java
Query JPQL
Se invoca así:
Se especifica que es “NamedQuery”
Query JPQL #1
Anotación
Query JPQL #2
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.
La sentencia JP-QL
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.
La sentencia JP-QL
Observe el uso de
parámetros ordinales
Término Descripción
Resumen
1. Diferenciar las clases Query y TypedQuery.
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
o JPQL: http://www.objectdb.com/java/jpa/query/parameter
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
ACTIVIDADES PROPUESTAS
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.
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:
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:
• /faces/*
• *.jsf
• *.faces
Estas reglas se
conocen como JSF
Navigation Model
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:
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.
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).
Luego, se procesan los eventos y se reportan los errores que pudieran ocurrir.
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.
• Aquellos que pueden aceptar valores: campos de texto, cajas de chequeo, etc.
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.
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.
En esta fase, los datos se promueven hacia un objeto Java conocido como “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:
6
Gráfico tomado de: “Java Server Faces 2.0: The Complete Reference”, pág 43.
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:
2.1.4. Facelets
• jsp:incluye
• <%@include %>
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 primer parámetro define que la extensión “.xhtml” es el sufijo por defecto de todas
las páginas que manejan contenido JSF.
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
• 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:
9
Muy similar a Apache Tiles
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).
Ejemplo de Template:
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.
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”:
Y la página de respuesta:
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
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).
Por ejemplo:
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.
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”:
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:
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.
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.
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/
2.2.1. Introducción
Un componente se define como una pieza de software con reglas de uso bien
definidas que permitan que pueda ser utilizado por otros componentes.
Se debe indicar que los componentes, además de las interfaces mencionadas, pueden
implementar otras interfaces para definir un comportamiento particular.
10
Fuente: Libro “Java Server Faces 2.0: The Complete Reference”, pág 140.
Se listan las principales funcionalidades de cada tag. Para el detalle de los atributos
soportados, por favor consultar la documentación de JSF.
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.
Este tag maneja una serie de patrones para formateo de los valores.
Ejemplo:
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: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>
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Ejemplo:
Sirve para anidar contenido en HTML, XML o cualquier otro lenguaje de marcas.
Ejemplo:
Ejemplo:
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”.
Ejemplo:
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.
Cada opción del menú se muestra como un elemento <option>. Si la opción se marca
como deshabilitada, se agrega el atributo “disabled”.
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.
Resumen
1. La librería CORE: se asocia al namespace “f:” y proporciona utilidades para
validación, conversión, internacionalización, etc.
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
o JSF: http://javaserverfaces.java.net/users.html
2.3.1. Introducción
• 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.
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 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.
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.
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.
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.
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.
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:
• Usando el MethodBinding:
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”.
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
• javax.faces.validator.LongRangeValidator.NOT_IN_RANGE
• javax.faces.validator.LongRangeValidator.TYPE
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).
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 en cualquier momento del ciclo de vida de la aplicación:
• ExceptionQueuedEvent
• PostConstructCustomScopeEvent
• PreDestroyCustomScopeEvent
• PostConstructViewMapEvent
• PreDestroyViewMapEvent
• PostAddToViewEvent
• PreRemoveFromViewEvent
EVENTOS DE APLICACIÓN
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:
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.
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.
EVENTOS DE FASE
Los eventos de fase (o “Phase Events”) se procesan entre cada fase del
procesamiento de ciclo de vida de un request.
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:
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.
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.
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
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
o JSF: https://javaserverfaces.java.net/
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.
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.
soportados.
Ejemplo:
JAVASCRIPT ESTÁNDAR
Existen dos objetos principales dentro del javaScript: ajax y útil. El objeto “ajax” tiene
las funciones siguientes:
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.
Token Significado
@all Todos los componentes de la vista
En este caso, se define el evento “onkeypress”: cada vez que se pulse una tecla, dicho
valor aparecerá en el campo con id “outNombre”.
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.
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).
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.
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:
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.
Los datos se muestran en celdas y las filas se van agregando a medida que se
completa la cantidad de columnas definidas.
Donde el tipo de dato de “value” puede ser: Array, List, ResultSet, Result (JSTL),
DataModel (JSF).
Ejemplo 1:
DATAMODEL
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.
Crear una clase “Item.java” que tenga la siguiente estructura (no olvidar los
getter/setter)
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:
Hasta aquí, se debe mostrar los datos y los botones de edición y borrado.
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>
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
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
ACTIVIDADES PROPUESTAS
3.1.1. Introducción
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.
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.
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.
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.
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, 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.
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.
Contenedor Core:
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.
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.
Varios:
El módulo Aspectos proporciona integración con AspectJ que es otra vez un marco de
programación potente y madura aspecto orientado (AOP).
Resumen
1. El módulo ORM provee capas de integración para APIs de mapeo objeto-
relacional populares, incluyendo JPA, JDO, Hibernate, y iBatis.
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
o Spring-Arquitectura: http://www.tutorialspoint.com/spring/spring_architecture
3.2.1. Introducción
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:
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>
<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>
<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.
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
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>
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.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolv
er">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
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:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>3.2.4.RELEASE</version>
</dependency>
<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";
}
}
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) {
super();
this.nombre = nombre;
this.apellidos = apellidos;
}
//omitimos equals y hashcode eclipse
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>
</dependency>
Resumen
1. @Controller: Anotación que registra el controlador para Spring MVC
Pueden revisar los siguientes enlaces para ampliar los conceptos vistos en esta
unidad:
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.
web.xml
SpringSecurity.xml
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>
<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”.
<authentication-manager>
<authentication-provider>
<user-service>
<user name="manuel" password="1234" authorities="ROLE_Usuario" />
</user-service>
</authentication-provider>
Resumen
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/springSecurity.xml
</param-value>
</context-param>
<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