Posted on 12-09-2007
Filed Under (Java, Programación) by galifate

Aquí tenemos un artículo de ejemplo de uso, en una aplicación web, de las tecnologías JSF, Spring 2.0 y Java Persistence. A continuación, a modo de práctica de inglés técnico y para no desconectarme demasiado de las tecnologías web java, puesto que cada vez programo menos, os pongo una traducción y tal. El articulo está sacado del blog de Carol McDonald, dentro de Java.net.

A modo de mostrar el uso de JSF, Spring 2.0 y Java Persistence en Glassfish, la autora ha montado una aplicación de ejemplo que consiste en paginación de conjuntos de datos sobre un catálogo de una tienda.

Paginación de Conjuntos de Datos en una Aplicación de Ejemplo usando las APIs de JSF, Spring 2.0 y Java Persistence en Glassfish

Esta aplicación de ejemplo de un catálogo de una tienda demuestra el uso de JavaServer Faces, la nueva API de Java Persistence, y Spring 2.0 para implementar la paginación. La autora cogió el ejemplo Pagination of Data Sets in a Sample Application using JSF, Catalog Facade Stateless Session, and Java Persistence APIs y lo modificó ligeramente para usar Spring Bean en lugar de los beans de sesion sin estado de EJB 3.0. Si se comparan los dos ejemplos, verás que el código es casi el mismo, la principal diferencia es la configuración en xml extra para Spring, lo cual no es fácil.

Descarga el código de la aplicación de ejemplo SpringJPA

Nótese: la autora modificó la parte de integración de Spring JSF en esta aplicación para usar org.springframework.web.jsf.DelegatingVariableResolver en lugar del Managed Bean ServiceLocator para obtener una referencia al CatalogService Spring Bean desde el application context de Spring.

Explicación del uso de JSF, Spring 2.0, y Java Persistence API en un aplicación de ejemplo del catálogo de una tienda

La siguiente imagen muestra la página de la Lista del Catálogo, que permite a un usuario ojear la lista de productos de una tienda.

listpage.jpg

La página List.jsp usa un componente JSF dataTable para mostrar una lista de productos del catálogo.

El componente dataTable es útil cuando quieres mostrar un conjunto de resultados en una tabla. En una aplicación de JavaServer Faces, el componente UIData (la superclase de dataTable) soporta el binding a una colección de objetos de datos. Hace el trabajo de iteración sobre cada registro de la fuente de datos. El dataTable renderer de HTML muestra los datos como una tabla HTML.

En la página web List.jsp la dataTable está definida como se muestra a continuación: (Nota: el color Rojo son para los tags Java EE, anotaciones de código, Azul para Spring y Verde para el código de la autora o variables)

Código de Ejemplo: List.jsp

<h:dataTablevalue=’#{item.items}var=’dataTableItem‘ border=”1″
cellpadding=”2″ cellspacing=”0″>

El atributo value de un tag dataTable se refiere a los datos a ser incluídos en la tabla.

El atributo var especifica un nombre que lo usan los componentes que están dentro del tag dataTable com un alias de los datos referenciados por el atributo value. En el tag dataTable de List.jsp, el atributo value apunta a una lista de productos del catálogo. El atributo var apunta a un sólo elemento de esa lista. Como el componente UIData itera por la lista, cada referencia a dataTableItem apunta al elemento actual en la lista.

El value de dataTable está limitado a la propiedad items de la clase controlador de item, ItemController, que está definido en el fichero faces-config.xml:

Código de: faces-context.xml

<managed-bean>
<managed-bean-name>item</managed-bean-name>
<managed-bean-class>
sessionpagination.ItemController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>catalogService</property-name>
<value>#{catalogService}</value>
</managed-property>

</managed-bean>


La propiedad items se define como se muestra a a continuación:

Código de: ItemController.java
public DataModel getItems() {
if (model==null || index != firstItem){
model=getNextItems();
}
return this.model;
}public DataModel getNextItems() {
model = new ListDataModel(catalogService.getItems(firstItem,batchSize));
index = firstItem;
return this.model;
}

El método getItems() recubre una List de objetos item, devuelto desde el catalogService, en un DataModel.

UIData, la superclase de dataTable, soporta data binding a una collection de objetos de datos representado por una instancia de DataModel. La collection de datos subyacente a una instancia de DataModel se modelo como una colección de objetos fila que pueden ser accedidos por un índice de fila. La API da mecanismos para posicionarse en un índice de fila especificado, y para devolver una objeto que represente los datos que corresponden a la fila actual.

Las propiedades de Item Name, Photo, y price se muestran con el componente column:

Ejemplo de código de: List.jsp

<h:column>
<f:facet name=”header“>
<h:outputText value=”Price”/>
</f:facet>
<h:outputText value=”#{dataTableItem.price}”/>
</h:column>

Los tags column representan columnas de datos en un componente UIData. Mientras este componente itera por las filas de datos, procesa el componente UIColumn asociado con cada tag column por cada fila de la tabla.

El componente UIData itera por la lista de elementos (item.items) y muestra el dataTableItem.price. Cada vez que UIData itera por la lista de items, pinta una celda en cada column.

Los tags dataTable y column usan facet para representar partes de la tabla que no son repetidas o modificadas. Estas partes incluyen las cabeceras, los pie y los títulos.

El modo recomendado para integrar Spring con JSF es configurar el DelegatingVariableResolver de Spring en el faces-context.xml. Los elementos <application> <variable-resolver> de un fichero faces-config.xml permiten a una aplicación basada en Faces registrar clases personalizadas para sustituir la implementación estándar de VariableResolver. El DelegatingVariableResolver de Spring primero delega al resolver original de la implementación subyacente de JSF, para luego delegar al WbApplicationContext raíz de Spring.Esto permite configurar los Spring Beans como propiedades gestionadas por los Managed Beans de JSF. Por ejemplo, el catalogService Spring Bean está configurado como una managed property del ItemController JSF ManagedBean:

Ejemplo de código de: faces-context.xml
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
<managed-bean>
<managed-bean-name>item</managed-bean-name>
<managed-bean-class>
sessionpagination.ItemController
</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>catalogService</property-name>
<value>#{catalogService}</value>
</managed-property>

</managed-bean>

El catalogService, y su implementación CatalogDAO, se define como un Spring bean en el fichero de configuración /WEB-INF/applicationContext.xml :

Ejemplo de código de: applicationContext.xml

<bean id=”catalogServiceclass=”service.CatalogDAO“/>

<bean name=”itemControllerclass=”sessionpagination.ItemController“>
<property name=”catalogService“>
<ref bean=”catalogService“/>
</property>
</bean>

</beans>

<property name=”catalogService“> se refiere al método setCatalogService de ItemController. El WebApplicationContext de Spring“inyecta” el Spring Bean catalogService dentro de la property catalogService del ItemController JSF ManagedBean :

Ejemplo de código de: ItemController.java

public class ItemController {
private CatalogService catalogService ;public void setCatalogService(CatalogService catalogService) {
this.catalogService = catalogService;
}

Para más información sobre el uso de JSF con Spring, ver Spring - Java/J2EE Application Framework Integrating with JavaServer Faces .

Usando la Java Persitence API (JPA) con Spring 2.0

El Spring bean CatalogDAO usa el objeto EntityManager Query de la Java Persistence API para devolver una lista de items. El CatalogDAO anota el campo private EntityManager em; con @PersistenceContext , que hace que un entity manager sea inyectado. (nótese que usar la anotación @PersistenceContext es el mismo método para inyectar un Entity Manager para un EJB 3.0 Session Bean.)

Ejemplo de código de: CatalogDAO.java

@Repository
@Transactional
public class CatalogDAO implements CatalogService {
@PersistenceContext(unitName=”PetCatalogPu”)
private EntityManager em;public List<Item> getItems(int firstItem,int batchSize) {
Query q = em.createQuery(”select object(o) from Item as o”);
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
List<Item> items= q.getResultList();
return items;
}

La Java Persistence Query APIs se usa para crear y ejecutar consultas que puedan devolver una lista de resultados. La interfaz JPA Query suministra soporte para paginación vía los métodos setFirstResult() y setMaxResults(): q.setMaxResults(int maxResult) establece el número máximo de resultados a devolver. q.setFirstResult(int startPosition) establece la posición del primer resultado a devolver.

En el siguiente código, se muestra la clase de entidad de Item que se “mapea” con la tabla ITEM que guarda las instancias de item. Éste es un objeto de entidad típico de la Java Persistence. Hay dos requisitos para una entidad:

  1. anotar la clase con la anotación @Entity.
  2. anotar el identificador de la clave primaria con @Id

Puesto que los campos name, description… son mapeos básicos de los campos del objeto a las columnas del mismo nombre en la tabla de la base de datos, no necesitan ser anotados. Las relaciones O/R con Address y Product también son anotadas. Para más información sobre definir entidades JPA ver Pro EJB 3: Java Persistence API book.

Ejemplo de código de: Item.java

@Entity
public class Item implements java.io.Serializable {
@Id
private String itemID;

private String name;
private String description;
private String imageurl;
private String imagethumburl;
private BigDecimal price;
@OneToOne(cascade={CascadeType.PERSIST})
private Address address;
@ManyToOne
private Product product;


public Item() { }
public String getItemID() {
return itemID;
}

public void setItemID(String itemID) {
this.itemID = itemID;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getDescription() {
return description;
}

public void setDescription(String description) {
this.description = description;
}

public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public void setAddress(Address address) {
this.address = address;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}

}

El ManagedBean ItemController pagina por la lista de items manteniendo los atributos firstItem y batchSize y pasándolos como parámetros al método CatalogService getItems(firstItem, batchSize). El <managed-bean-scope> de ItemController está definido como session, un ManagedBean de JSF con un alcance de session significa que que las propiedades del bean estarán disponibles durante toda la vida de la sesión HTTP.

La propiedad ItemController ItemCount se usa para obtener y mostrar el número de items del Catálogo de la base de datos en la página List.jsp:

Ejemplo de código de: List.jsp

<h:outputText value=”Item #{item.firstItem + 1}..#{item.lastItem} of
#{item.itemCount}”/>

Esta propiedad ItemController ItemCount se define como se muestra a continuación:

Ejemplo de código de: ItemController.java

public int getItemCount() {
int count = catalogService.getItemsCount();
return count;
}

El método ItemController getItemCount() llama a la interficie CatalogService para obtener el número de elementos de la lista. El métod getItemCount() del bean de Spring CatalogDAO usa la Query interface de JPA para obtener el numero de elementos de la tabla items de la base de datos:

Ejemplo de código de: CatalogDAO.java
public class CatalogDAO implements CatalogService {
. . .
public int getItemCount() {
Query q = entityManager.createQuery(”select count(o) from Item as o”);
int count = ((Long)q.getSingleResult()).intValue();
return count;
}

Un commandLink de JSF se usa para dar un enlace en el que clicar para mostrar la siguiente página de items. El tag commandLink representa un hyperlink HTML y se renderiza como un elementos HTML <a>. El tag commandLink se usa para enviar un action event a la aplicación.

Ejemplo de código de: List.jsp

<h:commandLink action=”#{item.next}” value=”Next #{item.batchSize}”
rendered=”#{item.lastItem + item.batchSize <= item.itemCount}”/>

El atributo action de commandLink referencia al método next() del bean que hay detrás de ItemController, el cual calcula la primera fila de la siguiente página y devuelve un String que hace que List.jsp muestre la siguiente página de la lista. El método ItemController next se define como se muestrab a continuación:

Ejemplo de código de: ItemController.java
public String next() {
if (firstItem + batchSize < getItemCount()) {
firstItem += batchSize;
}
return “item_list“;
}

El NavigationHandler de JSF empareja el resultado lógico item_list con las reglas de navegación en el fichero de configuración de la aplicación faces-config.xml para determinar a qué página acceder a continuación. En este caso, la implementación JSF carga la página List.jsp después del resultado de este método.

Ejemplo de código de: faces-config.xml
<navigation-rule>
<navigation-case>
<from-outcome>
item_list</from-outcome>
<to-view-id>/item/List.jsp</to-view-id>
</navigation-case>
</navigation-rule>

Se usa el commandLink de JSF para obtener un enlace para navegar a la página naterior. El atributo action se refiere al método ItemController prev() que calcula la primera fila de la página anterior y devuelve una salida lógica, que causa mostrar la página anterior de la lista de items:

Ejemplo de código de: List.jsp

<h:commandLink action=”#{item.prev}” value=”Previous #{item.batchSize}”
rendered=”#{item.firstItem >=item.batchSize}”/>

Este método ItemController prev() se define como se muestra a continuación:

Ejemplo de código de: ItemController.java
public String prev() {
firstItem -= batchSize;
if (firstItem < 0) {
firstItem = 0;
}
return “
item_list";
}

Se usa un ommandLink de JSF para obtener un enlace que clickar para mostrar una página con los detalles del item. El atributo action de commanLink referencia al método ItemController detailSetup():

Ejemplo de código de: List.jsp

<h:column>
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<h:commandLink action=”#{item.detailSetup}” value=”#{dataTableItem.name}”/>
</h:column>

El método ItemController detailSetup() obtiene los datos de item de la fila actual del dataModel, y devuelve un string que hace que la página Detail.jsp muestre los detalles del item:

Ejemplo de código de: ItemController.java

public String detailSetup() {
item = (Item) model.getRowData();
return “item_detail“;
}

El NavigationHandler de JSF busca una coincidencia con el resultado obtenido, item_detail, para encontrar una regla de navegación en el fichero de configuración de la aplicación, y así determinar a qué página nos dirigiremos a continuación. en este caso, la implementación de JavaServer Faces carga la página Detail.jsp cuando finaliza este método.

Ejemplo de código de: faces-config.xml

<navigation-rule>
<navigation-case>
<from-outcome>item_detail</from-outcome>
<to-view-id>/item/Detail.jsp</to-view-id>
</navigation-case>
</navigation-rule>

La Detail.jsp usa el componente outputText para mostrar por pantalla las propiedades de item:

Ejemplo de código de: detail.jsp

<h:outputText value=”#{item.item.name}” title=”Name” />
<h:outputText value=”#{item.item.description}” title=”Description”/>
<h:graphicImage url=”#{item.item.imageurl}” title=”Imageurl” />
<h:outputText value=”#{item.item.price}” title=”Price” />
<h:outputText value=”#{item.item.address.city}” title=”Address” />
<h:outputText value=”#{item.item.contactinfo.email}” title=”Address”/>

detailpage.jpg

Conclusión

Esto concluye la aplicación de ejemplo que demuestra como trabajar con dataTable y DataModel de JSF para paginar una lista de entidades Item obtenidas usando los métodos de Catalog que a su vez usa Java Persistence APIs con Spring 2.0.

Configurar las tablas de la base de datos para la aplicación de ejemplo:

  • editar las propiedades del fichero SpringJPA\setup\javadb.properties file, ejecutar el script ant del directorio SpringJPA\setup, o simplemente ejecutar el sql del directorio SpringJPA\setup\sql\javadb con cualquier herramienta para ello.

Configuración de la Aplication para Spring 2.0, JSF, JPA, ejecutandose en Glassfish

Para configurar glassfish y el proyecto Netbeans para Spring, la autora ha modificado los pasos descritos en Spring and Hibernate in GlassFish: Setting Things Up:

  • descargar y extraer Spring ( aquí se ha usado la versión 2.1).
  • Descargar e instalar NetBeans 5.5.1
  • Descargar e instalar GlassFish V1, siguiendo las instrucciones de la página de descarga. También puedes usar la distribución GlassFish de Sun, la Sun Java System Application Server PE 9.
  • Añadir el servidor Glassfish a Netbeans:
  • Iniciar NetBeans e ir a la ventana Runtime (Ctrl+5).
  • Click derecho al nodo de Servers y seleccionar Add Server.
  • seleccionar Sun Java System Application Server (distribución binaria de GlassFish de Sun).
  • Navegar al sitio donde hayas instalado GlassFish y seleccionar Finish.

Crear la librería de Spring en Netbeans:

  • Abrir la Netbeans Library Manager (menú Tools) y crea una nueva libreria que se llame Spring.
  • Añade los siguientes jars al Classpath:
  • dist/spring.jar, dist/weaving/spring-aspects.jar, lib/jakarta-commons/commons-logging.jar, lib/log4j/log4j-1.2.9.jar .
  • Establece el Sources con el directorio src de Spring.
  • Pon en Javadoc el directorio docs\api de Spring.
    Ahora esta librería está disponible para ser usada por cualquier proyecto.

Abrir y ejecutar el proyecto SpringJPA

Descargar la aplicación SpringJPA. Descomprime el código. Desde Netbeans haz “Open Project” y selecciona el proyecto de Netbeans SpringJPA del directorio que has descomprimido. La aplicación SpringJPA es un proyecto de Enterprise Application de Netbeans, que en realidad está compuesto por dos proyectos: SpringJPa y SpringJPA-war. SpringJPA-war es un módulo Java EE del proyecto SpringJPA. SpringJPA-war genera el fichero war y SpringJPA genera el fichero ear que contiene el war.

Abre el proyecto SpringJPA. Verás el siguiente diálogo cuando abras el proyecto, porque el proyecto de Aplicación de Empresa guarda la localización absoluta a sus módulos J2EE. Es necesario configurar la localización de SpringJPA-war.

reference_problems

  • Haz click en Close. El proyecto SpringJPA estrá en rojo negrita.
  • Click derecho en el proyecto y selecciona Resolve Reference Problems del menú contextual.
  • Usa el diálogo del Resolve Reference Problems para mapear el módulo war de SpringJPA a su proyecto, que encontrarás en un subdirectorio dentro del directorio SpringJPA.
  • Después de resolver las referencias, click derecho en el proyecto SpringJPA y selecciona Open Required Projects (ahora que las dependencias están correctas, el proyectto del war SpringJPA-war se abrirá siempre con el proyecto SpringJPA).
  • Aun hay problemas de referencias con el módulo web, puesto que éste referencia los ficheros jar de Spring necesarios para construir el proyecto.
  • Añadir una nueva libreria de Spring al SpringJPA-war…
    en la ventana de proyecto bajo SpringJPA-war:
    click derecho en Librairies, Add Library
    Selecciona la Spring Library (que ya creamos antes) de la lista, y clicka en Add Library. Así añadirás los jars de Spring a tu proyecto SpringJPA-war.
  • Todas las referencia deberían estar ya resueltas. Haz click derecho sobre el proyecto SpringJPA y selecciona “clean and build project”.
  • Presiona F6 para testear el proyecto. Netbeans construirá, empaquetará, desplegará y lanzará la aplicación.

Creando tu propio proyecto Netbeans con Spring y Glassfish:

  • Si quieres crear tu propia aplicación, crea una nueva Netbeans Enterprise Application:
  • En Netbeans selecciona File New Project, entonces selecciona Enterprise ..Enterprise Application, en la ventana New Enterprise Application, en Server elige Sun Java System Applicaton server, Java EE 5 Version, y selecciona Create Web Application Module:

newentapp.jpg

  • cambia las propiedades del proyecto de Netbeans para añadir la nueva libreria Spring …
    en la ventana del proyecto bajo el war de tu aplicación:
    click derecho sobre Libraries, Add Library
    Selecciona Spring Library de la lista, haz click en Add Library .
  • Para generar las clases de entidad de las tablas de la base de datos: en la ventana del proyecto, click derecho sobre el war, seleccionar new File..Persistence Entity clases de la base de datos. Clicka en next, selecciona la fuente de datos, las tablas y crea tu unidad de persistencia. Para más info sobre como hacer esto, prueba con Java EE 5, EJB 3.0, Java Persistence API (JPA)
  • Para la configuración de Spring añade el applicationConfiguration.xml y modifica el web.xml y el faces-config.xml como se describe a continuación.

Configuración de los ficheros XML para Spring 2.0, JSF, y JPA, ejecutandose en Glassfish

  • Añade el fichero /WEB-INF/applicationContext.xml al directorio WEB-INF del war. Este fichero está donde defines tus beans de servicios Spring, y los resources. Más abajo está el applicationContext.xml para la aplicación de ejemplo. Para más información sobre cómo configurar el applicationContext.cml de Spring para JPA ver este artículo: Using the Java Persistence API (JPA) with Spring 2.0

Ejemplo de código de: applicationContext.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”
xmlns:aop=”http://www.springframework.org/schema/aop”
xmlns:tx=”http://www.springframework.org/schema/tx”
xsi:schemaLocation=”
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”>

<bean id=”catalogService” class=”service.CatalogDAO“/>
<bean id=”entityManagerFactory” class=”org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean”>
<property name=”dataSource” ref=”dataSource”/>
<property name=”loadTimeWeaver”>

Discutir en el foro (0)

    Read More   

Comments

[…] el Blog del Galifate podemo ver un tutorial sobre la introducción al uso de los frameworks java Spring 2.0, JSF y JPA. […]


marcelo on 2 Mayo, 2008 at 10:19 am #

Esta bueno el articulo y la traduccion no esta tan mal :)


William on 26 Agosto, 2008 at 5:11 pm #

Tutorial Excelente para mi. Me aclaró muchas dudas. Gracias


Post a Comment
Name:
Email:
Website:
Comments: