Aplicación de Patrones J2EE en un Caso de Estudio

Al maestro Sr. Patricio Molina, mi profesor de computación de la infancia, que en paz descanse. Su trabajo de hace más de 10 años aproximadamente ha tenido sus primeros frutos. Espero que desde el más allá pueda apreciar el resultado de meses de paciencia con un niño de 10 a 12 años aproximadamente que solo deseaba jugar.

Ningún patrón de diseño puede entregar la experiencia que otorga un verdadero maestro como lo fue el señor Patricio Molina.

Resumen

El siguiente documento tiene por objetivo definir y aplicar los patrones de diseño Session Façade, Data Access Object y Value Objet a un ejemplo particular.

Para lograr este objetivo, se define que son los patrones J2EE, para posteriormente concentrarnos en la definición de los patrones de estudio. A continuación, se define un caso de estudio en el cual se aplican técnicas de análisis y diseño orientado a objetos, ilustrando la aplicación de los patrones directamente en la fase de diseño. Finalmente, se desarrolla una aplicación web de baja escala, la que implementará una solución a la problemática del caso de estudio en JSP / Struts / JDBC.

Los resultados del estudio permiten a los desarrolladores J2EE que no tienen conocimientos sobre el tema de patrones, comprender su aplicación y aprender su utilización por medio del ejemplo.

1.- Introducción

Sun Microsystem provee en su sitio web [SUN03-1] [SUN03-2] un conjunto de patrones que pueden ser usados en el contexto del diseño de aplicaciones Java 2 Enterprise Edition, J2EE. Los patrones de diseño J2EE consisten en soluciones recurrentes y documentadas de problemas comunes de diseño de aplicaciones J2EE. Muchas de estas soluciones se basan en los patrones de Gamma et al. [GAM95], así que se podrán encontrar soluciones J2EE que son aplicadas al diseño de aplicaciones de software en general.

Un patrón J2EE consiste en un documento basado en una plantilla que define las siguientes secciones:

  • Contexto: Juego de entornos bajo los cuales el patrón existe
  • Problema: Describe el problema de diseño enfrentado por el desarrollador.
  • Motivación: Lista de las razones y motivaciones que afectan al problema y a la solución. Esta lista resalta la razón del porqué se debe elegir utilizar el patrón en discusión en un problema de diseño y de la justificación de su utilización.
  • Solución: Describe el acercamiento a la solución brevemente y los elementos de la solución en detalle. Esta sección contiene 2 subsecciones: Estructura: Diagrama de clases que definen los objetos y relaciones entre estos.
  • Estrategias: Describen diferentes formas de cómo un patrón puede ser implementado.
  • Consecuencias: Los trade-off (ventajas y desventajas) cuando se aplica el patrón.

A continuación, se definen los patrones J2EE Value Object, Session Façade y DAO..

1.1.- Value Object

Contexto

Las aplicaciones cliente necesitan comunicar, transportar e intercambiar datos de negocios con los Enterprise Java Beans, objetos JDBC y otros objetos.

Problema

  • Cada llamada a get y set de un objeto remoto implica una invocación remota, lo que afecta directamente en la escalabilidad de una aplicación.
  • El paso de los atributos de un objeto de dominio (por ejemplo, Consumidores) a un método puede conducir a métodos con muchos argumentos, y cada modificación de un atributo del objeto de dominio afectará la signatura de todos los métodos que usen este objeto, teniendo con ello problemas de acoplamiento y mantenibilidad.

Motivación

  • Las aplicaciones J2EE generalmente hacen uso de EJB para la implementación de los componentes de negocio, lo que implica que cada llamada a una propiedad de un entity bean por medio de los métodos get/set signifi
  • caría una llamada remota.
  • El cliente requiere más de un atributo del componente remoto, lo que conduce a varias llamadas de red (ej, ingreso de un Consumidor).

Solución

Se debe usar una clase que implemente el interfaz Serializable (redefinir el metodo toString() ), en donde sus propiedades miembro pueden variar según el tipo de enfoque:

Si se necesita modelar una tabla relacional o similar, las propiedades de la clase serían las mismas que los campos de la tabla relacional. Este enfoque se denomina Domain Value Object [MAR02].

Si se necesita encapsular atributos de varias tablas en una petición (por ejemplo, un carrito de compra, con el id de un cliente, el id y cantidad de un producto), se crea una clase que combine todos los atributos que son requeridos. Este enfoque se denomina Custom Value Object [MAR02].

En una aplicación que no utilice un VO para una operación de negocios, se tendría la siguiente signatura en un método crear:

public void crearConsumidor(String rut, String nombre, String Apellido, Calendar edad….)

Es claro que la signatura es muy larga y difícil de escribir, y que su dificultad de escritura es proporcional a la cantidad de campos de una tabla.

Sin embargo:

public void crearConsumidor(ConsumidorVO vo)

Provee de una signatura mucho más sencilla que la anterior, puesto que se envía una referencia del objeto consumidor, el cual encapsula todos los datos requeridos.

La estructura del patrón es la siguiente:

Consecuencias

  • En el contexto de aplicaciones remota, se logra una mayor eficiencia, puesto que reduce el envío de mensajes por red.
  • En el contexto de JDBC, permite representar un conjunto de atributos procedentes de uno o varios objetos de dominio, representados por la signatura método (VO) en ves de método (arg1, arg2, arg3…).
  • Un Value Object puede contener información obsoleta si se pretende usar en una actualización posterior en otra transacción. Esto se puede corregir con el patrón Versión Number [MAR02].

Ejemplos

ConsultaVO.java o ProductoSoftwareVO.java

1.2. Session Façade

Contexto

Clases Java comunes o EJB encapsulan lógica y datos de negocios, exponiendo sus interfaces y la complejidad de los servicios distribuidos a la capa cliente.

Problema

En un método de aplicaciones donde se utiliza la arquitectura estratificada (o por capas), se pueden presentar los siguientes problemas:

  • Acoplamiento fuerte, provocado por la dependencia directa entre los clientes y los objetos de negocio.
  • Demasiadas llamadas a operaciones entre el cliente y el servidor, abocando a problemas de rendimiento de red (en el caso de EJB).
  • Falta de una estrategia de acceso uniforme de los clientes, exponiendo los objetos de negocio a una mala utilización.

Motivación

  • Proporcionar a los clientes un interfaz sencillo que oculte todas las interacciones complejas entre los componentes de negocio.
  • Ocultar al cliente las interacciones y las interdependencias entre los componentes de negocio, permitiendo de esta forma el aumento de flexibilidad y evitar que los cambios en los objetos de negocio repercutan en errores en la vista.
  • Evitar la exposición directa de los objetos de negocios a los clientes, para mantener el acoplamiento entre las dos capas al mínimo.
  • Centralizar los casos de uso en métodos centralizados sobre una clase.

Solución

Usar un session bean (para el caso de aplicaciones EJB) o una clase java común que encapsule la complejidad de las interacciones entre los objetos de negocio participantes en un flujo de trabajo (workflow). El session façade maneja los objetos de negocios y proporciona un servicio de acceso uniforme a los cliente. Es decir, el cliente (JSP, Swing, etc) no tratará con los EJB ni con la complejidad del acceso remoto, ni con JDBC, sino que trabajará con colecciones y Value's Object. .

La estructura del patrón es la siguiente

Consecuencias

  • Introduce una capa extra entre el Modelo y el Controlador: Agregando esta capa, se puede modelar los casos de uso de una forma centralizada, logrando también centralizar todo el acoplamiento a esta capa intermedia.
  • Expone un interfaz uniforme para el acceso al Modelo.
  • Cuando se utiliza con EJB, reduce el número de invocaciones remotas, aumentando la escalabilidad.
  • Simplifica la gestión de transacciones y el mantenimiento de los casos de uso.

Ejemplos

ProductoSoftwareFacade.java

1.3 Data Access Object

Contexto

El acceso a los datos varía según el soporte persistente y el proveedor.

