Zona HTML Zona Java Zona PHP Zona ASP Zona Bases de datos
Inicio > Tutoriales > Lenguajes orientados a objeto > Java > J2EE > Integración de JSF, Spring e Hibernate para crear una Aplicación Web del Mundo Real
-Tutoriales

Integración de JSF, Spring e Hibernate para crear una Aplicación Web del Mundo Real


Implementación

Ahora veamos cómo conectar todo junto e implementar JCatalog. Puede descargar todo el código fuente de la aplicación desde aquí.

. Diseño de la Base de Datos

Creamos un esquema llamado Catalog para la aplicación de ejemplo, que consta de cuatro tablas, como se ve en la siguiente figura:

. Diseño de Clases

En la siguiente figura puede ver el diagrama de clases de la aplicación:

Durante el diseño se ha utilizado la programación contra interfaces. En la capa de presentación, se han utilizado cuatro beans de respaldo: ProductBean, ProductListBean, UserBean, y MessageBean. La capa de lógica-de-negocio contiene dos servicios de negocio (CatalogService y UserService) y tres objetos de negocio (Product, Category, y User). La capa de integración contiene dos interfaces DAO y sus implementaciones Hibernate. El contexto de aplicación Spring conecta y maneja la mayoría de los beans dentro de las capas de lógica-de-negocio y de integración. ServiceLocator integra JSF con la capa de lógica-de-negocio.

. Conectarlo Todo

Debido a la limitación de espacio de este artículo, sólo examinaremos un caso de uso. El caso de utilización CreateProduct demuestra como conectar todo y construir la aplicación. Antes de sumergirnos en los detalles, usaremos un diagrama de secuencia (en la siguiente figura) para demostrar la integración de principio-a-fin de todas las capas.

Ahora veremos los detalles de cómo implementar CreateProduct.

. Capa de Presentación

La implementación de la capa de presentación implica crear las páginas JSP, definir la navegación por las páginas, crear y configurar los beans de respaldo, e integrar JSF con la capa de lógica de negocio:

  • Página JSP:
    createProduct.jsp es la página para crear un nuevo producto. Contiene componentes UI y conecta los componentes al ProductBean. La etiqueta personalizada ValidateItemsRange valida el número de categorías que el usuario ha seleccionado. Por cada producto nuevo se debe seleccionar al menos una categoria.
  • Navegación de páginas:
    La navegación por la aplicación se define en el fichero de configuación de la aplicación, faces-navigation.xml. Aquí están las reglas de navegación definidas para CreateProduct:
    <navigation-rule>
       <from-view-id>*</from-view-id>
       <navigation-case>
          <from-outcome>createProduct</from-outcome>
          <to-view-id>/createProduct.jsp</to-view-id>
       </navigation-case>
    </navigation-rule>
    
    <navigation-rule>
       <from-view-id>/createProduct.jsp</from-view-id>
       <navigation-case>
          <from-outcome>success</from-outcome>
          <to-view-id>/uploadImage.jsp</to-view-id>
       </navigation-case>
       <navigation-case>
          <from-outcome>retry</from-outcome>
          <to-view-id>/createProduct.jsp</to-view-id>
       </navigation-case>
       <navigation-case>
          <from-outcome>cancel</from-outcome>
          <to-view-id>/productList.jsp</to-view-id>
       </navigation-case>
    </navigation-rule>
    
  • Bean de respaldo:
    El ProductBean no sólo contiene los mapeos de propiades a los datos de los componentes UI de la página, también tiene tres acciones: createAction, editAction, y deleteAction. Aquí está el código para el método createAction():
    public String createAction() {
       try {
          Product product = ProductBeanBuilder.createProduct(this);
    
          //Save the product.	
          this.serviceLocator.getCatalogService().saveProduct(product);
    
          //Store the current product id inside the session bean.
          //For the use of image uploader.
          FacesUtils.getSessionBean().setCurrentProductId(this.id);
    
          //Remove the productList inside the cache.
          this.logger.debug("remove ProductListBean from cache");
          FacesUtils.resetManagedBean(BeanNames.PRODUCT_LIST_BEAN);
       } catch (DuplicateProductIdException de) {
          String msg = "Product id already exists";
          this.logger.info(msg);
          FacesUtils.addErrorMessage(msg);
          return NavigationResults.RETRY;
       } catch (Exception e) {
          String msg = "Could not save product";
          this.logger.error(msg, e);
          FacesUtils.addErrorMessage(msg + ": Internal Error");
          return NavigationResults.FAILURE;
       }
       
       String msg = "Product with id of " + this.id + " was created successfully.";
       this.logger.debug(msg);
       FacesUtils.addInfoMessage(msg);
       return NavigationResults.SUCCESS;
    }
    

    Dentro de la acción, se construye un objeto de negocio Product basado en las propiedades de ProductBean. ServiceLocator busca el CatalogService. Finalmente, createProduct pide su delegado al CatalogService, que está en la capa de lógica-de-negocio.

  • Declaración del Bean Manejado:
    El ProductBean se debe configurar en el fichero de configuración de recursos JSF, faces-managed-bean.xml:
    <managed-bean>
       <description>
          Backing bean that contains product information.
       </description>
    
       <managed-bean-name>productBean</managed-bean-name>
       <managed-bean-class>catalog.view.bean.ProductBean</managed-bean-class>
       <managed-bean-scope>request</managed-bean-scope>    
    
       <managed-property>
          <property-name>id</property-name>
          <value>#{param.productId}</value>
       </managed-property> 
       <managed-property>
          <property-name>serviceLocator</property-name>
          <value>#{serviceLocatorBean}</value>
       </managed-property> 
       
    </managed-bean>
    

    Se configura el ProductBean para tener un ámbito de petición, lo que significa que la implementación JSF crea un nuevo ejemplar de ProductBean por cada petición si se ha referenciado dentro de la página JSP. La propiedad ID-managed se rellena con el parámetro productId de la petición. La implementación JSF obtiene el parámetro desde la petición y selecciona la propiedad manejada.

  • Integración entre las capas de presentación y de lógica-de-negocio:
    ServiceLocator abstrae la lógica para localizar los servicios. En la aplicación de ejemplo, ServiceLocator está definido como un interfae. El interface está implementado como un bean manejado JSF, ServiceLocatorBean, que busca los servicios desde el contexto de aplicación Spring:
    ServletContext context = FacesUtils.getServletContext();
    this.appContext = WebApplicationContextUtils.getRequiredWebApplicationContext(context);
    this.catalogService = (CatalogService)this.lookupService(CATALOG_SERVICE_BEAN_NAME);
    this.userService = (UserService)this.lookupService(USER_SERVICE_BEAN_NAME);
    

    El ServiceLocator está definido como una propiedad dentro de BaseBean. La facilidad de bean manejado de JSF conecta la implementación del ServiceLocator con aquellos beans manejados que deben acceder a él. Se utiliza la Inversión de Control.

. Capa de Lógica-de_Negocio

La tarea de esta capa consiste en definir los objetos de negocio, creando los interfaces de servico con sus implementaciones, y conectándo los objetos con Spring.

  • Objetos de Negocio:
    Como Hibernate proporciona la persistencia, los objetos de negocio Product y Category deben proporcionar métodos get y set para todos sus campos.
  • Servicios de Negocio:
    El interface CatalogService define todos los servicios relacionados con el control del catálogo:
    public interface CatalogService {
    
       public Product saveProduct(Product product) throws CatalogException;
    
       public void updateProduct(Product product) throws CatalogException;
    
       public void deleteProduct(Product product) throws CatalogException;
    
       public Product getProduct(String productId) throws CatalogException;
    
       public Category getCategory(String categoryId) throws CatalogException;
    
       public List getAllProducts() throws CatalogException;
    
       public List getAllCategories() throws CatalogException;
    }
    

    CachedCatalogServiceImpl es la implementación del interface de servicio, que contiene un método set para un objeto CatalogDao. Spring conecta el CachedCatalogServiceImpl con el objeto CatalogDao. Como estámos condificando para interfaces, no acoplamos fuertemente las implementaciones.

  • Configuración de Spring:
    Aquí está la configuración de Spring para CatalogService:
    <!-- Hibernate Transaction Manager Definition -->
    
    <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager">
       <property name="sessionFactory"><ref local="sessionFactory"/></property>
    </bean>
    
    <!-- Cached Catalog Service Definition -->
    <bean id="catalogServiceTarget" class="catalog.model.service.impl.CachedCatalogServiceImpl" init-method="init">
       <property name="catalogDao"><ref local="catalogDao"/></property>
    </bean>
    
    <!-- Transactional proxy for the Catalog Service -->
    <bean id="catalogService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
       <property name="transactionManager"><ref local="transactionManager"/></property>
       <property name="target"><ref local="catalogServiceTarget"/></property>
       <property name="transactionAttributes">
          <props>
             <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
           <prop key="save*">PROPAGATION_REQUIRED</prop>
           <prop key="update*">PROPAGATION_REQUIRED</prop>
           <prop key="delete*">PROPAGATION_REQUIRED</prop>
          </props>
       </property>
    </bean>
    

    Se configura el control de transación declarativo para el CatalogService. CatalogService puede conectarse a una implementación diferente de CatalogDao. Spring crea y maneja un único objeto CatalogService y no se necesita una factoría.

    Ahora que la capa de lógica de negocio está lista, conectémosla con la capa de integración

  • Integración entre Spring e Hibernate:
    Aquí está la configuración de HibernateSessionFactory:
    <!-- Hibernate SessionFactory Definition -->
    
    <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
       <property name="mappingResources">
          <list>
             <value>catalog/model/businessobject/Product.hbm.xml</value>
             <value>catalog/model/businessobject/Category.hbm.xml</value>
             <value>catalog/model/businessobject/User.hbm.xml</value>
          </list>
       </property>
    
       <property name="hibernateProperties">
          <props>
             <prop key="hibernate.dialect">net.sf.hibernate.dialect.MySQLDialect</prop>
           <prop key="hibernate.show_sql">true</prop>
           <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
           <prop key="hibernate.cache.provider_class">net.sf.hibernate.cache.HashtableCacheProvider</prop>
          </props>
       </property>
    
       <property name="dataSource">
          <ref bean="dataSource"/>
       </property>
    </bean>
    

    CatalogDao utiliza HibernateTemplate para integrarse entre Hibernate y Spring. Aquí está la configuración para HibernateTemplate:

    <!-- Hibernate Template Defintion -->
    <bean id="hibernateTemplate" class="org.springframework.orm.hibernate.HibernateTemplate">
       <property name="sessionFactory"><ref bean="sessionFactory"/></property>
       <property name="jdbcExceptionTranslator"><ref bean="jdbcExceptionTranslator"/></property>
    </bean>
    

. Capa de Integración

Hibernate mapea objetos a la base de datos relacional utilizando un fichero de configuración XML. En JCatalog, Product.hbm.xml expresa el mapeo para el objeto de negocio Product. Se utiliza Category.hbm.xml para el objeto de negocio Category. Los ficheros de configuración están en el mismo directorio que los objetos de negocio correspondientes. Aquí está el Product.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
      "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
      "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">

<hibernate-mapping package="catalog.model.businessobject">
   <class name="Product" table="product">
      <id name="id" column="ID" unsaved-value="null">
         <generator class="assigned"/>
      </id>
      <property name="name" column="NAME" unique="true" not-null="true"/>
      <property name="price" column="PRICE"/>     
      <property name="width" column="WIDTH"/>      
      <property name="height" column="height"/>     
      <property name="description" column="description"/>	
      <set name="categoryIds" table="product_category" cascade="all">
         <key column="PRODUCT_ID"/>
         <element column="CATEGORY_ID" type="string"/>
      </set>
   </class>
</hibernate-mapping>

CatalogDao se conecta con HibernateTemplate mediante Spring:

<!-- Catalog DAO Definition: Hibernate implementation -->
<bean id="catalogDao" class="catalog.model.dao.hibernate.CatalogDaoHibernateImpl">
   <property name="hibernateTemplate"><ref bean="hibernateTemplate"/></property>
</bean>
 
Patrocinados
 

Copyright © 1999-2006 Programación en castellano. Todos los derechos reservados.
Formulario de Contacto - Datos legales - Publicidad

Hospedaje web y servidores dedicados linux por Ferca Network