Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Copia de Patrones de Diseño
Copia de Patrones de Diseño
Los patrones de diseño de J2EE presentados por Sun Microsystems, han sido divididos
en capas (presentación, negocios, integración) según su funcionalidad. Los patrones de la capa
de presentación contienen toda la información relacionada con los servlets y tecnología JSP
[1]. Los patrones de la capa de Lógica de Negocios, contienen toda la información relacionada
con los Enterprise Java Beans. Por ultimo, los patrones de la capa de Integración contienen
toda la información relacionada con el Java Message Service [1] y la tecnología para conexión
con base de datos de java JDBC.
Contexto
Problema
Fortalezas
Una vez mencionados los puntos centrales que deben ser cubiertos por el patrón se
procederá a describir la solución que propone el patrón.
La idea principal de esta solución es la de crear una serie de filtros que se conecten
entre sí para realizar el procesamiento de servicios comunes del sistema en una forma
estándar sin la necesidad de cambiar el código que se encuentra en el núcleo de la aplicación
para el procesamiento de solicitudes, con esto se pretende “decorar” el procesamiento
principal con una variedad de servicios comunes, tales como seguridad, registro de logs,
depuración, etc. Estos filtros son componentes independientes del código central de la
aplicación, lo cual permite que puedan ser removidos o añadidos fácilmente. Por ejemplo, un
archivo de configuración de despliegue o publicación puede ser modificado con la finalidad de
configurar una serie de filtros. El mismo archivo de configuración podría incluir un mapeo de
URL’s específicos para el conjunto de filtros mencionados anteriormente. Cuando un cliente
solicita un recurso que coincide con los URL’s que se han configurado, cada uno de los filtros es
procesado antes que se retorne el recurso solicitado.
• Control Centralizado
Este patrón provee un lugar central para manejar los servicios y lógica de negocios a lo
largo de múltiples solicitudes. Existe otro patrón denominado Front Controller3 que también
permite obtener un control centralizado pero tiene la desventaja de no permitir la separación
de servicios comunes no relacionados entre sí, tales como autenticación, registro de logs,
cifrado de datos, etc.
• Mayor Reusabilidad
• Flexibilidad de Configuración
Esto es debido a que cada componente es escrito independientemente uno del otro.
La información compartida entre filtros puede ser ineficiente, debido a que cada filtro
es independiente uno del otro. Si grandes cantidades de información deben ser compartidas
entre filtros puede resultar muy costoso el uso de este esquema.
3
En secciones posteriores se describirá con mayor detalle el funcionamiento de este patrón.
2.- Patrón Front Controller
Contexto
Este patrón surge con la finalidad de proveer un mecanismo que permita a la capa de
presentación controlar y coordinar el procesamiento de cada usuario a lo largo de múltiples
solicitudes, además debe permitir administrar dichos mecanismos de una forma centralizada o
distribuida.
Problema
El problema principal que debe resolver este patrón es que el sistema requiere un punto
de acceso centralizado para el manejo de solicitudes de la capa de presentación para con ello,
ayudar a la integración de los servicios del sistema, recuperación de contenido, manejo de
vistas y navegación. Cuando el usuario accede a una vista directamente sin pasar a través de
un mecanismo centralizado, pueden ocurrir dos tipos de problemas:
a.- Cada vista es requerida para proveer sus propios servicios de sistema, lo cual
termina resultando a menudo en duplicación de código.
Fortalezas
Solución
Aunque el patrón “Front Controller” propone la centralización del manejo de todas las
solicitudes, esto no limita el número de manejadores en el sistema, tal y como lo haría un
patrón de tipo Singleton4. Una aplicación puede usar múltiples controladores en un sistema,
cada unos de estos mapea un conjunto de servicios diferentes.
Consecuencias
• Control Centralizado
Un controlador provee un lugar central para manejar los servicios del sistema y la lógica
de negocios a lo largo de múltiples solicitudes. El acceso centralizado a una aplicación
implica el hecho de que las solicitudes sean fácilmente seguidas y registradas. La
desventaja principal del esquema centralizado es la poca tolerancia a fallos que posee.
4
Un patrón de tipo Singleton es aquel que permite que exista solo una instancia única de un ejemplar.
3.- Patrón Helper View
Contexto
Problema
Fortalezas
• Incluir lógica de negocio en las vistas promueve el tipo de reuso estilo “copiar y pegar”.
Esto puede ocasionar problemas y errores debido a que un trozo de la lógica de
negocios es reutilizado en la misma o en diferentes vistas simplemente colocando al
código duplicado en lugares diferentes.
• Es deseable incrementar una separación transparente para que cada individuo del
equipo de desarrollo pueda cumplir a cabalidad las labores relacionadas con su rol
dentro del equipo de trabajo.
• Una vista es comúnmente usada para responder a una solicitud particular.
Solución
Las vistas delegan el manejo de contenido a sus ayudantes (helpers), los cuales sirve
como modelo de datos y adaptadores para los datos. La lógica de presentación es encapsulada
en el ayudante y se sitúa entre la vista y la capa de negocios.
Una señal que puede indicar la necesidad de usar de este patrón con el código
existente, es que un scriplet sobrecargue o desordene una vista JSP. El objetivo principal de
aplicar este patrón es realizar la partición de la lógica de negocios fuera de la vista. Aunque
algo del código de la lógica de negocios puede ser más útil si se encuentra encapsulado dentro
de ayudantes, pueden existir porciones de código que deben estar en un componente
centralizado que los situé en frente de las vistas y los ayudantes (tales como chequeos de
autenticación o servicios de registro de actividades “logging”).5
5
Para resolver este problema se deben emplear los patrones “Decorating filter” y “Front Controller” explicados anteriormente .
Estructura
Vista
Ayudante
Una vista puede trabajar con cualquier número de ayudantes, los cuales son
implementados típicamente como JavaBeans y etiquetas personalizadas. Adicionalmente, un
ayudante puede representar un objeto de tipo Command, Delegate o también un objeto de
tipo XSLT, el cual es usado en combinación con una hoja de estilo para adaptar y convertir el
modelo a una forma apropiada.
Consecuencias
El uso de ayudantes proporciona una separación clara de las vistas con respecto a la
lógica de procesamiento de la aplicación. Los ayudantes, en la forma de JavaBeans y
Etiquetas Personalizadas, proveen un lugar para colocar la lógica de procesamiento fuera
de las páginas JSP.
• Separación de Roles
• Reusabilidad
Contexto
Problema
Fortalezas
Solución
Otro beneficio de este patrón es que los diseñadores Web pueden hacer prototipos de la
apariencia de un site, colocando contenido estático en cada una de las regiones de las
plantillas. A medida que el desarrollo del site avanza, el contenido puede ser modificado por
sus elaboradores.
La figura 3.5 muestra una toma del sitio oficial de Java, en ella se pueden observar las
4 regiones que conforman el site, y aunque el contenido de cada región puede provenir de
fuentes de datos distintas, al ser colocadas todas sobre una misma región conforman una vista
compuesta.
Figura 3.5 Vista de una página modular que incluye 4 regiones denominadas, Search,
Navigation, Feature Story, y Headlines
Por supuesto, este patrón posee desventajas, y una de las mas evidentes es la de la
posible sobrecarga de ejecución producida por el incremento de flexibilidad que este patrón
provee. Además, el uso de una distribución de elementos sofisticada puede generar problemas
de desarrollo, debido al gran número de artefactos que se deben mantener.
Estructura
Este patrón mejora el diseño modular. Esto hace posible que se puedan reutilizar
porciones atómicas de una plantilla, tal como una tabla de inventario, en numerosas vistas,
adicionalmente estas vistas pueden ser rellenadas con información diferente. Este patrón
permite que una tabla sea movida a su propio módulo y que sea usada solo cuando sea
necesario. Este tipo de distribución dinámica de elementos reduce la duplicación innecesaria de
código y mejora la facilidad de mantenimiento de la aplicación.
• Flexibilidad mejorada
• Impacto en el Rendimiento
Generar una página que contenga numerosas sub-vistas puede disminuir el rendimiento
de una aplicación. La inclusión de sub-vistas en tiempo de ejecución puede convertirse en un
retraso que se produce cada vez que la página es solicitada por el cliente, lo cual podría
afectar drásticamente el desempeño de la aplicación en ambientes con Niveles de Servicio muy
estrictos. Una alternativa es que la inclusión de la sub-vistas se realice en el momento en el
que el motor JSP se encuentra procesando una página, aunque esto limita a que los cambios
que se realicen sobre una sub-vista solo se muestren cuando esta sea nuevamente procesada.
5.- Patrón Service to Worker
Contexto
Problema
Las porciones de lógica de negocio que son mezcladas con las vistas deben ser
adaptadas a un modelo intermedio para su visualización.
Fortalezas
Solución
Combinar un despachador con vistas y ayudantes para manejar las solicitudes de los
clientes y preparar una presentación dinámica como respuesta. Un despachador es
responsable por el manejo de vistas y la navegación, y puede ser o no encapsulado dentro de
un controlador, o puede ser un componente independiente que trabaje de forma sincronizada
con los componentes internos.
Este patrón y el Dispatcher View poseen una estructura similar, pero aún así, cada
patrón sugiere una división diferente de las labores que debe realizar cada componente. En
este patrón, el Controlador y el Despachador poseen mayores responsabilidades
Un rol limitado para el Despachador ocurre cuando no se utilizan recursos externos para
seleccionar una vista. La información encapsulada en la solicitud es suficiente para determinar
las Vistas a utilizar para resolver una petición. Por ejemplo en este caso:
http://some.server.com/servlet/Controller?next=login.jsp
La responsabilidad del Despachador es la de proporcionar acceso a la vista ‘login.jsp‘
Un ejemplo del Despachador con rol moderado es el caso en el cual el cliente envía una
petición directamente a un Controlador con un parámetro de una consulta que describe una
acción que debe ser completada:
http://some.server.com/servlet/Controller?action=login
Por otro lado, en el patrón “Service to Worker”, el Despachador debe ser más
sofisticado, ya que este debe invocar las funciones de negocio necesarias para determinar las
vistas que se van a mostrar.
Estructura
La figura 3.7 muestra el diagrama de clases representa al patrón Service to Worker:
Controlador
Despachador
Una vista representa y visualiza información para los clientes. La información que es
usada en una vista es tomada de un modelo.
Ayudante
Una vista puede trabajar con cualquier número de ayudantes, los cuales son
implementados típicamente como JavaBeans y etiquetas personalizadas. Adicionalmente, un
ayudante puede representar un objeto de tipo Command, Delegate o también un objeto de
tipo XSLT, el cual es usado en combinación con una hoja de estilo para adaptar y convertir el
modelo a una forma apropiada.
Consecuencias
• Reusabilidad
El uso de ayudantes proporciona una separación clara de las vistas con respecto a la
lógica de procesamiento de la aplicación. Los ayudantes, en la forma de JavaBeans y Etiquetas
Personalizadas, proveen un lugar para colocar la lógica de procesamiento fuera de las páginas
JSP.
6.- Patrón Dispatcher View
Contexto
Problema
Las porciones de lógica de negocio que son mezcladas con las vistas deben ser
adaptadas al modelo intermedio para su visualización.
Fortalezas
Solución
Combinar un Despachador con Vistas y Ayudantes para manejar las solicitudes de los
clientes y preparar una presentación dinámica como respuesta. Un despachador es
responsable por el manejo de vistas y la navegación, y puede ser o no encapsulado dentro de
un controlador, o puede ser un componente independiente que trabaje de forma sincronizada
con los componentes internos.
Este patrón y el Service to Worker poseen una estructura similar, aunque cada patrón
sugiere una división diferente de las labores que debe realizar cada componente. El
Controlador y el Despachador tienen responsabilidades limitadas (como se mencionó en el
patrón anterior), debido a que el procesamiento principal y el manejo de vistas es muy básico.
Mas aún, si el control centralizado de los recursos subyacentes es considerado innecesario,
entonces el Controlador es removido y el Despachador puede ser movido a una Vista.
Un rol limitado para el Despachador ocurre cuando no se utilizan recursos externos para
seleccionar una vista. La información encapsulada en la solicitud es suficiente para determinar
las Vistas a utilizar para resolver una petición. Por ejemplo en este caso:
http://some.server.com/servlet/Controller?next=login.jsp
Un ejemplo del Despachador con rol moderado es el caso en el cual el cliente envía una
petición directamente a un Controlador con un parámetro de una consulta que describe una
acción que debe ser completada:
http://some.server.com/servlet/Controller?action=login
Por otro lado, en el patrón “Service to Worker”, el Despachador debe ser más
sofisticado, ya que este debe invocar las funciones de negocio necesarias para determinar las
vistas que se van a mostrar.
Estructura
Despachador
Vista
Una vista representa y visualiza información para los clientes. La información que es
usada en una vista es tomada de un modelo.
Ayudante
Una vista puede trabajar con cualquier número de ayudantes, los cuales son
implementados típicamente como JavaBeans y etiquetas personalizadas. Adicionalmente, un
ayudante puede representar un objeto de tipo Command, Delegate o también un objeto de
tipo XSLT, el cual es usado en combinación con una hoja de estilo para adaptar y convertir el
modelo a una forma apropiada.
Aunque las responsabilidades del Controlador están limitadas a los servicios que posee
el sistema, tales como autenticación y autorización, a menudo resulta beneficioso centralizar
estos aspectos del sistema. A diferencia del patrón “Service to Worker”, el Despachador no
realiza invocaciones a métodos de negocio para llevar a cabo su procesamiento y manejo de
las vistas.
De hecho, las funcionalidades del Despachador podrían ser incluso realizadas por el
contenedor, en el caso de que no se necesite lógica extra a nivel de aplicación. Un ejemplo de
esto, es una vista llamada main.jsp la cual tiene como alias el nombre first. El contenedor
puede procesar esta petición, traducir el alias al nombre fisico del recurso y entregar
directamente dicho recurso:
http://some.server.com/first
• Control Centralizado
El control centralizado provee un lugar central para manejar los servicios del sistema a
los largo de múltiples solicitudes. Aunque decisiones tales como seleccionar que JSP debe
mostrarse se encuentran incluidas dentro de la petición, el control centralizado permite al
controlador mejorar el manejo de los servicios de seguridad y despacho.
• Reusabilidad
El uso de ayudantes proporciona una separación clara de las vistas con respecto a la
lógica de procesamiento de la aplicación. Los ayudantes, en la forma de JavaBeans y Etiquetas
Personalizadas, proveen un lugar para colocar la lógica de procesamiento fuera de las páginas
JSP.
Patrones de la Capa de la Lógica de Negocios
Contexto
La aplicación cliente necesita intercambiar datos con algún Enterprise Java Bean (EJB).
Problema
Los aplicaciones J2EE implementan componentes de negocios del lado de servidor como
beans de sesión (session beans) y beans de entidad (entity beans). Los beans de sesión
representan los servicio de la lógica de negocios y permiten mantener una relación uno a uno
con el cliente. Los beans de entidad, por su parte, son multiusuarios y representan la data
persistente.
Fortalezas
Por lo general, las aplicaciones utilizan con mayor frecuencia de operaciones de lectura
que de actualización. La data se transfiere desde la lógica de negocio hacia la capa
presentación, despliegue y posteriormente al cliente.
El número de llamadas que realiza el cliente hacia los EJB tiene un gran impacto sobre
el rendimiento de la red, debido a la sobrecarga que se genera por cada petición.
Solución
Se puede utilizar un Value Object para encapsular la data del negocio. La llamada a un
método sencillo puede ser utilizado para enviar y recibir el Value Object. Cuando el cliente le
solicita al enterprise bean los datos de negocio, el bean puede construir el Value Object,
rellenarlo con los valores de los atributos, y retornarlo al cliente.
Los clientes por lo general requieren más de un valor de un enterprise bean. Para
reducir el numero de llamadas remotas y evitar por consiguiente la sobrecarga asociada,
resulta más conveniente utilizar el Value Object para transportar la data desde el enterprise
bean hacia el cliente.
Cuando el enterprise bean utiliza un value object, el cliente realiza una sola invocación
al bean obteniendo como resultado el value object en lugar de realizar múltiples llamadas para
obtener cada uno de los atributos. Luego el bean instancia un value object y copia los valores
de sus atributos en la instancia del objeto que acaba de crear. Finalmente retorna el value
object al cliente.
6
En secciones posteriores se describirá con mayor detalle el funcionamiento de este patrón.
Estructura
Consecuencias
El entity bean provee un método getData() para obtener el value object que contiene los
valores de los atributos deseados. Esto elimina la necesidad de tener multiples metodos
get, así como su respectiva implementación en el bean y su definición en la interfaz
remota. Similarmente, si el entity bean provee un método SetData(), se podrían eliminar
también los métodos set del bean en la implementación y de igual forma en la interfaz
remota.
• Propagación de la actualización
Si se adopta la estrategia del patrón value object los clientes pueden realizar
modificaciones en la copia local, es decir, el objeto value object. Una vez que se realizan
dichas modificaciones, el cliente puede invocar al método setData() y actualizar los valores
en el objeto entidad. Aunque esto puede traer problemas ya que otros clientes pueden
haber realizado el mismo procedimiento, ya que no es posible determinar en primera
instancia si ya se han modificado otros valores por parte de los clientes.
En lugar de realizar múltiples llamadas para obtener los valores de los atributos, ésta
solución provee un método único para realizar la llamada. Aunque muchas veces la
llamada a dicho método puede retornar gran cantidad de datos. Por lo cual se debe
considerar la relación entre el número de llamadas que se deben realizar al bean versus la
cantidad de datos obtenidos por llamada.
2. Patrón Business Delegate
Contexto
El sistema expone sus servicios de negocio por medio de un API a sus clientes, a través
de una red.
Problema
Finalmente, la exposición directa del API a los clientes, el mismo, se va obligado a lidiar
con la ínter conectividad a la cual esta asociada la tecnología de los EJB.
Fortalezas
Solución
Se puede utilizar el patrón Business Delegate para reducir el acoplamiento entre la capa
de presentación y los servicios de la lógica de negocios. El Business Delegate esconde los
detalles de implementación de la lógica de negocios, como por ejemplo búsqueda (lookup) y
los detalles de acceso a la arquitectura de los EJB.
Finalmente, hay que destacar que este patrón puede reducir la complejidad entre otras capas
y no sólo entre la capa de presentación y la de lógica de negocios.
Estructura
Consecuencias
• Impacto en el rendimiento:
Contexto
Los beans de entidad no están concebidos para representar cada uno de los objetos
persistentes dentro del modelo de objetos. Los beans de entidad se ajustan mejor para
representar los objetos del negocio persistentes de grano grueso.
Problema
En una aplicación J2EE, los clientes (aplicaciones, Java Server Pages, Servlets y Java
Beans), acceden los beans de entidad por medio de sus interfaces remotas. Así, cada
invocación potencial, realiza un direccionamiento a través de stubs y skeletons, incluso si el
cliente y el enterprise bean se encuentran en la misma máquina virtual de Java, bajo el mismo
sistema operativo o en la misma máquina. Cuando se utilizan beans de entidad de grano fino,
lo clientes tienden a invocar a múltiples métodos de un bean de entidad, lo cual resulta en una
sobrecarga de la red.
Los beans de entidad representan los objetos persistentes del negocio. Cuando se
desarrollan o se migran aplicaciones a la plataforma J2EE, la granularidad de los objetos es un
factor muy importante a la hora de decidir que se debe implementar como un bean de entidad
y que no. Los beans de entidad deben representar los objetos del negocio de grano grueso, es
decir, aquellos que posean un comportamiento complejo más allá de simplemente obtener y
actualizar campos de datos. Estos objetos de grano grueso por lo general poseen objetos
dependientes, los cuales no tienen significado alguno dentro del dominio de la aplicación sino
se asocian a algún objeto de grano grueso.
Fortalezas
Los beans de entidad se implementan por lo general como objetos de grano grueso
debido a la alta sobrecarga que generan los mismos. Cada bean de entidad esta asociado a un
EJB home, un objeto remoto, así, como a su implementación como tal, y cada uno de ellos es
manejado por los servicios del contenedor.
Las aplicaciones que realizan una correspondencia directa entre el esquema de una
base de datos relacional y los beans de entidad (donde cada fila esta representada por una
instancia de un bean de entidad), tienden a poseer una gran cantidad de beans de entidad de
grano fino. Sería deseable mantener beans de entidad de grano grueso y así reducir el número
de beans de entidad dentro de la aplicación.
Solución
Un objeto de grano grueso es auto suficiente. Es decir, posee su propio ciclo de vida y
gestiona sus relaciones con otros objetos. Cada uno de ellos puede referenciar o contener uno
o más objetos. Por esta razón, el objeto de grano grueso también gestiona los ciclos de vida de
los objetos que contiene. Dichos objetos se conocen con el nombre de objetos dependientes.
Los objetos dependientes a su vez, pueden contener otros objetos dependientes.
Una bean de aggregate entity puede representar a un objeto de grano grueso y a todos
sus objetos dependientes. La agregación combina los objetos persistentes interrelacionados en
un único bean de entidad, lo cual reduce drásticamente el número de beans de entidad
requeridos por la aplicación. Esto conlleva a que con el uso de beans de entidad de grano
grueso se obtengan mayores beneficios que si se utilizaran beans de grano fino. Ya que sin
este enfoque, la tendencia natural llevaría a tener una gran cantidad de beans de entidad.
Estructura
• Relaciones
Si se utiliza el patrón Agreggate Entity, los objetos dependientes son agregados como un
bean de entidad único, eliminando así todas las relaciones inter - beans de entidad. Este
patrón provee una forma centralizada de gestión tanto para las relaciones como para la
jerarquía de objetos.
• Gestión eficiente
• Rendimiento de Red
Los resultados de aplicar este patrón generan beans de entidad de grano grueso en su
implementación. El esquema de la base de datos es transparente para el cliente, ya que la
correspondencia se realiza con los beans de entidad de grano grueso. Sin embargo, si
ocurren cambios en el esquema de la base de datos, se deben realizar cambios en los
beans de aggregate entity. Sin embargo, los clientes no se verán afectados.
Como resultado de aplicar este patrón, el cliente por lo general busca sobre un bean de
entidad particular, en lugar de una cantidad numerosa de ellos de granularidad fina. El
cliente solicita al Agreggate entity los datos, él mismo puede crear un objeto compuesto
que contenga los valores necesarios desde el bean de entidad y retornar el objeto
correspondiente al cliente, en una sola llamada. Esto reduce el intercambio entre el cliente
y los EJB.
4. Patrón Value Object Assembler
Contexto
En las aplicaciones J2EE, los componentes del negocio del lado del servidor se
implementan utilizando los beans de sesión, los beans de entidad, entre otros. Los clientes de
la aplicación necesitan con frecuencia datos compuestos a partir de múltiples objetos.
Problema
2. El cliente accede a los componentes distribuidos por medio de la capa de red, esto
puede traer como consecuencia que si se crea un modelo de gran complejidad con
múltiples componentes, el rendimiento de la red se vea seriamente afectado, por la
cantidad de accesos que se realizan.
3. El cliente debe reconstruir el modelo una vez que obtiene la parte del mismo que viene
del componente distribuido. Por lo cual, el cliente necesita tener la información
necesaria de la lógica de negocios para construir el modelo. Si la construcción de dicho
modelo involucra numerosos objetos en su definición y una gran complejidad, entonces
se presenta una sobrecarga adicional sobre del lado del cliente debido a éste
procesamiento.
4. Debido a que el cliente se encuentra fuertemente acoplado a este modelo, los cambios
que se realicen sobre el modelo, recaen directamente en modificaciones sobre el
cliente. Si existe más de un tipo de cliente, cada vez se hace más difícil manejar los
cambios del modelo.
Fortalezas
Solución
Se debe utilizar el patrón Value Object Assemble para construir el modelo requerido o
un sub-modelo. El Value Object Assembler utiliza value objects para obtener los datos de
múltiples objetos de la lógica de negocios y de otros objetos que definen el modelo o parte del
mismo.
Estructura
La figura 3.12 muestra el diagrama de clases representa al patrón Value Object Assembler:
Cuando el cliente utiliza la lógica de negocios para gestionar las interacciones con los
componentes distribuidos, se dificulta mucho separar de manera clara la lógica de negocios
de la capa del cliente. Con el Value Object Assembler el cliente no necesita conocer como
está construido el modelo o los diversos componentes que proveen la data necesaria para
ensamblar el modelo.
• Rendimiento de la red
El Value Object Assembler permite construir el modelo como una composición de value
objects sin utilizar ningún recurso del lado del cliente. El cliente no consume tiempo y
recursos en esta operación.
5. Value List Handler
Contexto
Problema
Otro problema surge cuando se utilizan los métodos ejbFind de los beans de entidad
para obtener una lista de valores. Estos retornan una colección de objetos remotos y
posteriormente se llaman a los respectivos métodos uno a uno para obtener los valores
deseados, esto se considera como una mala práctica y además representa un gran consumo de
recursos de red.
Fortalezas
Solución
Se debe utilizar el patrón Value List Handler para controlar la búsqueda, mantener una
caché de resultados y proveer los resultados al cliente en un espacio de resultados, el cual
satisfaga las necesidades del mismo.
Este patrón crea un ValueListHandler para proveer la funcionalidad de ejecución de
querys y del caché de resultados. El ValueListHandler accede directamente al objeto de Acceso
a Datos (Data Access Object) que es el que puede ejecutar el query requerido. El
ValueListHandler almacena el resultado obtenido desde el Data Access object como una
colección de value objects. El cliente es el que le pide al ValueHandlerList que le provea de los
resultados que necesita. El ValueListHandler implementa el patrón Iterator(2) para proveer
esta solución.
Estructura
La figura 3.13 ilustra el diagrama de clases del patrón Value List Handler.
Consecuencias.
El método find del EJB por lo general es un recurso de uso intensivo y una manera muy
costosa de obtener una lista de valores, ya que involucra numerosas referencias a objetos
EJB. El patrón Value List Handler implementa un bean de sesión que utiliza un objeto de
acceso a los datos (DataAccessObject) para realizar las consultas respectivas y crear una
colección de value objects que cumplan con los criterios de la búsqueda. Dado que estos
value objects poseen una sobrecarga mucho menor si se comparan con los objetos EJB,
este patrón provee beneficios cuando la aplicación cliente requiere consultar una gran
cantidad de datos.
• Mecanismos de caché de los resultados de las consultas del lado del servidor y
despacho de resultados controlado del lado del cliente.
Este patrón permite que el conjunto de datos obtenidos al realizar una búsqueda sean
manejados por mecanismos de caché del lado del servidor mediante un bean de sesión.
Cuando el cliente solicita el conjunto de datos o un subconjunto de datos, el bean
manejador retorna los resultados como una colección de objetos serializados. El cliente
recibe esta colección y la puede procesar o mostrar. Cuando el cliente necesite otro
conjunto de datos, le solicita al manejador otra colección serializada de objetos que
proveen los resultados que se requieran y así sucesivamente. El bean manejador también
debe proveer al cliente facilidades de navegación (atrás o adelante) al cliente y que le
permitan realizar recorridos sobre el conjunto de datos obtenido.
• Flexibilidad de consultas
Cuando se añade una nueva consulta, por lo general se requiere un nuevo método find
o la modificación de uno ya existente, especialmente cuando se utiliza la persistencia
manejada por el bean (con la persistencia manejada por el bean, el desarrollador
implementa los métodos de búsqueda en conjunto con la implementación del bean).
Cuando la persistencia es manejada por el contenedor, el desarrollados especifica los
métodos de búsqueda del bean de entidad en el descriptor de despliegue del bean. Los
cambios que se realicen bajo el esquema de la persistencia manejada por el contenedor
requieren cambios en el descriptor de despliegue. Se podria realizar una implementación
del patrón Value List Handler que permita hacer más flexible los métodos de búsqueda y
que provea facilidades para consultas “adhoc”, construcción de consultas en tiempo de
ejecución usando métodos como templates, y así sucesivamente. En otras palabras, este
patrón puede implementar búsquedas inteligentes y algoritmos de almacenamiento sin
estar limitado sólo a los métodos de búsqueda de los beans.
• Rendimiento de la red
Mejora el rendimiento de la red debido a que los datos requerido son enviados (de
manera serializada) al cliente a medida que se necesiten, en lugar de enviarlos todos al
mismo tiempo. Así, si el cliente muestra solo los primeros resultados y posteriormente
decide abandonar la consulta, el ancho de banda de la red no es subutilizado, dado que los
datos no fueron enviados en su totalidad al cliente, aunque éste no hiciera uso de los
mismos. Sin embargo, si el cliente sabe que el conjunto de datos va a ser procesado en su
totalidad, esto recae sobre múltiples llamadas al servidor. Por lo cual en este caso se puede
proveer un método que envía al cliente el conjunto de datos en una sola llamada, y el
mecanismo de caché que provee el patrón no se utilizaría para esa caso en particular.
6. Patrón Service Locator
Contexto
Problema
Los clientes J2EE interactúan con los componentes del servicio como los EJB y los
componentes de JMS, los cuales proveen los servicios de negocios y la persistencia. Para
realizar la interacción con dichos componentes, los clientes deben localizar el componente del
servicio (esto se conoce también como operación de búsqueda) o crear un nuevo componente.
Por ejemplo, un cliente EJB debe localizar el objeto home del enteprise bean, que
posteriormente utilizará para localizar un objeto, o bien crear o remover alguno de los ya
existentes. De manera similar, un cliente JMS debe localizar en primera instancia la Factoría de
conexiones JMS (JMS Connection Factory) para obtener una conexión JMS o una sesión JMS.
Así, localizar un objeto de servicio administrado por JNDI es una situación común con la
cual el cliente debe lidiar. Si este es el caso, por lo general son múltiples los tipos de clientes
que utilizan los servicios JNDI, por lo cual la mayoría de las veces el código de utilización de
estos servicios aparecen duplicados. Esto resulta en una duplicación innecesaria de código para
realizar estas operaciones.
Fortalezas
- Los clientes de los EJB necesitan utilizar el API de JNDI para buscar los objetos
EJBHome por medio del nombre registrado en el servicio de JNDI.
- Los clientes de JMS necesitan utilizar el API de JNDI para buscar los
componentes de JMS por medio de los nombres registrados para los
componentes de JMS, como por ejemplo las factorías de conexión, las colas y los
tópicos.
- La factoría del contexto se utiliza para la creación del contexto inicial de JNDI, el
cual es realizado por el también depende del tipo de objeto que se necesite
buscar, por ejemplo, el contexto para JMS es diferente al contexto para los EJB,
de los distintos proveedores. proveedor del servicio y posteriormente por el
vendedor específico.
- La búsqueda y creación de los componentes del servicio puede ser complejo y se
puede utilizar repetidamente en múltiples clientes dentro de la aplicación.
- La creación del contexto inicial y la búsquedas del objeto de servicio, son
operaciones frecuentes, las cuales pueden consumir muchos recursos y pueden
impactar directamente sobre el rendimiento de la aplicación. Esto se aprecia
mayormente cuando el cliente y el servicio que se necesita se encuentran en
diferentes capas.
- Los clientes de los EJB podrían necesitar reestablecer la conexión a un bean
accedido previamente solamente mediante un manejador para el objeto
manejador del EJB.
Solución
Se debe utilizar el objeto Service Locator para realizar una abstracción del uso de JNDI
y así ocultar su complejidad para realizar los procesos de la creación del contexto inicial, la
búsqueda del objeto EJB Home y la re-creación del objeto EJB. Múltiples clientes pueden
reutilizar el objeto Service Locator para reducir la complejidad del código y así proveer un
punto particular de control y aumentando el rendimientos, mediante la inclusión de
mecanismos de caché.
Estructura
La figura 3.14 ilustra el diagrama de clases del patrón Value List Handler.
Consecuencias
• Abstracción de la complejidad
Este patrón realiza una abstracción de todos los detalles de complejidad mencionados
anteriormente. La interfaz del patrón asegura que todos los tipos de clientes en la
aplicación accedan de manera uniforme a los objetos del negocio, en términos de su
creación y/o búsqueda. Esta uniformidad reduce el desarrollo y el mantenimiento de la
aplicación.
Debido a que los objetos EJBHome no son percibidos directamente por el cliente, es posible
añadir nuevos objetos al EJBHome para los enterprise beans desarrollados sin que esto
tenga un impacto potencial sobre el cliente. De igual forma, esta situación se presenta para
los componentes de JMS.
• Rendimiento de la red
Los clientes no se involucran directamente en la creación y/o búsqueda de los objetos por
medio de JNDI. Debido a que el Service Locator realiza esta labor, solo se realizan las
llamadas por medio de la red cuando sea necesario, evitando así la sobrecarga que se
produce por múltiples llamadas a métodos remotos.
Rendimiento de la caché
El Service Locator puede establecer una caché con los objetos del contexto inicial y sus
referencias a los objetos de la factoría (EJBHome, factorías de conexiones JMS), para
eliminar actividades innecesarias de JNDI que se suscitan cuando se obtiene el contexto
inicial y otros objetos. Esto mejora el rendimiento de la aplicación.
Patrones de la Capa de Integración
Contexto
El acceso a los datos puede variar dependiendo del origen de los datos(datasource). El
acceso a almacenes persistentes de datos, tales como una base de datos, varía grandemente
dependiendo del tipo de almacenamiento (bases de datos relaciones, orientadas a objetos, etc)
y la implementación del fabricante.
Problema
Las aplicaciones pueden usar el API JDBC para acceder a los datos residentes en una
base de datos relacional. El API JDBC permite un acceso estándar y manipulación de datos en
un almacenamiento persistente. JDBC permite a las aplicaciones J2EE usar sentencias SQL, las
cuales son estándar para el manejo de tablas en bases de datos relacionales. Sin embargo,
incluso dentro de un ambiente relacional, la sintaxis y el formato de las sentencias SQL puede
variar dependiendo del manejador de base de datos que se utilice.
Fortalezas
- Componentes tales como Entity beans de Tipo BMP, Beans de Sesión y Servlets
necesitan obtener y almacenar datos de repositorios persistentes y otros Data source
como sistemas legacy, B2B, LDAP, etc.
- Las APIs usadas para acceder a los repositorios persistentes varían de acuerdo al
fabricante del producto. Algunos data source pueden tener APIs no estándares o
propietarias. Estas APIs y sus capacidades también varían según el tipo de
almacenamiento (Bases de datos relacionales, documentos XML, archivos planos. Etc).
Existe una carencia de uniformidad en las APIs para el manejo de los requerimientos de
acceso a datos que pueda tener el sistema.
- Los componentes que acceden a sistemas de tipo legacy para obtener y almacenar
datos por lo general utilizan APIs propietarias.
- La portabilidad de los componentes se ve afectada directamente cuando mecanismos de
acceso específicos y APIs son incluidos en los componentes.
- Los componentes necesitan deben tener un acceso a los datos transparentes totalmente
independiente de las implementaciones que posean los Data source, para así permitir
que se realice más fácilmente la migración entre diferentes productos de diferentes
fabricantes.
Solución
Usar un Objeto de Acceso a Datos para abstraer y encapsular todos los accesos
realizados al origen de los datos. Los Objetos de Acceso a Datos manejan la conexión con el
origen de datos para obtener y almacenar datos.
Los Objetos de Acceso a Datos (DAO) son el elemento principal de este patrón. Los DAO
implementan los mecanismos de acceso requeridos para trabajar con el origen de los datos.
Los orígenes de datos pueden ser un repositorio persistente tal como un Sistema Manejador
de Bases de Datos Remoto, un servicio externo (por ejemplo una transacción entre dos
empresas), una base de datos LDAP o una función de negocio que puede ser accedida vía
CORBA ó IIOP. Los componentes de negocios que dependen de los DAO usan interfaces
simples para la interacción con los clientes. Debido a que la interfaz mostrada por los DAO a
los clientes no cambia cuando la implementación subyacente del origen de datos cambia, este
patrón permite a los DAO adaptarse a diferentes esquemas de almacenamiento sin afectar a
sus clientes o a los objetos de lógica de negocio. Los DAO actúan como un adaptador entre los
componentes y los data source.
Estructura
La figura 3.15 muestra el diagrama de clases y las relaciones usadas por el patrón
Data Access Object.
BusinessObject
La clase BusinessObject representa a los clientes y es un objeto que requiere acceso a los
data source para obtener y almacenar datos. Un objeto de tipo Bussiness Object puede ser
implementado como un bean de sesión, un entity bean, o algún otro objeto Java, incluyendo
un servlet o un helper bean para acceder a los datos.
DataAccessObject (DAO)
Los DAO son el objeto principal de este patrón, estos proveen las características de
encapsulación y delegación al Business Object. Los DAO se abstraen de la implementación
subyacente para acceso a los datos permitiendo así que los objetos de negocio tengan un
acceso transparente al origen de datos. Los objetos de Negocio delegan a los DAO las
operaciones de almacenamiento y obtención de los datos.
DataSource
Este clase representa las implementación usada por un data source. Un data source
puede ser una base de datos relacional, una base de datos orientada a objetos, un repositorio
XML o un sistema de archivos planos entre otros.
Consecuencias
• Facilita la Transparencia
Los objetos de negocio pueden usar datos sin conocer los detalles específicos de la
implementación del origen de los datos. El acceso es transparente debido a que los detalles
de implementación se encuentran encapsulados dentro del Objeto de Acceso a Datos (DAO)
Una capa de Objetos de Acceso a Datos facilita a las aplicaciones el hecho de migrar a
diferentes bases de datos. Los objetos de negocio no tienen conocimiento de la
implementación subyacente de los datos. Así, al momento de realizar la migración solo se
consideran los cambios que deben realizarse a la capa de Acceso a Datos.
Debido a que todas las complejidades relacionadas con el acceso a los datos es realizado
por los Data Objects, todo el código relacionado con la implementación (por ejemplo
sentencias SQL) es colocado fuera de los Objetos de negocio, mejorando con ello la
legibilidad del código e incrementando la productividad de desarrollo.
Gracias a los Data Objects, la capa de acceso a datos puede ser vista como una capa que
puede aislar el resto de la aplicación de la implementación de los datos, incrementando con
ello la manejabilidad de la aplicación.
• Poca utilidad con Entity Beans con Persistencia Manejada por el Contenedor
(CMP)
Debido a que el contenedor de beans provee todos los servicios necesarios para el manejo
de datos persistente. Las Aplicaciones que usen beans de tipo CMP no necesitan Objetos de
Acceso a Datos, ya que el servidor de Aplicaciones donde se encuentre la aplicación provee
de forma transparente esta funcionalidad.
2. Service Activator
Contexto
Los Enterprise Java Beans (EJB) y otros servicios de negocios necesitan una forma de
ser activados de forma asíncrona sin intervención del usuario.
Problema
Fortalezas
- Los Enterprise Beans son mostrados a sus clientes por medio de sus interfaces remotas,
las cuales solo permite acceso sincrónico.
- El contenedor controla a los enterprise beans, permitiendo interacciones solo por medio
de referencias remotas. El contenedor EJB no permite acceso directo a la
implementación del bean o a sus métodos. Así, la implementación de un componente
“escucha” de mensajes en un Enterprise Bean no esta permitido ya que esto violaria las
especificaciones de EJB anteriores a la 2.0, ya que se estaria permitiendo un acceso
directo a la implementación del bean. La especificación de EJB 2.0 plantea un Nuevo
tipo de bean denominado Message-Driven Bean que permite el desarrollo de un
“manejador de mensajes”.
- Una aplicación necesita proveer un framework de publicación/suscripción en el cual los
clientes puedan publicar peticiones destinadas a los EJB, los cuales pueden procesar las
peticiones de un modo asíncrono.
- Los clientes necesitan capacidades de procesamiento asíncrono de los EJB y otros
componentes de negocio síncronos, con lo cual el cliente puede enviar una solicitud
para su procesamiento sin necesidad de esperar los resultados.
- Los clientes pueden usar las interfaces middleware “orientadas a mensajes” ofrecidas
por el Servicio de Mensajes de Java (JMS). Estas interfaces no están integradas en los
servidores EJB basados en especificaciones EJB anteriores a la 2.0.
- Proveer características similares a las de los procesos “demonio” permitiendo con esto
que un bean pueda permanecer inactivo hasta la ocurrencia de un evento o la llegada
de un Nuevo mensaje.
- Los Message Beans basados en la especificación 2.0 son beans de sesión sin estado, por
lo cual, no es posible realizar la invocación asincrónica de cualquier otro tipo de beans.
Solución
Usar un Service Activator para recibir peticiones y mensajes asincrónicos del cliente. Al
momento de la recepción de un mensaje, el Service Activator localiza e invoca los métodos de
negocios necesarios para completar las solicitudes de manera asincrónica.
Cualquier cliente que necesite invocar asincrónicamente un servicio, como por ejemplo
un enterprise bean, puede crear y enviar un mensaje al Service Activator. El Service Activator
recibe los mensajes y los analiza para interpretar la solicitud del cliente. Una vez que se ha
identificado la solicitud del cliente, se localizan componentes de negocio necesario para
satisfacer los requerimientos del cliente.
Estructura
Peticiones (Request)
Las peticiones son los mensajes creados por los clientes y enviados al Service Activator.
De acuerdo con la especificación de JMS, la petición es un objeto que implementa la interfaz
javax.jms.Message. El API de JMS muchos tipos de mensaje tales como:
TextMessage,ObjectMessage,etc, que pueden ser usados para generar peticiones.
ServiceActivator
La clase ServiceActivator es la clase principal de este patrón. Esta implementa la
interfaz javax.jms.MessageListener, la cual es definida por la especificación de JMS. La clase
ServiceActivator posee un método denominado onMessage() el cual es invocado cuando llega
un Nuevo mensaje. Posteriormente la clase analiza el mensaje para determinar que debe
hacerse para procesar la solicitud del usuario.
BusinessObject
Consecuencias
Antes de la especificación 2.0 de los EJB, no existía ningún tipo de integración entre los EJB
y los componentes JMS. Este patrón provee un medio para integrar JMS en una aplicación
que utilice EJBs, añadiendo además capacidades de procesamiento asíncrono. La
especificación 2.0 define un nuevo tipo de Bean de Sesión, denominado Message Bean, el
cual permite realizar la implementación de JMS con los EJB. Los Message Beans son
capaces de implementar la interfaz Message Listener y recibir mensajes de forma
asíncrona. En este caso, el Servidor de Aplicaciones tomaría el rol de Service Activator.
Usando el patrón Service Activator es possible proveer invocación asincrona en todos los
tipos de beans. Con ello, las aplicaciones no deben esperar por los resultados de todas sus
peticiones para continuar con sus funciones habituales.
• Estandarización de Procesos