Problema

  • La poca homogeneidad del almacenamiento persistente produce distintas implementaciones para lograr la accesibilidad (la iimplementación de operaciones sobre un archivo de texto plano es distinta a la realizada sobre un motor de base de datos, aunque se requiera de ambos las mismas operaciones)). Un cambio en el sistema de almacenamiento (cambio de proveedor de bd o de formato) puede conducir a una reimplentación de los componentes de datos y componentes vinculados (los que requieren estos datos).
  • Con el API de JDBC se puede acceder de una forma estándar a los servidores de bases de datos relacional. Sin embargo, la implementación del lenguaje SQL puede variar según el propietario, aunque se suponga que es un estándar (por ejemplo, las operaciones para recuperar el autonumérico de un registro ingresado no es igual en Oracle que en MySQL o SQLServer).
  • El acceso a datos de sistemas no relacionales incurre en la utilización de un API no propietario, por lo que se aumenta la dependencia entre el código de la aplicación y el código del acceso a datos.
  • Introducir el código de conectividad en todos los componentes que requieren de acceso hace difícil la mantención y la migración cuando se desea cambiar la fuente de datos.

Motivación

  • Los componentes de la aplicación necesitan recuperar y almacenar información desde almacenamientos persistentes y otras fuentes de datos variadas (includos archivos de texto, planillas de cálculo, etc). Además, puede variar los proveedores, por lo que se tiene el problema del SQL propietario.
  • Una API de datos que exponga al cliente un conjunto de operaciones comunes lograría reducir el acomplamiento y dependencias de la implementación. Por ejemplo, una tabla de clientes en un modelo relacional para el proveedor Oracle o MySQL tiene las mismas operaciones: agregar, eliminar, modificar, etc. Sin embargo, algunas operaciones pueden tener distintas implementaciones (porque el SQL para esa acción puede ser distinto según el proveedor), pero esto sería independiente para los clientes (por medio de una factory)
  • Los componentes necesitan ser transparentes al almacenamiento persistente real o la implementación de la fuente de datos para proporcionar una portabilidad y migración sencillas a diferentes productos, tipos de almacenamiento y tipos de fuentes de datos.

Solución

  • Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la fuente de datos, logrando así desacoplar la lógica de negocios de la lógica de acceso a datos. El DAO maneja la conexión con la fuente de datos para obtener y almacenar datos.
  • El desacoplamiento de la lógica de negocios con el acceso a datos permite crear implementaciones plugables del DAO, con solo seleccionar el tipo de fuente de datos durante la instalación/configuración de una aplicación.

Estructura

Consecuencias

  • Flexibilidad en la instalación/configuración de una aplicación.
  • Independencia del vendedor de la fuente de datos.
  • Independencia del recurso (base de datos relacional, base de datos orientado a objetos, ficheros planos, etc.).
  • Reduce la complejidad de la implementación de la lógica de negocios (Session Façades)
  • Más complejidad en el diseño, debido principalmente al conjunto de clases que colaboran en el DAO y en forma general, cada DAO es utilizado para modelar una tabla del modelo relacional.

Ejemplo

AbstractSQLConsultaDAO.java , SQLConsultaDAO.java, JDBC3CCSQLConsultaDAO.java, SQLConsultaDAOFactory.java

2. Caso de estudio

Para aplicar estos dos patrones J2EE, se presentará un caso de estudio de baja escala, en el cual se aplicará en forma directa los patrones de diseño vistos anteriormente.

El caso de estudio se enmarca en el grupo de desarrollo Inukisoft. Esta empresa basa su principal actividad en el desarrollo de software, por lo que requiere de una web que permita a los clientes ver la oferta de productos y enviar consultas / sugerencias. Los administradores de la web de Inukisoft deben poder revisar las consultas y actualizar el catálogo de productos, con una cuenta exclusiva para usuarios administradores. Se especifica que se requiere de una única cuenta de administración, por lo que no se deberá registrar una lista de usuarios.

Cada producto incluye su identificador, nombre, descripción. Los administradores podrán actualizar todos los datos de estos productos, y eliminarlos si lo consideran pertinente.

Las siguientes funciones se pueden resumir en el siguiente diagrama de casos de uso:

En base a este diagrama de casos de uso, se pueden identificar algunos objetos de dominio candidatos: Producto de software, Catálogo, Consulta, Cliente y Administrador. Definiendo un diagrama de clases para armar el modelo conceptual, quedaría:

Ya definido un bosquejo del análisis, toca ir al diseño de la aplicación. Para ello, se define el modelo de datos que se utilizará.

Atributo / Tipo Descripción del atributo
id / entero largo sin signo autonumérico Identifica a cada consulta con un número correlativo.
consulta / texto largo 255 El texto de la consulta efectuada por el cliente
fecha / tipo fecha timestamp La hora y fecha de la consulta

Tabla: ProductoSoftware
Atributo / Tipo Descripción del atributo
id / entero largo sin signo autonumérico id / entero largo sin signo autonumérico
nombre / texto largo 50 Describe las funcionalidades del producto
descripcion / texto largo 1000 La hora y fecha de la consulta
precio / flotante sin signo El precio del producto de software

Los otros elementos del modelo conceptual no están incluidos en el modelo relacional, puesto que no son entidades que almacenan cantidades de datos.

Ya con los objetos de dominio persistentes definidos, se puede entonces aplicar directamente el patrón Domain Value Object sobre las tablas Consulta y ProductoSoftware, por lo que se obtendría las clases ConsultaVO y ProductoSoftwareVO.

Ya generalizadas las tablas del modelo relacional en clases, se debe a continuación aplicar el patrón DAO a las tablas Consulta y Producto de Software. Bellas [BEL03] propone un esquema estructural para los DAO's, el cual se reutilizará este diseño para la tabla Consulta:

Tabla: Consulta
Clase / Interface Descripción
SQLConsultaDAO Interface que define todas las operaciones de acción y consulta de la tabla Consulta
AbstractSQLConsultaDAO Clase Abstracta que implementa SQLConsultaDAO. Los métodos implementados en la clase abstracta son los que son independiente de plataforma (en general son todos, a excepción del método create() ).
JDBC3CCConsultaDAO Subclase de AbstractSQLConsultaDAO, la cual es una clase concreta y final que implementa los métodos dependientes de la plataforma. En general, se implementa el método create(), puesto que el campo clave de la tabla es un autonumérico, por lo que la estrategia de recuperación, en este caso, es por DriverJDBC del tipo 3.
SQLConsultaDAOFactory Clase que implementa el patrón de diseño Factory Method [GAM95]. Esta clase define cual subclase de AbstractSQLConsultaDAO debe ser instanciada cuando se utiliza el DAOConsulta.

El diagrama de clases de este DAO queda representado de la siguiente manera:

Podríamos reutilizar este diseño de clases para la tabla “ProductoSoftware”, por lo que se tendría terminado el Modelo de Tablas del sistema.

El siguiente paso del diseño es definir donde van a ir implementados los casos de uso. Para ello, se puede aplicar directamente el patrón Session Façade, donde se definirán todas las operaciones de los casos de uso.

La façade es una clase concreta, definida de la siguiente forma:

package inukisoft.patronesj2ee.facade;
public class ProductoSoftwareFacade {
	public ProductoSoftwareVO createProductoSoftware(ProductoSoftwareVO vo) 
		throws InternalErrorException,DataBaseException {}
	public ConsultaVO createConsulta(ConsultaVO vo) 
		throws InternalErrorException,DataBaseException {}
	public Collection listConsulta() 
		throws InternalErrorException {}
	public Collection listProductoSoftware()
		throws InternalErrorException {}
	public void removeProductoSoftware(Long softwareIdentifier)
		throws InternalErrorException {}
	public void removeConsulta(Long consultaIdentifier) 
		throws InternalErrorException { }
	public void updateProductoSoftware(ProductoSoftwareVO vo) 
		throws InternalErrorException, DataBaseException {}
	public ProductoSoftwareVO findProductoSoftware(Long softwareIdentifier) 
		throws InternalErrorException,DataBaseException {
	}
}

Esta façade será el punto de acceso a todas las funcionalidades del sistema. En una arquitectúra MVC (Modelo Vista Control), los DAO’s y el VO representan la capa Modelo. La Vista puede ser representada por una aplicación Swing, JSP o Applet. La vista se comunica con las clases controlador, las cuales son las que se comunican a su vez con la façade del sistema. De esta forma, se tiene una arquitectura general del software con menos acoplamiento, lo que permite trabajar con el modelo de forma independiente a la vista (potenciando la separación de roles de trabajo, por ejemplo, equipo de desarrollo del Modelo, equipo de desarrollo de la Vista y Control, etc.)

La siguiente fase del diseño es definir la vista que se favorecerá del Modelo. Según el caso de estudio, se requiere de una WebApp, por lo que las vistas serán implementadas como JSP y las clases controlador serán definidas como Servlets Action (subclase de Action de Struts) que invocan a los datos de la façade (para evitar que la vista se comunique directamente con la façade del sistema). Para definir los elementos de la vista, se requiere del diseño de la navegación, la cual será jerárquica:

Mapa de navegación / componentes de la vista Administrador (1)
También incluye la siguiente jerarquía:

La navegación de la vista Cliente queda definida de la siguiente forma:

Los servlets action cumplen el rol de controlador de flujo de las acciones, seteando los datos que deben presentarse en las páginas JSP, y también son utilizados para invocar a los métodos de negocios definidos en la façade.

3. Implementación

En la implementación se deben codificar los modelos de clases obtenidos del diseño (en este caso, en un diseño logrado con la aplicación directa de los patrones de diseño). Se debe tener en cuenta que el patrón de diseño representa una solución de diseño, teniendo como objetivo la reutilización. Sin embargo, la codificación del patrón de diseño a lenguaje Java no conduce necesariamente a componentes reutilizables, por lo que se deberán utilizar otras herramientas para hacer reutilizable el código obtenido. En esta investigación se utilizó el Refactoring de Eclipse para reutilizar el código de las clases, utilizando un DAO de otro proyecto anterior, para luego adaptar el nombre, la ruta de los paquetes, y la redefinición del método (en general, cambiar el SQL). Las vinculaciones y correcciones de nombres son realizadas por el IDE. Esta técnica es útil para los DAO’s que tienen pocos campos y que cumplen las mismas funcionalidades básicas (por ejemplo, una tabla pais (id,descripción) y otra tabla categorias (id, categoria) las que son utilizadas para llenar los comboBox de un formulario).

La implementación del Modelo Vista Control se realizó en Struts 1.1 [APA02], aconsejando la siguiente metodología en la implementación del mapa de acciones [URZ03]:

  1. Definir el mapeo correspondiente a la nueva acción en el archivo struts-config.xml, indicando el nombre de la acción, y la clase Action que ejecutará las acciones correspondientes, el nombre del FormBean que validará los datos, el alcance que tendrán esos datos, de donde será referenciada y quien desplegará los datos para los ActionForward definidos en el servlet. (ver struts-config.xml)
  2. Escribir el BeanForm, y realizar las validaciones correspondientes para asegurar que los datos lleguen al controlador (Action). (ver ProductoSoftwareForm.java)
  3. Escribir el Action Servlet, el cual ejecutará las acciones del requerimiento (típicamente una invocación a la façade, la asignación de valores al FormBean y la asignación de valores asociados a la Request). (ver EditVerCatalogoAction.java)
  4. Escribir el o los archivos JSP que generará la vista para el usuario. Se debe tener especial cuidado con los beans y atributos que se utilizarán en este archivo ya que deben estar definidos en el FormBean e ingresados como atributos al requerimiento que recibe la página JSP.(ver VerCatalogo.jsp)

Para implementar los componentes de la vista, se utiliza Java Standar Tag Library (JSTL), puesto que consiste en una solución, basada en XML, que sustituye el scriptlet incristado de la páginas JSP por tags XML [PAL03]. Este tipo de solución permite adecuar la vista a los roles que no están familiarisados con el código Java, como por ejemplo, los diseñadores. De esta forma, se mejora la separación de roles de trabajo.

Conclusiones

La implementación de patrones J2EE no es trivial en los desarrollos de aplicaciones empresariales. Los desarrolladores necesitan conocer propuestas metodológicas para una correcta implementación de los patrones. La investigación entrega un aporte metológico, junto con un producto de baja escala con ejemplos de implementación.

El código fuente del caso de estudio, incluido en la investigación, puede ayudar a comprender la implementación del patrón, pero debe quedar claro que los patrones no son las respuestas únicas a un problema, sino que más bien representan una solución estructural y de comportamiento para un problema de diseño recurrente.

Recursos del artículo

Bibliografía general

  • [ALE77] Alexander, Christopher. A Pattern Language: Towns/Buildings/Construction. USA. Oxford University Press. 1977.
  • [APA02] Apache Software Foundation. The Apache Struts Web Application Framework, 2002.Disponible en http://jakarta.apache.org/struts/
  • [BAR03] Barrios Nuñez, Juan Manual. Investigación de la Plataforma J2EE y su Aplicación Práctica. Memoria para optar al título de Ingeniero Civil en Computación,Universidad de Chile, 2003. p.116
  • [BEL03] Bellas Permuy, Fernando. Apuntes y código fuente de la asignatura “Integración de Sistemas 2003”. Disponible en http://www.tic.udc.es/~fbellas/teaching/is.
  • [BEL03-2] Bellas Permuy, Fernando. Un Enfoque Práctico Basado en Patrones de Diseño para la Enseñanza de J2EE. Universidad de A Coruña año 2003. Disponible en http://www.tic.udc.es/~fbellas
  • [BOO99] Booch, Grady et al. El Lenguaje Unificado de Modelamiento. España. Addison Wesley. 1999. p.432
  • [DIA03] Días, Moises et al. Traducción al español del catálogo de patrones de diseño J2EE para la capa de presentación y negocios. 2003. Disponible en http://www.programacion.net/java/tutorial/patrones2/
  • [GAM95] Gamma, Erich et al. Design Patterns: Elements of Reusable Object-Oriented Software. Holanda. Addison Wesley. 1995. p.395
  • [GON03] González Calero, Pedro et al. Apuntes del curso Patrones de Diseño Orientado a Objetos. 2003. Disponible en http://www.ucm.es/info/dsip/DOOCT-PDDOO.html
  • [GUE03] Guerrero, Luis. Apuntes del curso de Análisis y Diseño Orientado a Objetos. 2003. Disponible en http://www.dcc.uchile.cl/~luguerre/cc40b
  • [HUS02] Husted, Ted. idioms struts. 2002 Disponible en http://husted.com/struts/catalog.html
  • [JAW99] Jaworski, James. Java 1.2 Al Descubierto. Madrid. Prentice Hall. 1999. p.1344
  • [MAR02] Marinescu, Floyd. EJB Design Patterns: Advanced Patterns, Pro-cesses, and Idioms. USA. John Wiley. 2002. p.259
  • [MID02] Middleware Company. J2EE and .NET Application Server and Web Service Benchmark
  • [PAL03] Palos, Juan Antonio. Estandarizando JSP. 2004 Disponible en http://www.programacion.com/java/tutorial/jstl1/2/
  • [PAL02] Palos, Juan Antonio. El API Struts. 2002. Disponible en http://www.programacion.com/tutorial.struts.html.
  • [PRE02] Pressman, Roger. Ingeniería de Software: Un Enfoque Práctico. Mexico. McGraw Hill. 2002. p.601
  • [SUN03-1] Sun Microsystem. Core J2EE Patterns Index. 2003. Disponible en http://java.sun.com/blueprints/corej2eepatterns/index.html
  • [SUN03-2] Sun Microsystem. Enterprise Java Technologies Tech Tips. 2003. Disponible en http://java.sun.com/developer/EJTechTips/
  • [URZ03] Urzúa Reinoso, José Andrés. Diseño e Implementación de un Nuevo Sistema de Facturación Para Nic Chile. Memoria para optar al título de Ingeniero Civil en Computación,Universidad de Chile, 2003. p.130. Disponible en http://nicolette.nic.cl/~jourzua/personal/files/memoria.pdf
  • [VIL02] Vilches Vásquez, Juan Antonio. Generación Automática de Encuestas Web Usando Patrones de Diseño. Memoria para optar al título de Ingeniero Civil en Computación, Universidad de Chile, 2002. p.78
  • [WEB1] Varios Autores. Estructura de patrones de diseño Gamma et al. 2003.Disponible en http://www.tml.hut.fi/~pnr/GoF-models/html/
  • [WEB2] Varios Autores. Patterns of Java and Distributed Computing. 2003. Disponible en http://cmcrossroads.com/bradapp/javapats.html
  • [WES02] Wesner, Stephan. Struts Tutorial. 2002. p.51. Disponible en http://www.stephanwiesner.de/

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP