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>