Sunteți pe pagina 1din 179

Catlogo de Patrones de Diseo J2EE. I.

- Capa de Presentacin
Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Puedes encontrar la versin original de este tutorial en Ingls en: http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html

Introduccin a los Patrones o Qu es un Patrn? o Abstraccin de Patrones o Identificar un Patrn o Patrones contra Estrategias o El Catlogo de Patrones J2EE (Core J2EE Patterns) Plantilla de Patrn Intercepting Filter o Contexto o Problema: o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados Front Controller o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados View Helper o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados Composite View o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados Service to Worker o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades

Estrategias Consecuencias Cdigo de Ejemplo Patrones Relacionados Dispatcher View o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

o o o

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Introduccin a los Patrones o Qu es un Patrn? o Abstraccin de Patrones o Identificar un Patrn o Patrones contra Estrategias o El Catlogo de Patrones J2EE (Core J2EE Patterns)

Introduccin a los Patrones


Qu es un Patrn?
Algunas personas definen un patrn como una solucin recurrente para un problema en un contexto. Estos trminos -- contexto, problema y solucin -- merecen una pequea explicacin. Primero, qu es un contexto? Un contexto es el entorno, situacin, o condiciones interrelacionadas dentro de las cuales existe algo. Segndo, qu es un problema? Un problema es una cuestin insatisfecha, algo que se necesita investigar y resolver. Un problema se puede especificar mediante un conjunto de causas y efectos. Normalmenete un problema est restringido al contexto en el que ocurre. Finalmente, la solucin se refiere a la respuesta al problema dentro de un contexto que ayuda a resolver las dificultades. Entonces, si tenemos una solucin a un problema en un contexto, es un patrn? No necesariamente. Tambin necesitamos asociar la caracterstica de recurrencia con la definicin de un patrn. Eso es todo? Quizs no. Los patrones deberan comunicar soluciones de diseo a los desarrolladores y arquitectos que los leen y los utilizan. Como puedes ver, aunque el concepto de patrn es bastante simple, definir realmente el trmino es muy complejo. Hemos sealado slo las referencias para que puedas indagar en ms profundidad en la historia de los patrones y aprender sobre ellos en otras reas. Sin embargo, deberas tener en mente que la definicin de patrn que hemos adoptado funciona. En nuestro catlogo, se describe un patrn de acuerdo a sus principales caractersticas: contexto, problema y solucion, junto con otros aspectos importantes, como causas y consecuencias. La pgina que describe la plantilla de patrones explica estas caractersticas en ms detalle.

Abstraccin de Patrones
Un patrn describe, con algn nivel de abtrasccin, una solucin experta a un problema. Normalmente, un patrn est documentado en forma de una plantilla. Aunque es una prctica estndar documentar los patrones en un formato de plantilla especializado, esto no significa que sea la nica forma de hacerlo. Adems, hay tantos formatos de plantillas como autores de patrones, esto permite la creatividad en la documentacin de patrones. Los patrones solucionan problemas que existen en muchos niveles de abstraccin. Hay patrones que describen soluciones para todo, desde el anlisis hasta el diseo y desde la arquitectura hasta la implementacin. Adems, los patrones existen en diversaa reas de inters y tecnologas. Por ejemplo, hay un patrn que describe como trabajar con un lenguaje de programacin especfico o un segmento de la industria especfico, como la sanidad.

Identificar un Patrn
Se han manejado muchos proyectos J2EE en Sun Java Center, y, con el tiempo, se ha notado que ocurren problemas similares en todos estos proyectos. Tambin se ha visto que han emergido soluciones similares para todos estos problemas. Aunque las estrategias de implementacin variaran, las soluciones generales eran bastante similares.

Cuando se ha visto un problema y una solucin recurrentes, se ha intentado identificar y documentar sus caractersticas usando la plantilla de patrn. Los candidatos a patrones no se han aadido al catlogo de patrones hasta que no se ha podido observar y documentar su utilizacin varias veces en diferentes proyectos. Tambin se emprendi el procesamiento de significado de los patrones buscando patrones en soluciones ya implementadas. Luego, hay una "Regla de Tres", como se la conoce en la comunidad de los patrones. Esta regla es una gui para ascender un patrn candidato al catlogo de patrones. De acuerdo a esta regla, una solucin permanece como un patrn candidato hasta que se ha verificado en al menos tres sistemas diferentes. Ciertamente que hay mucho espacio para la interpretacin en reglas como sta, pero ayudan a proporcionar un contexto para la identificacin de patrones. Muchas veces, soluciones similares podran representar un slo patrn. Cuando se decide cmo formar un patrn, es importante considerar cual es la mejor forma de comunicar la solucin. Algunas veces, un nombre indenpendiente mejora la comunicacin entre los desarrolladores. Si es as, es mejor considerar la documentacin de dos soluciones similares como dos patrones diferentes. Por otro lado, podra ser mejor comunicar la solucin destilando las ideas similares en una combinacin de patrn/estrategia.

Patrones contra Estrategias


Cuando se empez a documentar los patrones J2EE, se tom la decisin de documentarlos con un nivel de abstraccin relativamente alto. Al mismo tiempo, cada patrn incluye varias estrategias que proporcionan detalles de su implementacin a bajo nivel. A travs de las estrategias, cada patrn documenta una solucin con varios niveles de abstraccin. Se ha reconocido que se podra haber documentado algunas de estas estrategias como patrones por s mismas. Sin embargo, se ha credo que la estructura de plantilla actual comunica ms claramente la relacin de las estrategias con la estructura de patrn de alto nivel en que se ha incluido. Se han anotado algunos de los problemas con respecto a la relacin entre las estrategias y los patrones:

Los patrones existen a un nivel de abstraccin ms alto que las estrategias. Los patrones incluyen implementaciones ms comunes o ms recomendadas que las estrategias. Las estrategias proporcionan un punto de extensibilidad para cada patrn. Los desarrolladores descubren e inventan nuevas formas de implementar patrones, produciendo nuevas estrategias para patrones bien-conocidos. Las estrategias promueven una mejor comunicacin, proporcionando nombres para aspectos de bajo nivel de una solucin particular.

El Catlogo de Patrones J2EE (Core J2EE Patterns)


Abajo puedes ver una representacin grfica del Catlogo de Patrones Principales de J2EE (Core J2EE Patterns):

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Plantilla de Patrn

Plantilla de Patrn
Los patrones J2EE se han estructurado de acuerdo a una plantilla de patrn definida. Cada seccin de la plantilla de patrn contribuye a entender el patrn particular. Tambin observars que se ha intentado dar un nombre de patrn descriptivo a cada patrn J2EE. Aunque es dificil acompasar un patrn singular con su nombre, se ha intentado que los nombres de patrn proporcionen suficiente informacin sobre la funcin del patrn. Se ha adoptado una plantilla de patrn que consta de las siguientes secciones:

Contexto: Conjunto de entornos bajo los cuales existe el patrn. Problema: Describe los problemas de diseo que se ha encontrado el desarrollador. Causas: Lista los razones y motivos que afectan al problema y la solucin. La lista de causas ilumina las razones por las que uno podra haber elegido utilizar el patrn y proporciona una justificacin de su uso. Solucin: Describe brevemente la solucin y sus elementos en ms detalle. La seccin de la solucin contiene dos sub-secciones: o Estructura: Utiliza diagramas de clases UML para mostrar la estructura bsica de la solucin. Los diagramas de secuencias UML de esta seccin presentan los mecanismos dinmicos de la solucin. Hay una explicacin detalladas de los participantes y las colaboraciones. o Estrategias: Describe diferentes formas en las que se podra implementar el patrn. Consecuencias: Aqu se describen las compensaciones del patrn, esta seccin se enfoca en los resultados de la utilizacin de un patrn en particular o de su estrategia, y anota los pros y los contras que podran resultar de la aplicacin del patrn. Patrones Relacionados: Esta seccin lista otros patrones relevantes en el catlogo de patrones J2EE u otros recursos externos, como los patrones de diseo GoF. Por cada patrn relacionado, hay una breve descripcin de su relacin con el patrn que se est describiendo.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Intercepting Filter o Contexto o Problema: o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados

Intercepting Filter
Contexto
El mecanismo de manejo de peticiones de la capa de presentacin recibe muchos tipos diferentes de peticiones, cada uno de los cuales requiere varios tipos de procesamiento. Algunas peticiones simplemente requieren su reenvio al componente manejador apropiado, mientras que otras peticiones deben ser modificadas, auditadas, o descomprimidas antes de su procesamiento posterior.

Problema:
Se requiere un pre-procesamiento y un post-procesamiento de unas peticiones o respuestas de un cliente Web. Cuando una peticin entra a una aplicacin Web, normalmente debe pasar varios test de entrada antes del estado de procesamiento principal. Por ejemplo,

Se ha autentificado el cliente? Tiene el cliente una sesin vlida? La direccin IP del cliente es de una red conocida? Viola alguna restriccin el path de la peticin? Qu codificacin usa el cliente para enviar los datos? Soportamos el tipo de navegador del cliente?

Algunos de estos chequeos son tests, que resultan en una respuesta de si o no que determina si continuar el procesamiento. Otros chequeos manipulan el stream de datos entrantes a una forma aceptable para el procesamiento. La solucin bsica consiste en un serie de chequeos condicionales, si cualquiera de ellos falla la peticin se aborta. Las sentencias if/else anidadas son una estrategia estndar, pero esta solucin tiene fragilidad de cdigo y un estilo de programacin de copiar-y-pegar, porque el flujo del filtrado y la accin de los filtros se compila dentro de la aplicacin. La clave para solventar este problema de una forma flexible y no obstrusiva es tener un mecanismo simple para aadir y eliminar componentes de procesamiento, en el que cada componente completa una accin de filtrado especfica.

Causas

Procesamiento comn, como un chequeo del esquema de codificacin de datos o la informacin de login de cada peticin, completo por cada peticin.

Se desea la centralizacin de la lgica comn. Se debera facilitar la adicin o eliminacin de sevicios sin afectar a los componentes existentes, para que se puedan utilizar en gran variedad de combinaciones, como o Logging y autentificacin. o Depuracin y transformacin de la salida para un cliente especfico o Descomprensin y conversin del esquema de codificacin de la entrada.

Solucin
Crear filtros conectables para procesar servicios comunes de una forma estndar sin requerir cambios en el cdigo principal del procesamiento de la peticin. Los filtros interceptan las peticiones entrantes y las respuestas salientes, permitiendo un pre y post-procesamiento. Podemos aadir y eliminar estos filtros a discreccin, sin necesitar cambios en nuestro cdigo existente. Podemos, en efecto, decorar nuestro procesamiento principal con una veriedad de servicios comunes, como la seguridad, el logging, el depurado, etc. Estos filtros son componentes independientes del cdigo de la aplicacin principal, y pueden aadirse o eliminarse de forma declarativa. Por ejemplo, se podra modificar un fichero de configuracin de despliegue para configurar una cadena de filtros. Cuando un cliente pide un recurso que corresponde con este mapeo de URL configurado, se procesa cada filtro de la cadena antes de poder invocar el recurso objetivo.

Estructura
La siguiente figura representa el diagrama de clases del patrn Intercepting Filter.

Participantes y Responsabilidades
La siguiente figura representa el diagrama de la secuencia del patrn Intercepting Filter.

FilterManager
El FilterManager maneja el procesamiento de filtros. Crea el FilterChain con los filtros apropiados, en el orden correcto e inicia el procesamiento.

FilterChain
El FilterChain es una collection ordenada de filtros indenpendientes.

FilterOne, FilterTwo, FilterThree


Estos son los filtros individuales que son mapeados a un objetivo. El FilterChain coordina su procesamiento.

Target
El Target es el recurso que el cliente ha solicitado.

Estrategias

Custom Filter
El filtro se implementa mediante una estrategia personalizada definida por el desarrollador. Esto es menos flexible y menos poderoso que la preferida Estrategia de Filtro Estndar que veremos en la siguiente seccin y que slo est disponible en contenedores que soporten la especificacin servlet 2.3. La estrategia de filtro personalizado es menos poderosa porque no puede proporcionar una envoltura para los objetos request y response de una forma estndar y portable. Adems, el objeto request no se puede modificar, y se debe introducir alguna suerte de mecanismo de buffer si los filtros son para controlar los streams de salida. Para implementar esta estrategia, el desarrollador podra utilizar el patrn Decorator

[GoF] para envolver los filtros alrededor de la lgica principal del procesamiento de la peticin. Por ejemplo, podra haber un filtro de depuracin que envuelva un filtro de autentificacin. Los siguientes fragmentos de cdigo muestran como se podran crear estos mecanismos de forma programtia: DebuggingFilter:
public class DebuggingFilter implements Processor { private Processor target; public DebuggingFilter(Processor myTarget) { target = myTarget; } public void execute(ServletRequest req, ServletResponse res) throws IOException, ServletException { //Do some filter processing here, such as // displaying request parameters target.execute(req, res); } }

CoreProcessor:

public class CoreProcessor implements Processor { private Processor target; public CoreProcessor() { this(null); } public CoreProcessor(Processor myTarget) target = myTarget; } {

public void execute(ServletRequest req, ServletResponse res) throws IOException, ServletException { //Do core processing here } }

En el controlador servlet, hemos delegado en un mtodo llamado processRequest para manejar las peticiones entrantes:

public void processRequest(ServletRequest req, ServletResponse res) throws IOException, ServletException { Processor processors = new DebuggingFilter( new AuthenticationFilter(new CoreProcessor())); processors.execute(req, res); //Then dispatch to next resource, which is probably // the View to display dispatcher.dispatch(req, res); }

Slo para propsitos de ejemplo, imagina que cada componente de procesamiento escribe en la salida estndar cuando se ejecuta. El siguiente ejemplo muestra la posible salida de la ejecucin:
Debugging filter preprocessing completed... Authentication filter processing completed... Core processing completed... Debugging filter post-processing completed...

Se ejecuta una cadena de procesadores en orden. Cada procesador, excepto el ltimo de la cadena, se considera un filtro. En el componente procesador final es donde se encapsula el procesamiento principal que queremos completar para cada peticin. Con este diseo, necesitaremos cambiar el cdigo de la clase CoreProcessor, as como cualquier clase de filtro, cuando querramos modificar la forma de manejar las peticiones. La siguiente figura muestra un diagrama de secuencia que describe el flujo de control cuando se utiliza el cdigo de filtro de los ejemplos anteriores:

Observa que cuando usamos una implementacin de Decorator, cada filtro invoca directamente al siguiente filtro, aunque usando un interface genrico. De forma alternativa, esta estrategia se puede implementar utilizando un FilterManager y un FilterChain. En este caso, estos componentes manejan el procesamiento de los filtros y los filtros individuales no se comunican con ningn otro filtro directamente. Este diseo se aproxima al de una implementacin compatible con Servlet 2.3, aunque an as es una estrategia personalizada. En el primero de los siguientes listado veremos la clase FilterManager que crea un objeto FilterChain.
public class FilterManager { public void processFilter(Filter target, javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { FilterChain filterChain = new FilterChain(); // The filter manager builds the filter chain here // if necessary // Pipe request through Filter Chain filterChain.processFilter(request, response); //process target resource target.execute(request, response); } }

El FilterChain aade filtros a la cadena en el orden apropiado (por brevedad lo hemos hecho en el constructor, pero normalmente se hara en el lugar del comentario), procesa los filtros, y finalmente procesa el recurso objetivo:
public class FilterChain { // filter chain private Vector myFilters = new Vector(); // Creates new FilterChain public FilterChain() { // plug-in default filter services for example // only. This would typically be done in the // FilterManager, but is done here for example // purposes addFilter(new DebugFilter()); addFilter(new LoginFilter()); addFilter(new AuditFilter()); } public void processFilter( javax.servlet.http.HttpServletRequest request,

javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, java.io.IOException { Filter filter; // apply filters Iterator filters = myFilters.iterator(); while (filters.hasNext()) { filter = (Filter)filters.next(); // pass request & response through various // filters filter.execute(request, response); } } public void addFilter(Filter filter) myFilters.add(filter); } } {

En la siguiente figura podemos ver el diagrama de secuencia de este cdigo:

Esta estrategia no nos permite crear filtros que sean tan flexibles y poderosos como nos gustara. Por una cosa, los filtros se aade y eliminan programticamente. Aunque podramos escribir un mecanismo propietario para manejar la adicin y eliminacin de filtros mediante un fichero de configuracin, an no tendramos ninguna forma de envolver los objetos request y response. Adems, sin un mecanismo de buffer sofisticado, esta estrategia no proporcionar post-procesamiento flexible. La Estrategia de Filtro Estndar proporciona soluciones para estos problemas, utilizando caractersticas de la especificacin Servlet 2.3, que proporciona una solucin estndar al dilema de los filtros.

Standard Filter
Los filtros se controlan de forma declarativa utilizando un descriptor de despliegue, segn se describe en la especificacin Servlet 2.3. Esta especificacin incluye un mecanismo estndar para construir cadenas de filtos y poder aadir y eliminar filtros de esa cadena de forma transparente. Los filtros se contruyen sobre interfaces, y se aaden o eliminan de una forma declarativa modificando el descriptor de despliegue de una aplicacin Web. Nuestro ejemplo para esta estrategia ser crear un filtro que preprocese peticiones de cualquier tipo de codificacin como las que podramos manejar en el cdigo principal de manejo de peticiones. Por qu podra ser esto necesario? Los formularios HTML que incluyen un upload de ficheros utilizan un tipo de codificacin diferente a la mayora de formularios. As, los datos del formulario que acompaan al upload

no estn disponibles mediante simples llamadas a getParameter(). Por eso, creamos dos filtros que preprocesen las peticiones, traduciendo todos los tipos de codificacin en un slo formato consistente. El formato que elegimos es hacer que todos los datos del formulario estn disponibles como atributos de la peticin. Un fitlro maneja la forma de codificacin estndar para el tipo application/x-www-form-urlencoded y el otro maneja el tipo de codificacin menos comn multipart/form-data, que se utiliza en los formularios que incluyen uploads. Los filtros traducen todos los datos del formulario en atributos de la peticin, para que el mecanismo principal de manejo de peticiones pueda trabajar con todas las peticiones de la misma manera. en lugar de hacerlo con los casos especiales de las diferentes codificaciones. El siguiente ejemplo muestra un filtro que traduce las peticiones utilizando el esquema de codificacin de formularios estndar:
public class StandardEncodeFilter extends BaseEncodeFilter { // Creates new StandardEncodeFilter public StandardEncodeFilter() { } public void doFilter(javax.servlet.ServletRequest servletRequest,javax.servlet.ServletResponse servletResponse,javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { String contentType = servletRequest.getContentType(); if ((contentType == null) || contentType.equalsIgnoreCase( "application/x-www-form-urlencoded")) { translateParamsToAttributes(servletRequest, servletResponse); } filterChain.doFilter(servletRequest, servletResponse); } private void translateParamsToAttributes( ServletRequest request, ServletResponse response) { Enumeration paramNames = request.getParameterNames(); while (paramNames.hasMoreElements()) String paramName = (String) paramNames.nextElement(); String [] values; values = request.getParameterValues(paramName); System.err.println("paramName = " + paramName); if (values.length == 1) request.setAttribute(paramName, values[0]); else request.setAttribute(paramName, values); } } } {

El ejemplo siguiente muestra el filtro que maneja las traduciones de las peticiones que utilizan el esquema de codificacin multipart.:

public class MultipartEncodeFilter extends BaseEncodeFilter { public MultipartEncodeFilter() { } public void doFilter(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse,javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { String contentType = servletRequest.getContentType(); // Only filter this request if it is multipart // encoding if (contentType.startsWith( "multipart/form-data")){

try { String uploadFolder = getFilterConfig().getInitParameter( "UploadFolder"); if (uploadFolder == null) uploadFolder = "."; /** The MultipartRequest class is: * Copyright (C) 2001 by Jason Hunter * <jhunter@servlets.com>. All rights reserved. **/ MultipartRequest multi = new MultipartRequest(servletRequest, uploadFolder, 1 * 1024 * 1024 ); Enumeration params = multi.getParameterNames(); while (params.hasMoreElements()) { String name = (String)params.nextElement(); String value = multi.getParameter(name); servletRequest.setAttribute(name, value); } Enumeration files = multi.getFileNames(); while (files.hasMoreElements()) { String name = (String)files.nextElement(); String filename = multi.getFilesystemName(name); String type = multi.getContentType(name); File f = multi.getFile(name); // At this point, do something with the // file, as necessary } } catch (IOException e) { LogManager.logMessage( "error reading or saving file"+ e); } } // end if filterChain.doFilter(servletRequest, servletResponse); } // end method doFilter() }

El cdigo de estos filtros se basa en la especificacin servlet 2.3. Tambin se usa un filtro base, desde el que descienden estos dos filtros. El filtro base mostrado en el siguiente ejemplo proporciona el comportamiento por defecto para los mtodos de retrollamada del filtro estndar:
public class BaseEncodeFilter implements javax.servlet.Filter { private javax.servlet.FilterConfig myFilterConfig; public BaseEncodeFilter() { }

public void doFilter( javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { filterChain.doFilter(servletRequest, servletResponse); } public javax.servlet.FilterConfig getFilterConfig() { return myFilterConfig; } public void setFilterConfig( javax.servlet.FilterConfig filterConfig) { myFilterConfig = filterConfig; } }

Abajo tenemos un extracto del descriptor de despliegue de la aplicacin Web que contiene este ejemplo. Muestra cmo se registran estos dos filtros y luego los mapea a un recurso, en este caso un sencillo servlet de prueba.

. . .

<filter> <filter-name>StandardEncodeFilter</filter-name> <display-name>StandardEncodeFilter</display-name> <description></description> <filter-class> corepatterns.filters.encodefilter. StandardEncodeFilter</filter-class> </filter> <filter> <filter-name>MultipartEncodeFilter</filter-name> <display-name>MultipartEncodeFilter</display-name> <description></description> <filter-class>corepatterns.filters.encodefilter. MultipartEncodeFilter</filter-class> <init-param> <param-name>UploadFolder</param-name> <param-value>/home/files</param-value> </init-param> </filter> . . . <filter-mapping> <filter-name>StandardEncodeFilter</filter-name> <url-pattern>/EncodeTestServlet</url-pattern> </filter-mapping> <filter-mapping> <filter-name>MultipartEncodeFilter</filter-name> <url-pattern>/EncodeTestServlet</url-pattern> </filter-mapping> . . .

En la siguiente figura podemos ver el diagrama de secuencia de este ejemplo:

Los filtros StandardEncodeFilter y MultiPartEncodeFilter interceptan el control cuando un cliente hace una peticin al servlet controlador. El contenedor acepta el rol de manejador de filtros y conduce el control a estos filtros llamando a sus mtodos doFilter. Despus de completar su procesamiento, cada filtro pasa el control al FilterChain que lo contiene, que est instruido para ejecutar el siguiente filtro. Una vez que el control ha pasado por los dos filtros, el siguiente componente en recibir el control es el recurso objetivo real, en este caso el servlet controlador. Los filtros, segn lo soporta la especificacin Servlet 2.3, tambin soportan la envoltura de los objetos y response. Esta caracterstica proporciona un mecanismo mucho ms podereos que el que se puede construir utilizando la implementacin personlizada de la seccin anterior. Por supuesto, tambin podramos construir una aproximacin hbrida combinando las dos estrategias.

request

Base Filter

Un filtro base sirve como una superclase comn para todos los filtros. Las caractersticas comunes se pueden encapsular en el filtro base y se pueden compartir entre todos los filtros. Por ejemplo, un filtro base es un buen lugar para incluir el comportamiento por defecto de los mtodos de retrollamada del contenedor, como hemos visto en la seccin anterior. El siguiente fragmento de cdigo nos muestra cmo hacer esto:
public class BaseEncodeFilter implements javax.servlet.Filter { private javax.servlet.FilterConfig myFilterConfig; public BaseEncodeFilter() { }

public void doFilter(javax.servlet.ServletRequest servletRequest,javax.servlet.ServletResponse servletResponse, javax.servlet.FilterChain filterChain) throws java.io.IOException, javax.servlet.ServletException { filterChain.doFilter(servletRequest, servletResponse); } public javax.servlet.FilterConfig getFilterConfig() { return myFilterConfig; } public void setFilterConfig(javax.servlet.FilterConfig filterConfig) { myFilterConfig = filterConfig; } }

Template Filter
Usar un filtro base del que descienden todos los dems permite a la clase base proporcionar la funcionalidad de Plantilla de Mtodos [GoF]. En este caso, el filtro base se utiliza para dictar los pasos generales que debe completar cada filtro, aunque deja las especifidades de cmo completar esos pasos en la subclase de cada filtro. Normalmente, esto se definira de forma burda, mtodos bsicos que simplemente imponen una estructura limitada a cada plantilla. Esta estrategia tambin se puede combinar con cualquier otra estrategia de filtros. Los siguientes listados muestran como utilizar esta estrategia con la Estrategia de Filtro Declarado:
public abstract class TemplateFilter implements javax.servlet.Filter { private FilterConfig filterConfig; public void setFilterConfig(FilterConfig fc) { filterConfig=fc; } public FilterConfig getFilterConfig() return filterConfig; } {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Common processing for all filters can go here doPreProcessing(request, response, chain); // Common processing for all filters can go here doMainProcessing(request, response, chain); // Common processing for all filters can go here doPostProcessing(request, response, chain); // Common processing for all filters can go here // Pass control to the next filter in the chain or // to the target resource chain.doFilter(request, response); } public void doPreProcessing(ServletRequest request, ServletResponse response, FilterChain chain) { } public void doPostProcessing(ServletRequest request, ServletResponse response, FilterChain chain) { }

public abstract void doMainProcessing(ServletRequest request, ServletResponse response, FilterChain chain); }

Dando esta definicin de clase para TemplateFilter, cada filtro se implementa como una subclase que slo debe implementar el mtodo doMainProcessing. Estas subclases tienen la opcin de implementar los otros tres mtodos si lo desean. Abajo tenemos un ejemplo de una subclase que implementa el mtodo obligatorio (dictado por nuestra plantilla de filtro) y el mtodo de preprocesamiento opcional.
public class DebuggingFilter extends TemplateFilter { public void doPreProcessing(ServletRequest req, ServletResponse res, FilterChain chain) { //do some preprocessing here } public void doMainProcessing(ServletRequest req, ServletResponse res, FilterChain chain) { //do the main processing; } }

En la siguiente figura podemos ver el diagrama de secuencia de esta estrategia:

En el diagrama de secuencia, las subclases, como DebuggingFilter, definen el procesamiento sobreescribiendo el mtodo abstracto doMainProcessing, y, opcionalmente, doPreProcessing y doPostProcessing. As, la plantilla de filtro impone una estructura para el procesamiento de todos los filtros, as como proporciona un lugar para encapsular el cdigo que es comn para cada filtro.

Consecuencias

Centraliza el Control con Controladores de Acoplamiento Ligero Los filtros proporcionan un lugar centralaizado para controlar el procesamiento a travs de mltiples peticiones, como lo hace el controlador. Los filtros estn mejor preparados para manejar las peticiones y respuestas para el control ltimo por un recurso objetivo, como un controlador. Adems, un controlador frecuentemente junta el control de numerosos sevicios comunes y no relacionados, como la autentificacin, el login, la encriptacin, etc., mientras que los filtros nos permiten controladores de acoplamiento ms ligero, que se pueden combinar. Mejora la Reutilizacin Los filtros promueven la limpieza del particionamiento de la aplicacin y aconsejan su reutilizacin. Estos interceptores conectables se aaden y eliminan al cdigo existente de forma

transparente y debido a su interface estndar, funcionan en cualquier combinacin y son reutilizables por varias presentaciones. Configuracin Declarativa y Flexible Se pueden combinar numerosos servicios en varias permutaciones sin tener que recompilar ni una sola vez el cdigo fuente. La Comparticin Informacin es Ineficiente Compartir informacin entre filtros puede ser ineficiente, porque por definicin todo filtro tiene acoplamiento ligero. Si se deben compartir grandes cantidades de informacin entre los filtros, esta aproximacin podra ser muy costosa.

Patrones Relacionados

Front Controller El controlador resuelve algunos problemas similares, pero est mejor diseado para manejar el procesamiento principal. Decorator [GoF] El patrn Intercepting Filter est relacionado con el patrn Decorator, que proporciona envolturas conectables dinmicamente. Template Method [GoF] El patrn de Plantillas de Mtodos se utiliza para implementar la Estrategia de Plantilla de Filtros. Interceptor [POSA2] El patrn Intercepting Filter est relacionado con el patron Interceptor, que permite que se pueden aadir servicios de forma transparente y dispararlos automticamente. Pipes and Filters [POSA1] El patrn Intercepting Filter est relacionado con el patrn Pipes and Filters.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Front Controller o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados

Front Controller
Contexto
El mecanismo de manejo de peticiones de la capa de presentacin debe controlar y coordinar el procesamiento de todos los usuarios a travs de varias peticiones. Dichos mecanismos de control se pueden manejar de una forma centralizada o descentralizada.

Problema
El sistema requiere un punto de acceso centralizado para que el manejo de peticiones de la capa de presentacin soporte la integracin de los servicios del sistema, recuperacin de contenidos, control de vistas, y navegacin. Cuando el usuario accede a la vista directamente sin pasar un mecanismo centralizado, podran ocurrir dos problemas:

Se requiere que cada vista proporcione sus propios servicios del sistema, lo que normalmente resulta en duplicacin de cdigo. La vista de navegacin se deja a los visores. Esto podra resultar en una mezcla de contenidos y navegacin.

Adems, el control distribuido es ms difcil de mantener, ya que los cambios se tienen que realizar en numerosos lugares.

Causas

El procesamiento de servicios del sistema comunes se completa por cada peticin. Por ejemplo, el servicio de seguridad completa los chequeos de autentificacin y autorizacin. La lgica se maneja mejor en una localizacin central en lugar de estar replicada dentro de varias vistas. Existen puntos de decisin con respecto a la recuperacin y manipulacin de los datos. Se utilizan varias vistas para responder a peticiones de negocio similares. Puede ser muy til un punto de contacto centralizado para manejar una peticin, por ejemplo, para controlar y grabar el camino de un usuario por la site. Los servicios del sistema y la lgica de control de vistas son relativamente sofisticados.

Solucin
Usar un controlador como el punto inicial de contacto para manejar las peticiones. El controlador maneja el control de peticiones, incluyendo la invocacin de los servicios de seguridad como la autentificacin y autorizacin, delegar el procesamiento de negocio, controlar la eleccin de una

vista apropiada, el manejo de errores, y el control de la seleccin de estrategias de creacin de contenido. El controlador proporciona un punto de entrada centralizado que controla y maneja las peticiones Web. Centralizando los puntos de decisin y control, el controlador tambin ayuda a reducir la cantidad de cdigo Java, llamadas a scriptles, embebidos en la pgina JavaServer Pages (JSP). Centralizar el control en el controlador y reduciendo la lgica de negocios en la vista permite reutilizar el cdigo entre peticiones. Es una aproximacin preferible a la alternativa de embeber cdigo en varias vistas porque esta aproximacin trata con entornos ms propensos a errores, y de reutilizacin del tipo copiar-y-pegar. Tpicamente, un controlador se coordina con un componente dispatcher. Los dispatchers son responsable del control de la vista y de la navegacin. As, un dispatcher elige la siguiente vista por el usuario y dirige el control al recurso. Los dispatchers podran encapsularse directametne dentro del controlador o se puede extraer en un componente separado. Aunque el patrn Front Controller sugiere la centralizacin del manejo de peticiones, no limita el nmero de manejadores en el sistema, como lo hace Singleton. Una aplicacin podra utilizar varios controladores en un sistema, cada uno mapeado a un conjunto de servicios distintos.

Estructura
La siguiente figura representa el diagrama de clases del patrn Front Controller.

Participantes y Responsabilidades
La siguiente figura representa el diagrama de la secuencia del patrn Front Controller. Muestra como el controlador maneja una peticin:

Controller
El controlador es el punto de contacto inicial para manejar todas las peticiones en el sistema. El controlador podra delegar a un helper para completar la autentificacin y la autorizacin de un usuario o para iniciar la recuperacin de un contacto.

Dispatcher
Un dispatcher es el responsable del manejo de la vista y de la navegacin, controlando la eleccin de la siguiente vista que se le presentar al usuario, y proporcionando el mecanismo para dirigir el control a ese recurso. Un dispatcher se puede encapsular dentro de un controlador o se puede separar en otro componente que trabaja de forma coordinada. El dispatcher puede proporcionar un re-envo esttico de la vista o un mecanismo de re-envo ms sofisticado. El dispatcher utiliza un objeto RequestDispatcher (soportado en la especificacin Servlet) y encapsula algn procesamiento adicional.

Helper
Un helper es el responsable de ayudar a la vista o al controlador a completar su procesamiento. As, los helpers tienen muchas responsabilidades, incluyendo la recopilacin de los datos requeridos por la vista y el almacenamiento en el modelo intermedio, en cuyo caso algunas veces nos podemos referir al helper como un bean de valor. Adems, los helpers pueden adaptar este modelo de datos para usarlo en la vista. Una vista podra trabajar con cualquier nmero de helpers, que normalmente son componentes JavaBeans (JSP 1.0+) y etiquetas personalizadas (JSP 1.1+). Adems, un helper podra representar un objeto Command o un Transformador XSL, que se utiliza en combinacin con una hoja de estilos para adaptar y convertir el modelo a la forma apropiada.

View
Una Vista representa y muestra informacin al cliente. La vista recupera informacin desde el modelo. Los helpers soportan las diferentes vistas encapsulando y adaptanto el modelo de datos subyacente para usarlo en el display.

Estrategias
Hay varias estrategias para implementar un controlador.

Servlet Front
La estrategia de Servlet Frontal sugiere la implementacin del controlador como un servlet. Aunque semnticamente equivalente, es mejor que la Estrategia de JSP Frontal. El controlador maneja los aspectos del manejo de peticiones que estn relacionados con el procesamiento de negocio y el control de flujo. Estas responsabilidades estn relacionadas con, pero son lgicamente independientes, del formateo de display, y es ms apropiado encapsularlas en un servlet en lugar de en una pgina JSP. Esta estrategia tiene algunos potenciales inconvenientes. En particular, no permite utilizar algunas de las utilidadess del entorno de ejecucin JSP, como es el relleno automtico de parmetros de la peticion. Afortunadamente, este inconveniente es mnimo porque es relativamente fcil crear u obtener utilidades similares para su uso general. Abajo podemos ver un ejemplo de la Estrategia Servlet Front:

public class EmployeeController extends HttpServlet { // Initializes the servlet. public void init(ServletConfig config) throws ServletException { super.init(config); } // Destroys the servlet. public void destroy() { } /** Processes requests for both HTTP * <code>GET</code> and <code>POST</code> methods. * @param request servlet request * @param response servlet response */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { String page; /**ApplicationResources provides a simple API * for retrieving constants and other * preconfigured values**/ ApplicationResources resource = ApplicationResources.getInstance(); try { // Use a helper object to gather parameter // specific information. RequestHelper helper = new RequestHelper(request); Command cmdHelper= helper.getCommand(); // Command helper perform custom operation page = cmdHelper.execute(request, response); } catch (Exception e) { LogManager.logMessage( "EmployeeController:exception : " + e.getMessage()); request.setAttribute(resource.getMessageAttr(), "Exception occurred : " + e.getMessage()); page = resource.getErrorPage(e); } // dispatch control to view dispatch(request, response, page); } /** Handles the HTTP <code>GET</code> method.

* @param request servlet request * @param response servlet response */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Handles the HTTP <code>POST</code> method. * @param request servlet request * @param response servlet response */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Returns a short description of the servlet */ public String getServletInfo() { return "Front Controller Pattern" + " Servlet Front Strategy Example"; } protected void dispatch(HttpServletRequest request, HttpServletResponse response, String page) throws javax.servlet.ServletException, java.io.IOException { RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(page); dispatcher.forward(request, response); } }

JSP Front
La estrategia de JSP Frontal sugiere la implementacin del controlador como una pgina JSP. Aunque semnticamente equivalente, es mejor utilizar la Estrategia de Servlet Frontal. Como el controlador maneja el procesamiento que no est especificamente relacionado con el formateo de la salida, no tiene sentido implementar este componente como una pgina JSP. La implementacin del controlador como una pgina JSP tiene otra razn para no ser la preferida: Requiere que un desarrollador de software trabaje con una pgina de etiquetas para poder modificar la lgica del control de peticiones. El siguiente listado es un ejemplo de esta estrategia:

<%@page contentType="text/html"%> <%@ page import="corepatterns.util.*" %> <html> <head><title>JSP Front Controller</title></head> <body> <h3><center> Employee Profile </h3> <% /**Control logic goes here... At some point in this code block we retrieve employee information, encapsulate it within a value object and place this bean in request scope with the key "employee". This code has been omitted. We either dispatch to another JSP at this point or simply allow the remaining portions of scriptlet code to execute**/ %> <jsp:useBean id="employee" scope="request" class="corepatterns.util.EmployeeTO"/> <FORM method=POST > <table width="60%"> <tr> <td> First Name : </td> <td> <input type="text" name="<%=Constants.FLD_FIRSTNAME%>" value="<jsp:getProperty name="employee" property="firstName"/>"> </td> </tr> <tr> <td> Last Name : </td> <td> <input type="text"

name="<%=Constants.FLD_LASTNAME%>" value="<jsp:getProperty name="employee" property="lastName"/>"></td> </tr> <tr> <td> <td> Employee ID : </td> <input type="text" name="<%=Constants.FLD_EMPID%>" value="<jsp:getProperty name="employee" property="id"/>"> </td>

</tr> <tr> <td>

<input type="submit" name="employee_profile"> </td> <td> </td> </tr> </table> </FORM> </body> </html>

Command and Controller


Basada en el patrn Commando de [GoF], la estrategia de Commando y Controlador sugiere proporcionar un interface genrico para los componentes helper en los que el controlador podra delegar responsabilidades, minimizando el acoplamiento entre estos componentes. Aadir o modificar el trabajo que necesitan realizar estos helpers no requiere ningn cambio en el interface entre el controlador y ellos, sino en el tipo y/o contenido de los comandos. Esto proporciona un mecanismo flexible y fcilmente extensible para que los desarrolladores puedan aadir comportamientos al manejo de peticiones. Finalmente, como el procesamiento de comandos no est acoplado a la invocacin de comandos, el mecanismo de procesamiento de comandos se podra reutilizar para varios tipos de clientes, no slo con los navegadores Web. Esta estrategia tambin facilita la creacin de comandos compuestos. Aqu tenemos un ejemplo de esta estrategia:

/** This processRequest method is invoked from both * the servlet doGet and doPost methods **/ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { String resultPage; try { RequestHelper helper = new RequestHelper(request); /** the getCommand() method internally uses a factory to retrieve command objects as follows: Command command = CommandFactory.create( request.getParameter("op")); **/ Command command = helper.getCommand(); // delegate request to a command object helper resultPage = command.execute(request, response); } catch (Exception e) { LogManager.logMessage("EmployeeController", e.getMessage() ); resultPage = ApplicationResources.getInstance(). getErrorPage(e); } dispatch(request, response, resultPage); }

En la siguiente figura podemos ver el diagrama de secuencia de la estrategia Command and Controller.

Phisical Resource Mappping


En la estrategia de Mapeo Fsico de Recursos todas las peticiones se hacen sobre nombres de recursos fsicos especificos en lugar de sobre nombres lgicos. Un ejemplo es la siguiente URL: http://some.server.com/resource1.jsp. En el caso de un controlador, un ejemplo de URL podra ser: http://some.server.com/servlet/Controller. Es preferible utilizar la estrategia de Mapeo Lgico de Recursos porque proporciona una mayor flexibilidad, porque nos permite mapear los recuros de una forma declarativa.

Logical Resource Mapping


En la estrategia de Mapeo de Recurso Lgico todas las peticiones se hacen sobre nombres de recursos lgicos en vez de sobre nombres fsicos especficos. Los recursos fsicos a los que se refieren estos nombres lgicos podran modificarse de una forma declarativa. Por ejemplo, la URL http://some.server.com/process podra mapearse como:
process=resource1.jsp

o como:
process=resource2.jsp

o como:
process=servletController

Multiplexed Resource Mapping


La estrategia de Mapeo Multiplexado de Recursos realmente es una estrategia de Mapeo Lgico de Recursos. Esta estrategia no mapea slo a un nombre lgico, sino a un conjunto completo de nombres lgicos, para un slo recurso fsico. Por ejemplo, un mapeo de comodn podra mapear todas las peticiones que terminen en .ctrl a un controlador especfico, como podermos ver en la siguiente tabla:

Peticin>

Mapeo

http://some.server.com/action.ctrl *.ctrl = servletController

De hecho, es la estragegia que utilizan los motores de pginas JSP para asegurarse de que las peticiones de recursos de pginas JSP (es decir, recursos cuyos nombres terminan en .jsp) las procesa el manejador apropiado. Se pueden aadir informacin adicional a una peticion, proporcionando mayores detalles para este mapeo lgico, como se puede ver en la siguiente tabla:

Peticin>

Mapeo

http://some.server.com/profile.ctrl?usecase= create *.ctrl = servletController

Un beneficio importante de la utilizacin de esta estrategia es que proporciona una enorme flexibilidad cuando diseanos nuestros componentes de manejo de peticiones. Cuando se combina con las otras estrategias, como con la estrategia Command and Controller, se pueden crear un potente marco de trabajo para manejar peticiones. Consideremos un controlador que maneja todas las peticiones que terminan en .ctrl, como hemos visto antes. Consideremos tambin la parte izquierda del nombre de recursos delimitado por puntos (profile en el ejemplo de arriba) para que sea una parte del nombre de un ejemplo. Ahora combinamos este nombre con el valor de parmetro de la consulta (creado en el ejemplo de arriba). Estamos diciendo a nuestos manejador de peticiones que queremos procesar un ejemplo llamado crear perfil. Nuestro mapeo de recursos multiplexado enva la peticin a nuestro servletController, que es parte del mapeo mostrado en la tabla anterior. Nuestro controlador crea el objeto command apropiado, segn describimos en la Estrategia Command and Controller. Cmo sabe el controlador en qu objeto command debera delegar? Utilizando la informacin adicional de la URI de la peticin, el controlador delega en el objeto command que maneja la creacin de perfiles. Est podra ser un objeto ProfileCommand que sirve peticiones para la creacin y modificacin de perfiles, o podra ser un objeto ms especfico como ProfileCreationCommand.

Dispatcher in Controller
Cuando la funcionalidad del dispatcher es mnima, se puede plegar junto al controlador, como se muestra en la siguiente figura:

Base Front
La estrategia Base Front utilizada en combinacin con la estrategia Servlet Front, sugiere la implementacin de una clase base controladora, cuya implementacin deben extender otros controladoes. La clase Base Front podra contener implementaciones comunes y por defecto, aunque las subclases puedan sobreescribir estas implementaciones. El inconviente de esta estrategia es el hecho de que un superclase compartida, aunque promueve la reutilizacin y la comparticin, tiene el problema de crear un herencia frgil, donde los cambios necesarios para una subclase afectan a todas las dems subclases.

Filter Controller
Los filtros proporcionan un soporte similar para la centralizacin de manejo de peticiones. As, algunos aspectos de un controlador se pueden implementar de forma razonable como un filtro. Al mismo tiempo, los filtros se enfocan principalmente en la intercepcin y decoracin de peticiones, no en el procesamiento y en la generacin de respuestas. Aunque hay un solapamietno de responsabilidades, como en el manejo del log y la depuracin, cada componente complementa a los otros cuando se utilizan de la forma apropiada.

Consecuencias

Centraliza el Control Un controlador proporciona un lugar central para manejar los servicios del sistema y la lgica de negocios entre varias peticiones. Un controlador maneja el procesamiento de la lgica de negocio y el manejo de peticiones. El acceso centralizado a una aplicacin significa que las peticiones se pueden seguir y guardar muy fcilmente. Debemos tener en mente, que como controles centralizados, es posible presentar un slo punto de fallo. En la prctica, esto rramente es un problema, ya que tpicamente existe mltiples controladores, bien dentro de un slo servidor o en un cluster. Mejora la Manejabilidad de la Seguridad Un controlador centraliza el control, propocionando un punto de choque para intentos de accesos ilcitos en la aplicacin Web. Adems, auditar una sola entrada en la aplicacin requiere menos recursos que distribuir los chequeos de seguridad entre todas las pginas. Mejora la Reutilizabilidad Un controlador promueve el particionamiento limpio de la aplicacin y aconseja la reutilizacin, ya que el cdigo que es comn entre los componentes se mueve dentro de un controlador o es manejado por un controlador.

Patrones Relacionados

View Helper El patrn Front Controller, en conjuncin con el patrn View Helper, describe la creacin de lgica de negocio de la vista y proporciona un punto central de control y reenvio. El flujo lgico se construye dentro del controlador y el cdigo de manejo de datos se mueve hacia los helpers. Intercepting Filter Tanto Intercepting Filter como Front Controller describen formas de centralizar el control de ciertos tipos de procesamiento de peticiones, sugiriendo diferentes aproximaciones a este problema. Dispatcher View y Service to Worker Los patrones Dispatcher View y Service to Worker son otras forma de nombrar la combinacin entre el patrn View Helper con un dispatcher, y un patrn Front Controller. Dispatcher View y Service to Worker, aunque estructuralmente son iguales, describen diferentes divisiones de labores entre los componentes.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

View Helper o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Patrones Relacionados

View Helper
Contexto
El sistema crea el contenido de la presentacin, lo que requiere el procesamiento de datos de negocio dinmicos.

Problema
Los cambios en la capa de presentacin ocurren muy frecuentemente y son difciles de desarrollar y mantener cuando la lgica de acceso a los datos de negocio y la lgica del formateo de la presentacin se mezclan. Esto hace el sistema menos flexible, menos reutilizable, y generalmente menos adaptable a los cambios. Mezclar la lgica de negocio y de sistema con el procesamiento de la vista reduce la modularidad y tambin proporciona una pobre separacin de los roles entre los equipos de produccin Web y de desarrollo de software.

Causas

Los requerimientos de asimilacin de datos de negocio no son triviales. o Embeber la lgica de negocio en la vista promueve un tipo de reutilizacin del tipo copiar-y-pegar. Esto causa problemas de mantenimiento y errores porque una pieza de lgica se reutiliza en la misma vista o en otra diferente simplemente duplicndola en la nueva localizacin. o Es deseable promover una separacin limpia de labores teniendo diferentes individuos cumpliendo los roles de miembros de un equipo de desarrollo de software y de produccin Web. o Una vista comnmente se utiliza para responder a una peticin de negocios particular.

Solucin
Una vista contiene cdigo de formateo, delegando sus responsabilidades de procesamiento en sus clases de ayuda, implementadas como JavaBeans o etiquetas personalizadas. Las clases de ayuda o helpers tambin almacenan el modelo de datos intermedio de la vista y sirven como adaptadores de datos de negocio. Hay varias estrategias para implementar el componente de la vista. La estrategia JSP View siguiere utilizar una JSP como el componente vista. Esta es la estrategia preferida, y es la que se utiliza ms comunmente. La otra estrategia principal es la estrategia Servlet View, que utiliza un servlet como la vista.

Encapsular la lgica de negocio en un helper en lugar de hacerlo en la vista hace que nuestra aplicacin sea ms modular y facilita la reutilizacin de componentes. Varios clientes, como controladores y vistas, podran utilizar el mismo helper para recuperar y adaptar estados del modelo similares para su presentacin en varias vistas. La nica forma de reutilizar la lgica embebida en una vista es copiando y pegando en cualquier lugar. Adems, la duplicacin mediante copiar-y-pegar hace que un sistema sea difcil de mantener, ya que necesitamos corregir en muchos sitios el mismo error potencial. Una seal de que podramos necesitar aplicar este patrn al cdigo existente es cuando el cdigo scriptlet domina en la vista JSP. Ya que el objetivo general cuando se aplica este patron, es el particionamiento de la lgica de negocio fuera de la vista. Mientras alguna lgica est mejor cuando se encapsula dentro de objetos helper, otra lgica est mejor situndola en un componente centralizado que se sita delante de las vistas y los helpers -- esta podra la lgica que sea comn entre varias peticiones, como los chequeos de autentificacin o servicios de logs, por ejemplo. Si no se emplea un controlador separado en la arquitectura, o si no se utiliza para manejar todas las peticiones, entonces el componente vista se convierte en el punto de contacto inicial para manejar algunas peticiones. Para ciertas peticiones, particularmente aquellas que implican un procesamiento mnimo, este escenario funcionar bien. Tpicamente, esta situacin ocurre cuando pginas que estn basadas en informacin esttica, como la primera de un conjunto de pginas que se servirn a un usuario para obtener alguna informacin. . El patrn View Helper se enfoca en recomendar formas de particionar las responsabilidades de nuestras aplicaciones.

Estructura
Abajo podemos observar el diagrama de clases que representa el patrn View Helper.

Participantes y Responsabilidades
La siguiente figura muestra el diagrama de secuencia que represetna el patrn View Helper. Normalmente un controlador media entre el cliente y la vista. Aunque en algunos casos, no se utiliza un controlador y la vista se convierte en el punto de contacto inicial para manejar peticiones.

Como se ha podido observar en el diagrama de clases, podran no haber helpers asociados con una vista. En este caso simple, la pgina podra ser completamente esttica o incluir una muy pequea cantidad de scriptles. Este escenario se describe en el siguiente diagrama de secuencia:

View
Una vista representa y muestra informacin al cliente. La informacin que se utiliza en un display dinmico se recupera de un modelo. Los helpers soportan vistas encapsulando y adaptando un modelo para utilizarlo en un display.

Helper
Un helper es el responsable de ayudar a la vista o al controlador a completar su procesamiento. As los helpers tienen numerosas responsabilidades, incluyendo la obtencin de los datos requeridos por la vista y su almacenamiento en el modelo intermedio, en cuyo caso algunas veces nos podemos referir al helper como un Bean de Valor. Adems, los helpers podran adaptar este modelo de datos para que los utilizara la vista. Los helpers pueden servir peticiones de datos desde la vista simplemente proporcionando acceso a los datos o fomateando los datos como contenido Web. Una vista podra trabajar con cualquier nmero de helpers, que normalmente estn implementados como JavaBeans (JSP 1.0+) y etiquetas personalizadas (JSP 1.1+). Adems, un helper podra representar un objeto Command o un Tranformador XSL, que se utiliza en combinacin con una hoja de estilo para adaptar y convertir el modelo en el formato apropiado.

ValueBean
Un Bean de Valor es un otro nombre para un helper que es responsable de contener el estado del modelo intermedio para que lo utilice una vista. Un caso tpico, es el que tiene un servicio de negocio que devuelve un bean de valor en respuesta a esta peticin. Este caso, el Bean de valor cumple el rol de un objeto Transfer.

BusinessService
El servicio de negocio es un rol que cumple el servicio al que est accediendo el cliente. Tpicamente, se accede al servicio de negocio mediante un Delegado de Negocio. El rol del delegado de negocio es proporcionar control y proteccin para el servicio de negocio (podremos ver el patrn Business Delegate ms adelante).

Estrategias

JSP View
La estrategia de Vista JSP sugiere la utilizacin de una JSP como el componente vista. Aunque semnticamente equivalente a la estrategia de Vista Servlet, es una solucin ms elegante y ms utilizada. Las vistas son el dominio de los diseadores Web, que prefieren un lenguaje de marcas al cdigo Java. El siguiente ejemplo muestra un ejemplo de cdigo para esta estrategia. El fragmento es de un fichero fuente llamado welcome.jsp, al que nos reenvia un controlador servlet despus de situar el JavaBean WelcomeHelper en el mbito de la peticion:

<jsp:useBean id="welcomeHelper" scope="request" class="corepatterns.util.WelcomeHelper" /> <HTML> <BODY bgcolor="FFFFFF"> <% if (welcomeHelper.nameExists()) { %> <center><H3> Welcome <destacar> <jsp:getProperty name="welcomeHelper" property="name" /> </destacar><br><br> </H3></center> <% } %> <H4><center>Glad you are visiting our site!</center></H4> </BODY> </HTML>

La estrategia alternativa de Vista Servlet normalmente se implementa embebiendo marcas HTML directamente dentro del cdigo Java. Mezclar cdigo Java y etiquetas de marcas crea una pobre separacin de los roles de usuario dentro de un proyecto e incrementa las dependencias de los mismos recursos entre varios miembros de diferentes equipos. Cuando un individuo trabaja en una plantilla que contiene cdigo o etiquetas no familiares, incrementa el riesgo de que un cambio accidental introduzca problemas en el sistema. Tambin hay una reduccin de la eficiencia del entorno de trabajo (demasiada gente compartiendo los mismos recursos fsicos) y un incremento en el manejo de control de fuentes. Estos problemas ocurren ms frecuentemente en grandes entornos empresariales que tienen requerimientos de sistemas ms complicados y que utilizan equipos de desarrolladores. Tiene menos probabilidades de ocurrir en pequeos sistemas que tienen sencillos requerimientos y utilizan unos pocos desarrolladores porque el mismo individuo cumple los roles mencionados arriba. Sin embargo, debemos tener en mente que los proyectos suelen empezar pequeos -- con requerimiento sencillos y unos cuantos desarrolladores -- pero finalmente evolucionan y se convierten en suficientemente sofisticados como para beneficiarse de estas sugerencias.

Servlet View
La estrategia de Vista Servlet utiliza un servlet como la vista. Es semnticametne equivalente al estrategia preferida de Vista JSP. Sin embargo, la estrategia de Vista Servlet, como vemos en el ejemplo siguiente, es ms engorrosa para los equipos de desarrollo de software y de produccin Web porque embebe etiquetas de marcas dentro del cdigo Java. Cuando las etiquetas se mezclan con el cdigo Jaba, la plantilla de la vista es ms difcil de actualizar y modificar.

public class Controller extends HttpServlet { public void init(ServletConfig config) throws ServletException { super.init(config); } public void destroy() { } /** Processes requests for both HTTP * <code>GET</code> and <code>POST</code> methods. * @param request servlet request * @param response servlet response */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException {

String title = "Servlet View Strategy"; try { response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter(); out.println("<html><title>"+title+"</title>"); out.println("<body>"); out.println("<h2><center>Employees List</h2>"); EmployeeDelegate delegate = new EmployeeDelegate(); /** ApplicationResources provides a simple API * for retrieving constants and other * preconfigured values**/ Iterator employees = delegate.getEmployees( ApplicationResources.getInstance(). getAllDepartments()); out.println("<table border=2>"); out.println("<tr><th>First Name</th>" + "<th>Last Name</th>" + "<th>Designation</th><th>Id</th></tr>"); while (employees.hasNext()) out.println("<tr>"); EmployeeTO emp = (EmployeeTO)employees.next(); out.println("<td>"+emp.getFirstName()+ "</td>"); out.println("<td>"+emp.getLastName()+ "</td>"); out.println("<td>"+emp.getDesignation()+ "</td>"); out.println("<td>"+emp.getId()+"</td>"); out.println("</tr>"); } out.println("</table>"); out.println("<br><br>"); out.println("</body>"); out.println("</html>"); out.close(); } catch (Exception e) { LogManager.logMessage("Handle this exception", e.getMessage() ); } } /** Handles the HTTP <code>GET</code> method. * @param request servlet request * @param response servlet response */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Handles the HTTP <code>POST</code> method. * @param request servlet request * @param response servlet response */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Returns a short description of the servlet. */ public String getServletInfo() { return "Example of Servlet View. " + "JSP View is preferable."; } /** dispatcher method **/ protected void dispatch(HttpServletRequest request, HttpServletResponse response, String page) throws javax.servlet.ServletException, java.io.IOException { RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(page); dispatcher.forward(request, response); } }

JavaBean Helper

El helper se implementa como un JavaBean. La utilizacin de helpers resulta en una separacin limpia de la vista y el procesamiento de negocio en una aplicacin, ya que la lgica de negocio est construida fuera de la vista y dentro del componente helper. En este caso, la lgica de negocio se encapsula en un JavaBean, que ayuda en la recuperacin de contenido y adapta y almacena el modelo para usarlo en la vista. La utilizacin de la estrategia JavaBean Helper requiere menos trabajo que la estrategia Custom Tag Helper, ya que los JavaBeans se construyen e integran ms facilmente en un entorno JSP. Adems, incluso los desarrolaldores novatos entienden los JavaBeans. En el siguiente cdigo podemos ver un ejemplo de esta estrategia:

<jsp:useBean id="welcomeHelper" scope="request" class="corepatterns.util.WelcomeHelper" /> <HTML> <BODY bgcolor="FFFFFF"> <% if (welcomeHelper.nameExists()) { %> <center><H3> Welcome <destacar> <jsp:getProperty name="welcomeHelper" property="name" /> </destacar><br><br> </H3></center> <% } %> <H4><center>Glad you are visiting our site!</center></H4> </BODY> </HTML>

Custom Tag Helper


El helper se implementa como una etiqueta personalizada (slo JSP 1.1+). La utilizacin de helpers resulta en una separacin limpia de la vista y el procesamiento de negocio en una aplicacin, ya que la lgica de negocio est construida fuera de la vista y dentro del componente helper. En este caso, la lgica de negocio se encapsula en un componente de etiqueta personalizada, que podra ayudar en la recuperacin de contenido y adaptar el modelo para su utilizacin en la vista. Usar esta estrategia requier mucho ms trabajo que hacerlo con la estrategia JavaBean Helper, ya que el desarrollo de etiquetas personalizadas es moderadamente complicado en relacin al desarrollo de JavaBeans. No solo es ms complejo el proceso de desarrollo, sino que hay mucha complejidad con respecto a la integracin y el manejo de las etiquetas completadas. Para utilizar esta estrategia, debemos configurar el entorno con numerosos artefactos generados, incluyendo la propia etiqueta, un descriptor de librera de etiquetas, y los ficheros de configuracin. Abajo podemos ver un fragmento de una vista JSP que utiliza esta estrategia:

<%@ taglib uri="/web-INF/corepatternstaglibrary.tld" prefix="corepatterns" %> <html> <head><title>Employee List</title></head> <body> <div align="center"> <h3> List of employees in <corepatterns:department attribute="id"/> department - Using Custom Tag Helper Strategy. </h3> <table border="1" > <tr> <th> First Name </th> <th> Last Name </th> <th> Designation </th> <th> Employee Id </th> <th> Tax Deductibles </th> <th> Performance Remarks </th> <th> Yearly Salary</th> </tr> <corepatterns:employeelist id="employeelist_key"> <tr> <td><corepatterns:employee attribute="FirstName"/> </td> <td><corepatterns:employee

attribute= "LastName"/></td> <td><corepatterns:employee attribute= "Designation"/> </td> <td><corepatterns:employee attribute= "Id"/></td> <td><corepatterns:employee attribute="NoOfDeductibles"/></td> <td><corepatterns:employee attribute="PerformanceRemarks"/></td> <td><corepatterns:employee attribute="YearlySalary"/></td> <td> </tr> </corepatterns:employeelist> </table> </div> </body> </html>

Business Delegate as Helper


Los componentes helper normalmente hacen llamadas distribuidas a la capa de negocio. Sugerimos la utilizacin de un delegado de negocio para poder ocultar los detalles de la implementacin subyacente, as como dicho helper simplemente invoca un servicio de negocio sin conocer los detalles sobre su implementacin fsica y su distribucin. Tanto el helper como el delegado de negocio deben implementarse como JavaBeans. As, se podra combinar la nocin del componente helper y del delegado de negocio e implementar el delegado de negocio como un tipo de helper especializado. Hay una mayor distincin entre un helper y un delegado de negocio: Un desarrollador que trabaja en la capa de presentacin escribe un componente helper, mientras que el delegado normalmente lo escribe un desarrollador que trabaja en los servicios de la capa de negocio. (Nota: El delegado tambin se podra proporcionar como una parte del marco de trabajo). As, est estrategia trato mucho ms sobre quin escribe realmente el delegado que sobre la propia implementacin. Si hay algn solapamiento en los roles de desarrollo, entonces deberiamos considerar la utilizacin de esta estrategia.

/**A servlet delegates to a command object helper, as shown in the following excerpt:**/ String resultPage = command.execute(request, response); /**The command object helper uses the business delegate, which is simply implemented as another JavaBean helper, as shown in the following excerpt:**/ AccountDelegate accountDelegate = new AccountDelegate();

Una nota sobre los Helpers: Los helpers JavaBean se utilizan para ayudar en la recuperacin de contenido y en el almacenamiento y adaptacin del modelo para la vista. Los helpers JavaBean tambin se utilizan frecuentemente como objetos Command. Al igual que los helpers JavaBean, los helpers de etiquetas personalizadas podran cumplir cualquiera de estos roles, excepto el de actuar como un objeto command. Al contrario que los helpers JavaBean, los helpers de etiquetas personalizadas estn bien diseados para el control de flujo y la interaccin con la vista. Los helpers de etiquetas personalizadas utilizados de esta forma encapsulan lgica que de otro modo podra embeberse directamente dentro de la pgina JSP como cdigo scriptlet. Otra rea donde es preferible utilizar helpers de etiquetas personalizadas es en el formato de datos para display. Una etiqueta personalizada puede iterar sobre una coleccin de resultados, formatear esos resultados en un tabla HTML, y embeber la tabla dentro de la

vista JSP sin requerir ningn scriptlet Java. Consideremos un ejemplo en el que le pedimos a un cliente Web alguna informacin de la cuenta del sistema, como se ve en la siguiente figura.

Podemos ver cinco helpers en este diagrama. Los cuatro helpers JavaBean son el objeto AccountCommand, el objeto Account, el objeto AccountDAO, y AccountDetails. El nico helper de etiqueta personalizada es el objeto TableFormatter. El controlador maneja la peticin. Crea o busca el objeto command apropiado, que est implementado como un helper JavaBean. En este caso, es el objeto command que procesa las peticiones de informacin de la cuenta. El controlador invoca al objeto Command, que le pide la informacin sobre la cuenta a un objeto Account. El objeto Account invoca al servicio de negocio, pidendole estos detalles, que se devuelven en forma de un objeto Transfer implementado como un JavaBean. Entonces, como accede el objeto Account a los servicios de negocio? Examinemos dos casos, uno sencillo y otro un poco ms complicado. En el caso sencillo, imaginemos que un proyecto est en fase de aproximacin, enfasando Enterprise JavaBeans (EJB) dentro de la capa de negocio en el tiempo. Asumamos que estmos en el momento en que se est accediendo a la base de datos mediante llamadas JDBC desde la capa de presentacin. En ese caso, el objeto Account utiliza un objeto Data Access (en pginas posteriores veremos este patrn), ocultando los detalles de implementacin para acceder a la base de datos. El objeto Data Access sabe qu consultas SQL son las necesarias para recuperar la informacin. Estos detalles estn ocultos del resto de la aplicacin, reduciendo el acoplamiento y haciendo que todos los componentes sean ms modulares y reutilizables. Este es el caso descrito en el diagrama de secuencia anterior. Cuando la arquitectura se vuelve ms sofisticada, se introduce un EJB en la capa de negocio, entonces el objeto Data Access se reemplaza con un Business Delegate (ms adelante veremos este patrn), que normalmente est escrito por

los desarrolladores de servicios de negocio. El delegado oculta los detalles de implementacin de la bsqueda EJB, de la invocacin y del manejo de excepciones. Tambin podra mejorar el rendimiento proporcionando servicio de cach. De nuevo, el objeto reduce el acoplamiento entre las capas, mejorando la reutilizacin y la modularidad de varios componentes. Sin importar la implementacin especfica de este objeto, su interface podra permanecer invariable durante esta transicin. La siguiente figura describe este escenario despus de la transicin al delegado de negocio.

Ahora el objeto command tiene que manejar el objeto AccountDetails, el cual almacena antes de devolver el control al controlador. El Controller lo reenvia a la vista apropiada, llamada AccountView.jsp. Entonces la vista obtiene una combinacin de datos en bruto y de datos formateados de los helpers AccountDetails y TableFormatter, respectivamente. TableFormatter est implementado como una etiqueta personalizada que pasa a travs de los datos en bruto y los formatea en una tabla HTML para mostrarla. Como vimos, esta conversin no requiere escribir nign scriptlet en la vista, lo que s sera necesario para realizar la misma funcionalidad con un helper JavaBean. Adems, el objeto Account o el helper AccountDetails podran proporcionar mtodos convenientes para adaptar los datos en bruto a otros formatos. Aunque dichos mtodos no introduciran etiquetas HTML en los datos, podran proporcionar diferentes combinaciones de datos. Un ejemplo es entregar el nombre completo del usuario en varios formatos, como "Lastname, Firstname" o "Firstname Lastname", etc.

Transformer Helper
El helper se implementa como un eXtensible Stylesheet Language Transformer. Esto es particularmente til con modelos que existen como marcas estructuradas, como el lenguaje eXtensible Markup Language (XML), bien nativamente dentro de sistemas legales o mediante alguna forma de conversin. Utilizar esta estrategia puede ayudarnos a forzar la separacin entre el modelo y la vista, ya que la mayora de las marcas de la vista se tienen que crear en una hoja de estilos separada. La siguiente figura describe una potencial implementacin de esta estrategia:

El controlador maneja la peticin e invoca al objeto Command, implementado como un helper JavaBean. El objeto Command inicia la recuperacin de los datos de la cuenta. El objeto Account invoca al servicio de negocio, que devuelve los datos en forma de un objeto Transfer, implementado como un JavaBean. Se completa la recuperacin de contenido y el control se pasa al AccountView, que utiliza su etiqueta personalizada transformer para manipular el estado del modelo. El transformer trata con un hoja de estilo, que describe cmo transformar el modelo, normalmente describiendo cmo formatearlo con etiquetas para mostrarlo en el cliente. La hoja de estilo normalmente se recupera como un fichero esttico, aunque se podra generar dinmicamente. Aqu tenemos un ejemplo de lo que debera ser la etiqueta personalizada:

<xsl:transform model="accounthelper" stylesheet="/transform/styles/basicaccount.xsl"/>

Consecuencias

Mejora el Particionamiento de la Aplicacin, la Reutilizacin y el Mantenimiento Utilizar helpers resulta en una clara separacin de la vista del procesamiento de negocio en una aplicacin. Los helpers, en forma de JavaBeans (JSP 1.0+) y etiquetas personalizadas (JSP 1.1+), proporcionan un lugar externo para que la vista encapsule la lgica de negocio. Por el contrario, el cdigo en scriptlets dentro de las pginas JSP, emborrona ampliamente la situacin, especialmente en gandes proyectos. Adems, la lgica de negocio que se construye fuera de las JSPs y dentro de los JavaBeans y las etiquetas personalizadas se reutiliza, reduciendo la duplicacin y facilitando el mantenimiento.

Mejora la Separacin de Roles Separar la lgica del formateo de la lgica de negocio de la aplicacin reduce las dependencias podran tener los individuos que juegan los diferentes roles en los mismos recursos. Por ejemplo, un desarrollador de software podra poseer cdigo que est embebido dentro de marcas HTML, mientras que un miembro del equipo de produccin Web podra necesitar modificar la distribucin de la pgina y disear componentes que estn mezclados con la lgia de negocios. Ningn individuo que cumpla estos roles podra estar familiarizado con las implementaciones especficas del trabajo del otro individuo, y asi se evita el riesgo de introducir bugs mediante modificaciones accidentales del sistema.

Patrones Relacionados

Business Delegate Los componentes helper necesitan mtodos de acceso al API de servicios de negocio. Tambin es importante reducir el acoplamiento entre helpers en la capa de presentacin y entre servicios de negocio en la capa de negocio. Se recomienda que se utilice un delegate porque estas capas podran estar distribuidas fsicamente por la red. El delegado le oculta al clinte los detalles subyacentes de la bsqueda y acceso a los servicios de negocio, y tambin podra proporcionar un cach intermedio para reducir el trfico de la red. Dispatcher View y Service to Worker Cuando sea deseable el control centralizado para manejar problemas como la seguridad, el control del carga de trabajo, la recuperacin de contenidos y la navegacin, debemos considerar la utilizacin de los patrones Dispatcher View o Service to Worker. Front Controller Este patrn est emparejado con el patrn View Helper para crear los patrones Dispatcher View o Service to Worker.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Composite View o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

Composite View
Contexto
Las pginas Web sofisticadas presentan contenido de varias fuentes de datos, utilizando varias subvistas que completan una sla pgina. Adems, varios individuos con diferentes habilidades contribuyen al desarrollo y mantenimiento de esas pginas Web.

Problema
En lugar de proporcionar un mecanismo para combinar modularmente, en el que porciones atmicas de una vista componen un pgina completa, las pginas se construyen embebiendo cdigo de formateo directamente dentro de cada vista. La modificacin de la distribucin de mltiples vistas es difcil y propensa a errores, debido a la duplicacin de cdigo.

Causas

Las porciones atmicas del contenido de la vista cambian con frecuencia. Varias vistas compuestas utilizan subvistas similares, como un tabla de inventario de clientes. Estas porciones atmicas se decoran con una plantilla de texto alrededor diferente o aparecen en diferentes localizaciones dentro de la pgina. Los cambios de distribucin son ms difciles de manejar y el cdigo ms difcil de mantener cuando las subvistas se embeben directamente y se duplican en varias vistas. Frecuentemente, embeber las porciones cambiantes de la plantilla de texto directamente dentro de las vistas tambin afecta potencialmente a la disponibilidad y administracin del sistema. El servidor podra necesitar reinicializarse antes de que los cliente vieran las modificaciones o actualizaciones de estas plantillas de componentes.

Solucin
Utilizar vistas compuestas que se componen de varias subvistas atmicas. Cada componente de la plantilla se podra incluir dinmicamente dentro del total y la distribucin de la pgina se maneja independientemente del contenido. Esta solucin promueve la creacin de una vista compuesta basada en la inclusin y sustitucin de fragmentos de plantilla modulares tanto estticos como dinmicos. Tambin promueve la reutilizacin de porciones atmicas de la vista asegurando un diseo modular. Es apropiado utilizar este patrn para generar pginas que muestran componentes que podran combinarse en una gran variedad de formas. Este escenario ocurre, por ejemplo, con sites de portal que incluyen numerosas subvistas independientes,

como noticias, informacin del tiempo, y valores de stocks en una sla pgina. La distribucin de la pgina se maneja y modifica de forma independiente al contenido de las subvistas. Otro beneficio de este patrn es que los diseadores Web pueden hacer un prototipo de la distribucin de la site, conectando contenido esttico en todas las regiones de la plantilla. Segn va progresando el desarrollo de la site, ese contenido esttico se puede sustituir por el contenido dinmico. La siguiente figura muestra una captura de pantalla de la pgina inicial de Sun, java.sun.com. Se identifican cuatro regiones: Navegacin, Bsqueda, Contenido y Cabeceras. Aunque el contenido de cada una de estas subvistas podra estar originado desde diferentes fuentes de datos, se unen para crear un sla pgina compuesta.

Esta patrn tambin tiene inconvenientes. Provoca una sobrecarga en el entorno de ejecucin, un precio que hay que pagar por el incremento de flexibilidad que proporciona. La utilizacin de un mecanismo de distribucin ms sofisticado tambin trae consigo algunos problemas de manejabilidad y desarrollo, ya que hay ms artefactos que mantener y un cierto nivel indirecto de implementacin que entender.

Estructura
La siguiente figura representa el diagrama de clases del patrn Composite View.

Participantes y Responsabilidades
La siguiente figura representa el diagrama de secuencia del patrn Composite View.

Composite View
Una vista compuesta es una vista a la que se le han agregado varias subvistas.

View Manager
El Controlador de Vista maneja la inclusin de porciones de fragmentos de plantilla en la vista compuesta. El Controlador de Vista podra ser parte de un motor de ejecucin estndar de pginas JSP, en la forma de la etiqueta <jsp:include> de JSP, o podra encapsularse dentro de un helper JavaBean (JSP 1.0+) o una etiqueta personalizada (JSP 1.1+) para proporcionar una funcionalidad ms robusta. Un beneficio adicional de utilizar un mecanismo distinto a la etiqueta include estndar es que stos facilitan la inclusin condicional. Por ejemplo, ciertos fragmentos de plantilla se podran incluir slo si el usuario cumple un rol particular o si se cumplen ciertas condiciones del sistema. Adems, utilizar un componente helper como View Manager nos permite un control ms sofisticado de toda la estructura de la pgina, lo que es til para crear distribuciones de pginas reutilizables.

Included View

Una Vista Incluida es una subvista que es una pieza atmica de un vista completa mayor. Esta vista incluida potencialmente tambin podra ser una vista compuesta, incluyeno ella misma varias subvistas.

Estrategias

JSP page View


Ver la estrategia "JSP page View" en el patrn View Helper.

Servlet View
Ver la estrategia "Servlet View" en el patrn View Helper.

JavaBean View Management


El control de la vista se implementa utilizando componentes JavaBeans, como se ve en el siguiente ejemplo. La vista delega en el JavaBean, que implementa la lgica personalizada para controlar la distribucin y composicin de la vista. Las decisiones sobre la distribucin de la pgna se deben basar en roles de usuario o polticas de seguridad, hacindolo mucho ms poderoso que la etiqueta include de una pgina JSP. Aunque es semnticamente equivalente a la Estrategia de Control de Vista por Etiqueta Personalizada, no es tan elengante porque introduce cdigo scriptlet en la vista. Utilizar esta estrategia requiere menos trabajo que utilizar la estrategia preferida de Control de Vista por Etiqueta Personalziada, porque es ms fcil construir componentes JavaBeans e integrarlos en un entorno de pginas JSP. Adems, incluso los desarrolladores ms novatos pueden entender los componentes JavaBeans. Esta estrategia tambin es fcil desde el punto de vista de la manejabilidad, porque los componentes JavaBeans son los nicos artefactos que hay que manejar y configurar.

<%@page import="corepatterns.compositeview.beanhelper.ContentHelper" %> <% ContentHelper personalizer = new ContentHelper(request); %> <table valign="top" cellpadding="30%" width="100%"> <% if (personalizer.hasWorldNewsInterest() ) { %> <tr> <td><jsp:getProperty name="feeder" property="worldNews"/></td> </tr> <% } if ( personalizer.hasCountryNewsInterest() ) { %> <tr> <td><jsp:getProperty name="feeder" property="countryNews"/></td> </tr> <% } if ( personalizer.hasCustomNewsInterest() ) { %> <tr> <td><jsp:getProperty name="feeder" property="customNews"/></td> </tr> <% } if ( personalizer.hasAstronomyInterest() ) { %> <tr> <td><jsp:getProperty name="feeder" property="astronomyNews"/></td> </tr> <% } %> </table>

Standard Tag View Management


El control de la vista se implementa utilizando etiquetas JSP estndar, como <jsp:include>. Utilizar etiquetas estndar para manejar la distribucin y composicin de las vistas es una estrategia fcil de implementar, pero no proporciona el poder y la flexibilidad de la Estrategia de Control de Vista por Etiqueta Personalizada, ya que la distribucin de las pginas individuales permanece embebida dentro de esas pginas. As, aunque esta estrategia permite variar dinmicamente el contenido subyacente, cualquier cambio general en la distribucin requerira modificaciones individuales en muchas pginas JSP. Podemos verlo en el siguiente ejemplo:

<html> <body> <jsp:include page="/jsp/CompositeView/javabean/banner.html" flush="true"/> <table width="100%"> <tr align="left" valign="middle"> <td width="20%"> <jsp:include page="/jsp/CompositeView/javabean/ProfilePane.jsp" flush="true"/> </td> <td width="70%" align="center"> <jsp:include page="/jsp/CompositeView/javabean/mainpanel.jsp" flush="true"/> </td> </tr> </table> <jsp:include page="/jsp/CompositeView/javabean/footer.html" flush="true"/> </body> </html>

Cuando se crea una vista compuesta utilizando etiquetas estndar, se puede incluir tanto contenido esttico, ficheros HTML, como contenido dinmico, pginas JSP. Adems, el contenido se puede incluir en el momento de la traduccin o durante la ejecucin. Si el contenido se incluye durante la traduccin, la vista permanecer sin modificada hasta que se recompile la pgina JSP, momento en el que sern visibles las modificaciones incluidas en el contenido. En otras palabras, la pgina se distribuye y genera una sola vez, cada vez que la pgina JSP se recompila. El siguiente ejemplo, muestra una excepcin de una pgina JSP que genera una vista compuesta de esta manera, utilizando la directiva <%@ include %> estndar de JSP que incluye el contenido en tiempo de traduccin..

<table border=1 valign="top" cellpadding="2%" width="100%"> <tr> <td><%@ file="news/worldnews.html" %> </td> </tr> <tr> <td><%@ file="news/countrynews.html" %> </td> </tr> <tr> <td><%@ file="news/customnews.html" %> </td> </tr> <tr> <td><%@ file="news/astronomy.html" %> </td> </tr> </table>

La inclusin de contenido en tiempo de ejecucin significa que los cambios en las subvistas son visibles en la pgina compuesta cada vez que el cliente accede a ella. Esto es mucho ms dinmico y se puede conseguir utilizando la etiqueta <jsp:include> estndar de JSP, como se muestra en el siguiente ejemplo. Por supuesto que hay una sobrecarga del entorno de ejecucin asociada con este tipo de generacin de vistas, pero este es el incoveniente de mejorar la flexibilidad de las modificaciones de contenidos al-vuelo.

<table border=1 valign="top" cellpadding="2%" width="100%"> <tr>

<td><jsp:include page="news/worldnews.jsp" flush="true"/> </td> </tr> <tr> <td><jsp:include page="news/countrynews.jsp" flush="true"/> </td> </tr> <tr> <td><jsp:include page="news/customnews.jsp" flush="true"/> </td> </tr> <tr> <td><jsp:include page="news/astronomy.jsp" flush="true"/> </td> </tr> </table>

Custom Tag View Management


El control de la vista se implementa mediante etiquetas personalizadas (JSP 1.1+), que es la estrategia preferida. La lgica implementada dentro de la etiqueta controla la distribucin de la vista y la composicin. Estas etiquetas son mucho ms poderosas y flexibles que la etiqueta include estndar de JSP, pero tambin requiere un mayor nivel de esfuerzo. Las acciones personalizadas se pueden basar en la distribucin y composicin de la pgina o en otras cosas como los roles del usuario y las polticas de seguridad. Utilizar esta estrategia requiere mucho ms trabajo que las otras estrategias de control de vista ya que el desarrollo de etiquetas personalizadas es ms complicado que simplemente utilizar componentes JavaBeans o etiquetas estndar. No slo es ms complicado el proceso de desarrollo, tambin hay mucha ms complejidad en cuanto a la integracin y el manejo de las etiquetas generadas. La utilizacin de esta estrategia requiere la generacin de numerosos artefactos, incluyendo la propia etiqueta, un descriptor de librera de etiquetas, ficheros de configuracin, y configurar el entorno con estos artefactos. El siguiente fragmento de pgina JSP muestra una posible implementacin de esta estrategia.

<region:render template='/jsp/CompositeView/templates/portal.jsp'> <region:put section='banner' content='/jsp/CompositeView/templates/banner.jsp' /> <region:put section='controlpanel' content= '/jsp/CompositeView/templates/ProfilePane.jsp' /> <region:put section='mainpanel' content= '/jsp/CompositeView/templates/mainpanel.jsp' /> <region:put section='footer' content= '/jsp/CompositeView/templates/footer.jsp' /> </region:render>

Transformer View Management


El control de la vista se implementa utilizando un Transformador XSL. Esta estrategia se complementara con la Estrategia de Control de Vista por Etiqueta Personalizada, utilizando etiquetas personalizadas para implementar y delegar en los componentes apropiados. Utilizar esta estrategia nos puede ayudar a reforzar las separacin entre el modelo y la vista, ya que muchas de las marcas de la vista se deben crear dentro de una hoja de estilos separada. Al mismo tiempo, implica tecnologas que requieren nuevas y sofisticadas habilidades para implementarlo correctamente, un problema que hace que esta estrategia sea impracticable en muchos entornos donde estas tecnologas no estn an establecidas. El siguiente fragmento muestra el uso de una etiqueta personalizada dentro de una pgina JSP para convertir un modelo utilizando un hoja de estilo y un transformador:

<xsl:transform model="portfolioHelper" stylesheet="/transform/styles/generalPortfolio.xsl"/>

Early-Binding Resource
Este es otro nombre para la inclusin de contenido durante la traduccin, como se describe en la estrategia Control de Vista Mediate Etiqueta Estndar. Es apropiado para mantener y actualizar una plantilla relativamente esttica y est recomendado si una vista incluye cabeceras y pies de pgina que no cambian muy a menudo.

Late-Binding Resource
Este es otro nombre para la inclusin de contenido durante la traduccin, como se describe en la estrategia Control de Vista Mediate Etiqueta Estndar. Es apropiada para pginas compuestras que podran cambiar con cierta frecuencia. Una advertencia: Si la subvista incluida en tiempo de ejecucin es un recurso dinmico, como una pgina JSP, entonces sta subvista tambin podra ser una vista compuesta, incluyendo ms contenido en tiempo de ejecucin. La flexibilidad ofrecida por dichas estructuras anidadas debera pesar mucho ms que la sobrecarga del entorno que va crear.

Consecuencias

Mejora la Modularidad y la Reutilizacin Este patrn promueve un diseo modular. Es posible reutilizar porciones atmicas de una plantilla, como una tabla de consulta de stocks, en varias vistas y redecorar estas porciones reutilizadas con informacin diferente. Este patrn permite que la tabla se mueva dentro de su propio mdulo e incluirla simplemente donde sea necesario. Este tipo de distribucin y composicin dinmicos reduce la duplicacin, fuerza la reutilizacin y mejora la manejabilidad. Mejora la Flexibilidad Una implementacin sofisticada podra incluir condicionalmente fragmentos de plantillas de vista basndose en decisiones en tiempo de ejecuin, como los roles de usuario o las polticas de seguridad. Mejora el Mantenimiento y la Manejabilidad Es mucho ms eficiente manejar cambios en porciones de una plantilla cuando la plantilla no est codificada directamente en las marcas de la vista. Cuando se mantienen separadas de la vista, es posible modificar prociones modulares del contenido de la plantilla independientemente de su distribucin. Adems, esos cambios estn disponibles inmediatamente para los clientes, dependendiendo de la estrategia de implementacin. Las modificaciones en la distribucin de una pgona tambin se maneja ms fcilmente, ya que los cambios estn centralizados. Reduce la Manejabilidad Agregar piezas atmicas para mostrarlas juntas y crear una sola vista presenta algunos potenciales problemas de presentacin, ya que las subvistas son fragmentos de pginas. Esta es una limitacin que se puede convertir en un problema de manejabilidad. Por ejemplo, si una pgina JSP est generando una pgina HTML utilizando una pgina principal que incluye tres subvistas, y cada una de las subvistas incluye las etiquetas de apertura y cierre de HTML (es decir, <HTML> y </HTML>), entonces la pgina compuesta no ser vlida. Por lo tanto, es importante cuando utilicemos este patrn tener cuidado de que las subvistas no deben ser vistas completas. Se deben contabilizar estrictamente las etiquetas utilizadas para crear vistas compuestas vlidas, y as corregir este problema de manejabilidad. Impacto en el Rendimiento Generar una presentacin que incluye numerosas subvistas podra empeorar el rendimiento. La inclusin en tiempo de ejecucin de subvistas resultar en un retardo cada vez que se sirva la pgina a un cliente. En un entorno con Acuerdos de Nivel de Servicio que obligan a tiempos de respuesta especficos, dichas bajadas de rendimiento, anque tpicamente sean mnimas, podran no ser aceptables. Una alternativa es mover la inclusin de las subvistas al tiempo de la traduccin, aunque esto limita a que las subvistas slo cambien cuando se re-traduce la pgina.

Cdigo de Ejemplo
El patrn de Vista Compuesta se puede implementar utilizando cualquier nmero de estrategias, pero una de las ms populares es la Estrategia de Control de Vista por Etiqueta Personalizada. De hecho, actualmente hay disponibles varias libreras de etiquetas personalizadas para implementar vistas compuestas que separan las distribucin de la vista de su contenido y proporciona plantillas de subvistas modulares y conectables. Este ejemplo utilizar una librera de plantillas escrita por David Geary.

La librera template describe tres componentes bsicos: secciones, regiones y plantillas:

Una seccion es un componente reutilizable que representa HTML o una pgina JSP. Una regin describe contenido definiendo secciones. Una plantilla controla la distribucin de la regiones y secciones en una pgina.

Aqu podemos ver una regin y sus secciones

<region:render template='portal.jsp'> <region:put section='banner' content = 'banner.jsp' /> <region:put section = 'controlpanel' content = 'ProfilePane.jsp' /> <region:put section='mainpanel' content = 'mainpanel.jsp' /> <region:put section='footer' content='footer.jsp' /> </region:render>

Una regin define su contenido correspondiendo nombres de secciones lgicas con una porcin de contenido, como banner.jsp. La distribucin de la regin y sus secciones est definida por una plantilla, a la que se asocia cada regin. En este caso, la plantilla se llama portal.jsp, como se define en el siguiente ejemplo:

<region:render section='banner'/> <table width="100%"> <tr align="left" valign="middle"> <td width="20%"> <!-- menu region --> <region:render section='controlpanel' /> </td> <td width="70%" align="center"> <!-- contents --> <region:render section='mainpanel' /> </td> </tr> </table>

Un site con varias vistas y una sola distribucin cosistente tiene un pgina JSP que contiene cdigo que ser similar a la definicin del ejemplo anterior, y muchas pginas JSP que sern similares al primer fragmento de cdigo de esta seccin, que definen regiones y secciones alternativas. Las secciones son fragmentos de pginas JSP que se utilizan como subvistas para construir una vista completa segn se define en la plantilla. Abajo podemos ver la seccin banner.jsp:

<table width="100%" bgcolor="#C0C0C0"> <tr align="left" valign="middle"> <td width="100%"> <TABLE ALIGN="left" BORDER=1 WIDTH="100%"> <TR ALIGN="left" VALIGN="middle"> <TD>Logo</TD> <TD><center>Sun Java Center</TD> </TR> </TABLE> </td> </tr> </table>

Las vistas compuestas son una forma modular, flexible y extensible de construir vistas de pginas JSP para nuestras aplicaciones J2EE.

Patrones Relacionados

View Helper El patrn de vista compuesta se podra utilizar como la vista del patrn View Helper.

Composite [GoF] El patrn de Vista Compuesta est basado en el patrn Composite, que describe las herencias parte-totalidad cuando un objeto compuesto se compone de varias piezas, todas ellas tratadas como equivalente lgicos.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Service to Worker o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

Service to Worker
Contexto
El sistema controla el flujo de ejecucin y accede a los datos de negocio, desde los que crea el contenido de la presentacin.

Nota: El patrn Service to Worker, igual que el patrn Dispatcher View, describe una combinacin comn de otros patrones del catlogo. Estos dos macropatrones describen las combinacin de un controlador y un dispatcher con vistas y helpers. Aunque describen esta estructura comn, cada uno enfatiza un uso diferentes de los patrones.
Problema
El problema es una combinacin de los problemas resueltos por los patrones Front Controller y View Helper de la capa de presentacin. No hay un componente centralizado para manejar el control de acceso, la recuperacin de contenido, o el manejo de la vista, y hay cdigo de control duplicado esparcido por varias vistas. Adems, la lgica de negocio y la de formateo de la presentacin estn mezcladas en esas vistas, haciendo que el sistema sea menos flexible, menos reutilizables y generalmente menos resistente a los cambios. Mezclar lgica de negocio con el procesamiento de la vista tambin reduce la modularidad y proporciona una pobre separacin de roles entre los equipos de produccin Web y de desarrollo de software.

Causas

Los chequeos de autentificacin y autorizacin se completan en cada peticin. El cdigo scriptlet dentro de las vistas se debera minimizar. La lgica de negocio se debera encapsular en componentes distintos a la vista. El control de flujo es relativamente complejo y se basa en valores del contenido dinmico. La lgica de control de la vista es relativamente sofisticada, con varias vistas que potencialmente se mapean a la misma peticin.

Solucin

Combinar un controlador y un dispacher con vistas y helper (ver Front Controller y View Helper) para manejar peticiones de clientes y preparar una presentacin dinmica como respuesta. Los controladores delegan la recuperacin de contenido en los helpers, que manejan el relleno del modelo intermedio para la vista. Un dispatcher es el responsable del control de la vista y la navegacin y puede encapsularse dentro de un controlador o de un componente separado. Service to Worker describe la combinacin de los patrones Front Controller y View Helper con un componente dispatcher. Aunque este patrn y Dispatcher View describen una estructura similar, ambos sugieren diferentes divisiones de la labor entre los componentes. En Service to Worker, el controlador y el dispatcher tienen ms responsabilidades. Aunque los patrones Service to Worker y Dispatcher View representan una combinacin de otros patrones del catlogo, el primero garantiza con su nombre una comunicacin eficiente entre los desarrolladores. Mientras que el segundo sugiere una recuperacin de contenido relegada al momento de procesamiento de la vista. En el patrn Dispatcher View, el dispatcher normalmente juega un rol moderado en el control de la vista. En el patrn Service to Worker, el dispatcher juega un rol algo ms elevado en el control de la vista. Un rol limitado para el dispatcher ocurre cuando no se utiliza recursos exteriores para poder elegir la vista. La informacin encapsulada en la peticin es suficiente para determinar la vista a la que despachar la peticin. Por ejemplo:
http://some.server.com/servlet/Controller?next=login.jsp

La nica responsabilidad del componente dispatcher en este caso es reenviar a la vista login.jsp. Un ejemplo del dispatcher jugando un rol moderado es el caso donde el cliente enva una peticin directamente al controlador con un parmetro de consulta que describe una accin a realizar:
http://some.server.com/servlet/Controller?action=login

Aqu la responsabilidad del dispatcher es traducir el nombre lgico login en el nombre del recurso de una vista apropiada, como login.jsp, y reenviar a esa vista. Para conseguir esta traduccin, el dispatcher podra acceder a recursos como un fichero de configuracin XML que especifica las vistas apropiadas a mostrar. Por otro lado, en el patrn Service to Worker, el dispatcher podra invocar servicios de negocio para determinar la vista apropiada que se debe mostrar. La estructrua compartida de Service to Worker y Dispatcher View consiste en un controlador trabajanado con un dispatcher, vistas y helpers.

Estructura
En la siguiente figura podemos ver el diagrama de clases que representa al patrn Service to Worker.

Participantes y Responsabilidades
La siguiente figura muestra el diagrama de secuencia que representa al patrn Service to Worker.

Como hemos comentado, Service to Worker y Dispatcher View representan una estructura similar. La principal diferencia es que Service to Worker describe arquitecturas con un comportamiento ms up front (ms cercano) al controlador y al dispatcher, mientras que Dispatcher View describe arquitecturas donde se ha movido ms comportamiento al momento del procesamiento de la vista. As, los patrones sugieren una continuidad, donde el comportamiento se ha encapsulado ms cerca de la vista o se ha movido haca atrs en el flujo de proceso.

Controller
El controlador normalmente es el punto de contacto inicial para manejar una peticin. Funciona con un dispatcher para completar el control de la vista y la navegacin. El controlador maneja la autentificacin, la autorizacin, la recuperacin de contenido, la validacin y otros aspectos del manejo de la peticin. Delega en los helpers para completar partes de este trabajo.

Dispatcher

Un dispatcher es el responsable del control de la vista y la navegacin, controlando la eleccin de la siguiente vista a mostrar y proporciona el mecanismo para dirigir el control a este recurso. Un dispatcher se puede encapsular dentro de un controlador (ver Front Controller) o puede ser un componente independiente que trabaja en coordinacin con el controlador. El dispatcher puede proporcionar reenvo esttico a la vista o podra proporcionar un mecanismo de reenvo dinmico ms sofisticado. El dispatcher utiliza el objeto RequestDispatcher (soportado en la especificacin Servlet), pero tambin encapsula alguna informacin de procesamiento adicional. Cuantas ms responsabilidades encapsule este componente, ms se acercar al ideal del patrn Service to Worker. Y al controlario, cuando el diapatcher juega un papel ms limitado, ms se acercar al ideal del patrn Dispatcher View.

View
Una Vista representa una presentacin de informacin al cliente. La informacin utilizada en esta presentacin se recupera de un modelo. Los helpers soportan vistas encapsulando y adaptando un modelo para utilizarlo en una presentacin.

Helper
Un helper es el responsable de ayudar a la vista o al controlador a completar su procesamiento. As, los helpers tienen numerosas responsabilidades, incluyendo la obtencin de los datos requeridos por la vista y almacenndolos en el modelo intermedio, en cuyo caso el helper es conocido como un value bean. Adems, los helpers podran adaptar este modelo de datos para que los utilice la vista. Los helpers pueden servir peticiones de datos desde la vista simplemente proporcionando acceso a los datos en bruto o formatendolos como contenido Web. Una vista podra trabajar con cualquier nmero de helpers, que normalmente estn implementados por componentes JavaBeans (JSP 1.0+) o componentes de etiquetas personalidas (JSP 1.1+). Adems, un helper podra representar un objeto Command o delegate.

ValueBean
Un value bean es otro nombre para un helper que es responsable de contener el estado del modelo intermedio para que lo utilice una vista.

BusinessService
Servicio de Negocio es un rol que cumple el servicio al que el cliente quiere acceder. Normalmente, se accede al servicio de negocio mediante un Business delegate. El rol del business delegate es proporcionar control y proteccin para el servicio de negocio (puedes ver el patrn "Business Delegate" ms adelante).

Estrategias

Servlet Front
Ver la estrategia "Servlet Front" en el patrn Front Controller.

JSP Front
Ver la estrategia "JSP Front" en el patrn Front Controller.

JSP page View


Ver la estrategia "JSP page View" en el patrn View Helper.

Servlet View
Ver la estrategia "Servlet View" en el patrn View Helper.

JavaBean Helper
Ver la estrategia "JavaBean Helper" en el patrn View Helper.

Custom Tag Helper


Ver la estrategia "Custom Tag Helper" en el patrn View Helper.

Dispatcher in Controller
Ver la estrategia "Dispatcher in Controller" en el patrn Front Controller. Como hemos visto, los patrones Service to Worker y Dispatcher View sugieren una continuidad, donde el comportamiento se ha encapsulado ms cerca de la vista o se ha movido haca atrs en el flujo de proceso. La siguiente figura describe un escenario en el que se ha cargado al controlador con mucho trabajo, pero la funcionalidad del dispatcher es mnima.

Transformer Helper
Ver la estrategia "Transformer Helper" en el patrn View Helper.

Consecuencias

Centraliza el Control y Mejora la Modularidad y la Reutilizacin Este patrn sugiere proporcionar un lugar central para manejar los servicios del sistema y la lgica de negocio entre varias peticiones. El contolador maneja el procesamiento de la lgica de negocio y el manejo de peticiones. Hay que tener en cuenta, que como control centralizado, es posible introducir un slo unto de fallo. El patrn tambin promueve el particionamiento de la aplicacin y aconseja la reutilizacin. El cdigo comn se mueve dentro de un controlador y es reutilizado por las peticiones y movido dentro de componentes helpers, en los que delegan los controladores y las vistas. La mejora de

modularidad y de reutilizacin significa menos duplicacin de cdigo, que normalmente significa en entorno ms libre de bugs.

Mejora el Particionamiento de la Aplicacin La utilizacin de helpers resulta en una separacin clara entre la vista y el procesamiento de negocio en una aplicacin. Los helpers, en la forma de JavaBeans (JSP 1.0+) o etiquetas personalizadas (JSP 1.1+), proporcionan un lugar donde construir la lgica de negocio fuera de la pgina JSP. Si la lgica de negocio se deja dentro de la pgina JSP, los grandes proyectos resultan embrollados. Mejora la Separacin de Roles Al separar la lgica de formateo de la lgica de negocio de la aplicacin tambin se reducen las dependencias de los mismos recursos entre individuos que cumplen diferentes roles. Sin esta separacin, por ejemplo, un desarrollador de sofware poseera cdigo que est embebido dentro de marcas HTML, mientras que un miembro del equipo de produccin Web necesitara modificar la distribucin de una pgina y disear componentes que estn mezclados con lgica de negocio. Como ningn individuo que cumple estos roles est familiarizado con las implementaciones especficas del trabajo del otro individuo, se puede llegar a un punto de confusin en que las modificaciones accidentales introduzcan errores el sistema.

Cdigo de Ejemplo
Los siguientes fragmentos de cdigos muestran una implementacin del patrn Service to Worker, utilizando un servlet controlador, un helper command, un componente dispatcher y una vista. La implementacin incluye las estrategias Servlet Front, Command and Controller, JSP View y JavaBean Helper. Tambin se utiliza una vista compuesta muy bsica, como se puede ver en la siguiente imagen:

El siguiente ejemplo muestra el controlador servlet, que delega en un objeto Command para completar el procesamiento del control. El objeto Command se recupera mediante una llamada a la factora, que devuelve un Command de tipo genrico, como veremos ms adelante. El ejemplo utiliza un LogManager para guardar mensajes.

public class Controller extends HttpServlet { /** Processes requests for both HTTP * <code>GET</code> and <code>POST</code> methods. * @param request servlet request

* @param response servlet response */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { String next; try { // Log pattern info LogManager.recordStrategy(request, "Service To Worker", " ServletFront Strategy;" + " JSPView Strategy; JavaBean helper Strategy"); LogManager.logMessage(request, getSignature(), "Process incoming request. "); // Use a helper object to gather parameter // specific information. RequestHelper helper = new RequestHelper(request, response); LogManager.logMessage(request, getSignature(), "Getting command object helper"); // Get command object helper Command command = helper.getCommand(); // delegate processing to the command object, // passing request and response objects along next = command.execute(helper); /** * * * * * * * If the above command returns a value, we will dispatch from the controller. In this example, though, the command will use a separate dispatcher component to choose a view and dispatch to that view. The command object delegates to this dispatcher component in its execute method, above, and control should not return to this point **/

} catch (Exception e) { LogManager.logMessage( "EmployeeController(CommandStrategy)", e.getMessage() ); /** ApplicationResources provides a simple API * for retrieving constants and other * preconfigured values**/ next = ApplicationResources.getInstance(). getErrorPage(e); } dispatch(request, response, next); } /** Handles the HTTP <code>GET</code> method. * @param request servlet request * @param response servlet response */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Handles the HTTP <code>POST</code> method. * @param request servlet request * @param response servlet response */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Returns a short description of the servlet. */ public String getServletInfo() { return getSignature(); } /** dispatcher method */ protected void dispatch(HttpServletRequest request, HttpServletResponse response, String page) throws javax.servlet.ServletException, java.io.IOException { RequestDispatcher dispatcher =

getServletContext().getRequestDispatcher(page); dispatcher.forward(request, response); } public void init(ServletConfig config) throws ServletException { super.init(config); } public void destroy() { } private String getSignature() { return "ServiceToWorker-Controller"; } }

En el siguiente fragmento tenemos el interface Command:

public interface Command { public String execute(RequestHelper helper) throws javax.servlet.ServletException, java.io.IOException; }

Todo objeto command implementa este interface genrico, que es un ejemplo del patrn Command de GoF. El objeto command es un ejemplar de la clase ViewAccountDetails, que podemos ver abajo. El ejemplar de command delega en un AccountingAdapter para hacer una llamada a la capa de negocio mediante Business Delegate.

public class ViewAccountDetailsCommand implements Command { public ViewAccountDetailsCommand() { } // view account details operation public String execute(RequestHelper helper) throws javax.servlet.ServletException, java.io.IOException { /** This will tell the user that a system error * has occured and will typically not be seen. It * should be stored in a resource file **/ String systemerror = "/jspdefaultprocessingerror.jsp"; LogManager.logMessage(helper.getRequest(), "ViewAccountDetailsCommand", "Get Account Details from an adapter object"); /** Use an adapter to retrieve data from business * service, and store it in a request attribute. * Note: Object creation could be avoided via * factory, but for example purposes object * instantiation is shown **/ AccountingAdapter adapter = new AccountingAdapter(); adapter.setAccountInfo(helper); LogManager.logMessage(helper.getRequest(), "ViewAccountDetailsCommand", "processing complete"); /** Note: Object creation could be avoided via * factory, but for example purposes object * instantiation is shown**/ Dispatcher dispatcher = new Dispatcher(); dispatcher.dispatch(helper); /** This return string will not be sent in a * normal execution of this scenario, because * control is forwarded to another resource * before reaching this point. Some commands do * return a String, though, so the return value * is included for correctness. **/ return systemerror; } }

La clase adaptador, mostrada en el siguiente ejemplo, utiliza una componente dispatcher independiente para determinar la siguiente vista a la que se debera reenviar el control y para reenviar realmente el control a esa vista.

public class AccountingAdapter { public void setAccountInfo( RequestHelper requestHelper) { LogManager.logMessage( requestHelper.getRequest(), "Retrieving data from business tier"); // retrieve data from business tier via // delegate. Omit try/catch block for brevity. AccountDelegate delegate = new AccountDelegate(); AccountTO account = delegate.getAccount( requestHelper.getCustomerId(), requestHelper.getAccountKey()); LogManager.logMessage( requestHelper.getRequest(), "Store account Transfer Object in request attribute"); // transport data using request object requestHelper.getRequest().setAttribute( "account", account); } }

La invocacin del servicio de negocio mediante el delegado tiene que ver con un objeto Account Transfer, que el adaptador almacena en un atributo de la peticin para utilizarlo en la vista. El siguiente ejemplo muestra accountdetails.jsp, la pgina JSP que despachar la peticin. El objeto Transfer Object se importa mediante la etiqueta estndar <jsp:useBean> y se accede a sus propiedades utilizando la etiqueta estndar <jsp:getProperty>. La vista tambin utiliza una estrategia Composite muy simple, haciendo la inclusin de la subvista trace.jsp durante la traduccin, est subvista es la responsable de guardar informacin de la presentacin slo para propsitos de ejemplo.

<html> <head><title>AccountDetails</title></head> <body> <jsp:useBean id="account" scope="request" class="corepatterns.util.AccountTO" /> <h2><center> Account Detail for <jsp:getProperty name="account" property="owner" /> </h2> <br><br> <table border=3> <tr> <td> Account Number : </td> <td> <jsp:getProperty name "account" property="number" /> </td> </tr> <tr> <td> Account Type: </td> <td> <jsp:getProperty name="account" property="type" /> </td> </tr> <tr> <td> Account Balance: </td> <td> <jsp:getProperty name="account" property="balance" /> </td> </tr> <tr> <td>

OverDraft Limit: </td> <td> <jsp:getProperty name="account" property="overdraftLimit" /> </td> </tr> </table> <br> <br> </center> <%@ include file="/jsp/trace.jsp" %> </body> </html>

Patrones Relacionados

Front Controller y View Helper El patrn Service to Worker es el resultado de combinar el patrn View Helper con un dispatcher, en coordinacin con el patrn Front Controller. Dispatcher View El patrn Dispatcher View es otro nombre para la combinacin del patrn Front Controller con un dispatcher, y el patrn View Helper. Los patrones Service to Worker y Dispatcher View son idnticos con respecto a los componentes implicados, pero son diferentes en la divisin de labores entre esos componentes. El patrn Dispatcher View siguiere relegar la recuperacin de contenido al momento en que se procesa la vista. Adems, el dispatcher juega un rol ms limitado en el control de la vista, ya que la eleccin de le vista normalmente ya est incluida en la peticin.

Catlogo de Patrones de Diseo J2EE. I.- Capa de Presentacin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Dispatcher View o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

Dispatcher View
Contexto
El sistema controla el flujo de ejecucin y accede al proceso de presentacin, que es el responsable de generar el el contenido dinmico.

Nota: El patrn Dispatcher View, igual que el patrn Service to Worker, describe una combinacin comn de otros patrones del catlogo. Estos dos macropatrones describen la combinacin de un controlador y un dispatcher con vistas y helpers. Aunque describen esta estructura comn, cada uno enfatiza un uso diferente de los patrones.
Problema
El problema es una combinacin de los problemas resueltos por los patrones Front Controller y View Helper de la capa de presentacin. No hay un componente centralizado para manejar el control de acceso, la recuperacin de contenido, o el manejo de la vista, y hay cdigo de control duplicado esparcido por varias vistas. Adems, la lgica de negocio y la de formateo de la presentacin estn mezcladas en esas vistas, haciendo que el sistema sea menos flexible, menos reutilizable y generalmente menos resistente a los cambios. Mezclar lgica de negocio con el procesamiento de la vista tambin reduce la modularidad y proporciona una pobre separacin de roles entre los equipos de produccin Web y de desarrollo de software.

Causas

Los chequeos de autentificacin y autorizacin se completan en cada peticin. El cdigo scriptlet dentro de las vistas se debera minimizar. La lgica de negocio se debera encapsular en componentes distintos a la vista. El control de flujo es relativamente complejo y se basa en valores del contenido dinmico. La lgica de control de la vista es relativamente sofisticada, con varias vistas que potencialmente se mapean a la misma peticin.

Solucin

Combinar un controlador y un dispatcher con vistas y helpers (ver Front Controller y View Helper) para manejar peticiones de clientes y preparar una presentacin dinmica como respuesta. Los controladores delegan la recuperacin de contenido en los helpers, que manejan el relleno del modelo intermedio para la vista. Un dispatcher es el responsable del control de la vista y la navegacin y puede encapsularse dentro de un controlador o de un componente separado. Dispatcher View describe la combinacin de los patrones Front Controller y View Helper con un componente dispatcher. Aunque este patrn y Service to Worker describen una estructura similar, ambos sugieren diferentes divisiones de la labor entre los componentes. El controlador y el dispatcher tienen responsabilidades limitadas, comparadas con el patrn Service to Worker, porque la lgica de procesamiento y de control de vista son bsicas. Adems, si no se considera necesario el control de los recursos subyacentes, se puede eliminar el controlador y el dispatcher se podra mover dentro de una vista. Aunque los patrones Service to Worker y Dispatcher View representan una combinacin de otros patrones del catlogo, el primero garantiza con su nombre una comunicacin eficiente entre los desarrolladores. Mientras que el segundo sugiere una recuperacin de contenido relegada al momento de procesamiento de la vista. En el patrn Dispatcher View, el dispatcher normalmente juega un rol moderado en el control de la vista. En el patrn Service to Worker, el dispatcher juega un rol algo ms elevado en el control de la vista. Un rol limitado para el dispatcher ocurre cuando no se utilizan recursos exteriores para poder elegir la vista. La informacin encapsulada en la peticin es suficiente para determinar la vista a la que despachar la peticin. Por ejemplo:
http://some.server.com/servlet/Controller?next=login.jsp

La nica responsabilidad del componente dispatcher en este caso es reenviar a la vista login.jsp. Un ejemplo del dispatcher jugando un rol moderado es el caso donde el cliente enva una peticin directamente al controlador con un parmetro de consulta que describe una accin a realizar:
http://some.server.com/servlet/Controller?action=login

Aqu la responsabilidad del dispatcher es traducir el nombre lgico login en el nombre del recurso de una vista apropiada, como login.jsp, y reenviar a esa vista. Para conseguir esta traduccin, el dispatcher podra acceder a recursos como un fichero de configuracin XML que especifica las vistas apropiadas a mostrar. Por otro lado, en el patrn Service to Worker, el dispatcher podra invocar servicios de negocio para determinar la vista apropiada que se debe mostrar. La estructrua compartida de Service to Worker y Dispatcher View consiste en un controlador trabajanado con un dispatcher, vistas y helpers.

Estructura
En la siguiente figura podemos ver el diagrama de clases que representa al patrn Dispatcher View.

Participantes y Responsabilidades
La siguiente figura muestra el diagrama de secuencia que representa al patrn Dispatcher View.

Aunque las responsabilidades del controlador estn limitadas a los servicios del sistema, como la autentificacin y autorizacin, todava es beneficioso centralizar estos aspectos del sistema. Observa tambin que, al contrario que el patrn Service to Worker, el dispatcher no hace llamadas a servicios de negocio para poder completar el procesamiento de la vista. La funcionalidad del dispatcer se podra encapsular en su propio componente. Al mismo tiempo, cuando las responsabilidades del dispatcher son limitadas, como se describen en este patrn, la funcionalidad del dispatcher se puede poner en otro componente, como en el controlador o la vista. De hecho, la funcionalidad del dispatcher podra incluso ser completada por el contenedor, en el caso donde no sea necesaria una lgica extra a nivel de la aplicacin. Un ejemplo es una vista llamada main.jsp a la que se le da el alias de first. El contenedor procesar la siguiente peticin, traduciendo el nombre del alias al nombre del recurso fsico, y reenviando directamente a ese recurso:
http://some.server.com/first --> /mywebapp/main.jsp

En este caso, nos hemos quedado con el patrn View Helper, donde la peticin la maneja directamente la vista. Como la vista es el punto de contacto inicial para manejar peticiones, normalmente se utilizan etiquetas personalizadas para realizar el procesamiento de negocio o para delegar este procesamiento a otros componentes.

As, el patrn Dispatcher View describe una continuidad de escenarios relacionados, movindose de un escenario que es estructuralmente similar a Service to Worker a otro que es similar a View Helper.

Controller
El controlador normalmente es el punto de contacto inicial para manejar una peticin. El controlador maneja la autentificacin y la autorizacin, y delega en un dispatcher para hacer el control de la vista.

Dispatcher
Un dispatcher es el responsable del control de la vista y la navegacin, controlando la eleccin de la siguiente vista a mostrar y proporciona el mecanismo para dirigir el control a este recurso. Un dispatcher se puede encapsular dentro de un controlador (ver Front Controller) o puede ser un componente independiente que trabaja en coordinacin con el controlador. El dispatcher puede proporcionar reenvo esttico a la vista o podra proporcionar un mecanismo de reenvo dinmico ms sofisticado.

View
Una Vista representa una presentacin de informacin al cliente. La informacin utilizada en esta presentacin se recupera de un modelo. Los helpers soportan vistas encapsulando y adaptando un modelo para utilizarlo en una presentacin.

Helper
Un helper es el responsable de ayudar a la vista o al controlador a completar su procesamiento. As, los helpers tienen numerosas responsabilidades, incluyendo la obtencin de los datos requeridos por la vista y almacenndolos en el modelo intermedio, en cuyo caso el helper es conocido como un value bean. Adems, los helpers podran adaptar este modelo de datos para que los utilice la vista. Los helpers pueden servir peticiones de datos desde la vista simplemente proporcionando acceso a los datos en bruto o formatendolos como contenido Web. Una vista podra trabajar con cualquier nmero de helpers, que normalmente estn implementados por componentes JavaBeans (JSP 1.0+) o componentes de etiquetas personalidas (JSP 1.1+). Adems, un helper podra representar un objeto Command o delegate.

ValueBean
Un value bean es otro nombre para un helper que es responsable de contener el estado del modelo intermedio para que lo utilice una vista.

BusinessService
Servicio de Negocio es un rol que cumple el servicio al que el cliente quiere acceder. Normalmente, se accede al servicio de negocio mediante un Business delegate. El rol del business delegate es proporcionar control y proteccin para el servicio de negocio (puedes ver el patrn "Business Delegate" ms adelante).

Estrategias

Servlet Front
Ver la estrategia "Servlet Front" en el patrn Front Controller.

JSP Front

Ver la estrategia "JSP Front" en el patrn Front Controller.

JSP page View


Ver la estrategia "JSP page View" en el patrn View Helper.

Servlet View
Ver la estrategia "Servlet View" en el patrn View Helper.

JavaBean Helper
Ver la estrategia "JavaBean Helper" en el patrn View Helper.

Custom Tag Helper


Ver la estrategia "Custom Tag Helper" en el patrn View Helper.

Dispatcher in Controller
Ver la estrategia "Dispatcher en Controller" en el patrn Front Controller. Como hemos visto, los patrones Service to Worker y Dispatcher View sugieren una continuidad, donde el comportamiento se ha encapsulado ms cerca de la vista o se ha movido haca atrs en el flujo de proceso. La siguiente figura muestra las interacciones para esta estrategia:

El controlador no crea explicitmente un objeto dispatcher. En vez de eso, el controlar tiene cuidado de reenviar a la vista. Alternativamente, se podra implementar un dispatcher en el que el controldor puede delegar la funcin de reenvo.

Dispatcher in View
Si el controlador se eliminara debido a su rol limitado, el dispatcher se podra mover a una vista. Este diseo puede ser til en casos donde es tpico que una vista mapee a una peticin especfica, pero donde

se podra utilizar de forma poco frecuente un vista secundaria. Por ejemplo, basndose en la informacin de la peticin o los resultados de algn procesamiento de la vista, un helper de etiqueta personalizada en la vista podra dirigir el control a una vista secundaria. Un caso tpico es cuando una peticin de cliente es reenviada a una vista especfica, y ser servida por esa vista en cualquier otro caso. Consideremos el caso donde el usuario no se ha autentificado, pero pide acceso a unas pginas JSP protegidas de la site. Como la site tiene slo unas pocas pginas JSP protegidas, y el contenido dinmico es limitado, la autentificacin se puede realizar dentro de esas pginas JSP, en lugar de utilizar un controlador centralizado para toda la site. Esas pginas que necesitan autentificacion incluyen un helper de etiqueta personalizada al principio de la pgina. Este helper realiza el chequeo de autentificacin y muestra la pgina al usuario o lo reenva a la pgina de autentificacin. La siguiente figura representa este escenario:

Transformer Helper
Ver la estrategia "Transformer Helper" en el patrn View Helper.

Consecuencias

Centraliza el Control y Mejora la Modularidad y la Reutilizacin Este patrn sugiere proporcionar un lugar central para manejar los servicios del sistema y la lgica de negocio entre varias peticiones. El contolador maneja el procesamiento de la lgica de negocio y el manejo de peticiones. Hay que tener en cuenta, que como control centralizado, es posible introducir un slo unto de fallo. Mejora el Particionamiento de la Aplicacin La utilizacin de helpers resulta en una separacin clara entre la vista y el procesamiento de negocio en una aplicacin. Los helpers, en la forma de JavaBeans (JSP 1.0+) o etiquetas personalizadas (JSP 1.1+), proporcionan un lugar donde construir la lgica de negocio fuera de la pgina JSP. Si la lgica de negocio se deja dentro de la pgina JSP, los grandes proyectos resultan embrollados. Mejora la Separacin de Roles Al separar la lgica de formateo de la lgica de negocio de la aplicacin tambin se reducen las dependencias de los mismos recursos entre individuos que cumplen diferentes roles. Sin esta separacin, por ejemplo, un desarrollador de sofware poseera cdigo que est embebido dentro de marcas HTML, mientras que un miembro del equipo de produccin Web necesitara modificar la distribucin de una pgina y disear componentes que estn mezclados con lgica de negocio. Como ningn individuo que cumple estos roles est familiarizado con las implementaciones especficas del trabajo del otro individuo, se puede llegar a un punto de confusin en que las modificaciones accidentales introduzcan errores el sistema.

Cdigo de Ejemplo
El siguiente cdigo de ejemplo muestra una implementacin del patrn Dispatcher View, utilizando un servlet controlador y una vista con helpers JavaBean y de etiquetas personalizadas. La implementacin incluye las estrategias Servlet Front, Dispatcher in Controller, JSP View, JavaBean Helper y Custom Tag Helper. Tambin utiliza una vista compuesta muy bsica, mostrada en la siguiente imagen:

El siguiente ejemplo muestra el servlet controlador que simplemente completa el chequeo de autentificacin y pasa el control a la vista apropiada. Observa que el controlador no delega directamente a ningn componente helper para poder hacer llamadas a la capa de negocio mediante Delegate. Ests responsabilidades se han relegado a la vista, que se llama accountdetails.jsp. El cdigo de ejemplo utiliza un LogManager para guardar los mensajes.

public class Controller extends HttpServlet { /** Processes requests for both HTTP * <code>GET</code> and <code>POST</code> methods. * @param request servlet request * @param response servlet response */ protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { String nextview; try { LogManager.recordStrategy(request, "Dispatcher View", " Servlet Front Strategy; " + "JSP View Strategy; Custom tag helper Strategy"); LogManager.logMessage(request, getSignature(), "Process incoming request. "); // Use a helper object to gather parameter // specific information. RequestHelper helper = new RequestHelper(request, response); LogManager.logMessage(request, getSignature(), " Authenticate user"); Authenticator auth = new BasicAuthenticator(); auth.authenticate(helper); //This is an oversimplification for the sake of // simplicity. Typically, there will be a // mapping from logical name to resource name at // this point LogManager.logMessage(request, getSignature(),

"Getting nextview"); nextview = request.getParameter("nextview"); LogManager.logMessage(request, getSignature(), "Dispatching to view: " + nextview); } catch (Exception e) { LogManager.logMessage( "Handle exception appropriately", e.getMessage() ); /** ApplicationResources provides a simple API * for retrieving constants and other * preconfigured values**/ nextview = ApplicationResources.getInstance(). getErrorPage(e); } dispatch(request, response, nextview); } /** Handles the HTTP <code>GET</code> method. * @param request servlet request * @param response servlet response */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Handles the HTTP <code>POST</code> method. * @param request servlet request * @param response servlet response */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { processRequest(request, response); } /** Returns a short description of the servlet. */ public String getServletInfo(){ return getSignature(); } public void init(ServletConfig config) throws ServletException { super.init(config); } public void destroy() { } /** * dispatcher method */ protected void dispatch(HttpServletRequest request, HttpServletResponse response, String page) throws javax.servlet.ServletException, java.io.IOException { RequestDispatcher dispatcher = getServletContext(). getRequestDispatcher(page); dispatcher.forward(request, response); } private String getSignature() { return "DispatcherView-Controller"; } }

Observa que la vista utiliza helpers de etiquetas personalizadas para controlar la recuperacin de contenido. ya que esta actividad no se realiz en el controlador. Cuando se utilizan las etiquetas personalizadas de esta forma, normalmente se convierten en estrechas fachadas para componentes solitarios en los que delegar para completar este procesamiento. De esta forma, la lgica de procesamiento general est pobremente acoplada a la implementacin de la etiqueta. Si no se utilizan etiquetas personalizadas con Dispatcher View, la pgina JSP se terminar llenando de cdgio scriptlet, una situacin que debemos evitar.

<%@ taglib uri="/web-INF/corepatternstaglibrary.tld" prefix="corepatterns" %> <html>

<head><title>AccountDetails</title></head> <body> <corepatterns:AccountQuery queryParams="custid,acctkey" scope="request" /> <h2><center> Account Detail for <corepatterns:Account attribute="owner" /></h2> <br><br> <tr> <td>Account Number :</td> <td><corepatterns:Account attribute="number" /></td> </tr> <tr> <td>Account Type:</td> <td><corepatterns:Account attribute="type" /></td> </tr> <tr> <td>Account Balance:</td> <td><corepatterns:Account attribute="balance" /></td> </tr> <tr> <td>OverDraft Limit:</td> <td><corepatterns:Account attribute="overdraftLimit" /></td> </tr> <table border=3> </table> </corepatterns:AccountQuery> <br> <br> </center> <%@ include file="/jsp/trace.jsp" %> </body> </html>

Patrones Relacionados

Front Controller y View Helper El patrn Dispatcher View es el resultado de combinar el patrn View Helper con un dispatcher, en coordinacin con el patrn Front Controller. Service to Worker El patrn Service to Worker es otro nombre para la combinacin del patrn Front Controller con un dispatcher, y el patrn View Helper. Los patrones Service to Worker y Dispatcher View son idnticos con respecto a los componentes implicados, pero son diferentes en la divisin de labores entre esos componentes. El patrn Dispatcher View siguiere relegar la recuperacin de contenido al momento en que se procesa la vista. Adems, el dispatcher juega un rol ms limitado en el control de la vista, ya que la eleccin de le vista normalmente ya est incluida en la peticin.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Puedes encontrar la versin original de este tutorial en Ingls en: http://java.sun.com/blueprints/corej2eepatterns/Patterns/index.html

Busisness Delegate o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo: Implementar el Patrn Business Delegate o Patrones Relacionados Service Locator o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Patrn Service Locator Implementar la Estrategia Type Checked Service Locator o Patrones Relacionados Session Facade o Contexto o Problema o Causas o Solucin Estructura Participantes y Colaboraciones Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Session Facade o Patrones Relacionados Transfer Object o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el patrn Transfer Object Implementar la Estrategia Updatable Transfer Objects Implementar la Estrategia Multiple Transfer Objects Implementar la Estrategia Entity Inherits Transfer Object Implementar la Estrategia Transfer Object Factory o Patrones Relacionados Transfer Object Assembler o Contexto o Problema

o o

Causas Solucin

Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Transfer Object Assembler o Patrones Relacionados Value List Handler o Contexto o Problema o Causas o Solucin Estructura Participantes y Colaboraciones Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Value List Handler como un objeto Java o Patrones Relacionados Composite Entity o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Codigo de Ejemplo Implementacin del patrn Composite Entity Implementar la Estrategia Lazy Loading Implementar la Estrategia Store Optimization (Dirty Marker) Implementar la Estrategia Composite Transfer Object o Patrones Relacionados o Bean de Entidad como un Objeto Dependiende: Problemas y Recomendaciones Data Access Object o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Patrn Data Access Object Implementar la Estrategia Factory for Data Access Objects o Patrones Relacionados Service Activator o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Busisness Delegate o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo: Implementar el Patrn Business Delegate o Patrones Relacionados

Busisness Delegate
Contexto
Un sistema multi-capa distribuido requiere invocacin remota de mtodos para enviar y recibir datos entre las capas. Los clientes estn expuestos a la complejidad de tratar con componentes distribuidos.

Problema
Los componentes de la capa de presentacin interactan directamente con servicios de negocio. Esta interaccin directa expone los detalles de la implementacin del API del servicio de negocio a la capa de presentacin. Como resultado, los componentes de la capa de presentacin son vulnerables a los cambios en la implementacin de los servicios de negocio: cuando cambia la implementacin del servicio de negocio, la implementacin del codigo expuesto en la capa de presentacin tambin debe cambiar. Adems, podra haber una reduccin de rendimiento en la red porque los componentes de la capa de presentacin que utilizan el API de servicio de negocio hacen damasiadas invocaciones sobre la red. Esto sucede cuando los componentes de la capa de presentacin usan directamente el API subyacente, sin cambiar el mecanismo del lado del cliente o agregar servicios. Por ltimo, exponer directamente los APIs de servicios al cliente fuerza a ste a tratar con los problemas de red asociados con la naturaleza distribuida de la tecnologa Enterprise JavaBeans (EJB).

Causas

Los clientes de la capa de presentacin necesitan acceder a servicios de negocio. Diferentes clientes, dispositivos, clientes Web, y programas, necesitan acceder a los servicios de negocio. Los APIs de los servicios de negocio podran cambiar segn evolucionan los requerimientos del negocio. Es deseable miniminar el acoplamiento entre los clientes de la capa de presentacin y los servicios de negocio, y as ocultar los detalles de la implementacin del servicio. Los clientes podran necesitar implementar mecanismos de cach para la informacin del servicio de negocio. Es deseable reducir el trfico de red entre el cliente y los servicios de negocio.

Solucin
Utilizamos un Business Delegate para reducir el acoplamiento entre los clientes de la capa de presentacin y los servicios de negocio. El Business Delegate oculta los detalles de la

implementacin del servicio de negocio, como los detalles de bsqueda y acceso de la arquitectura EJB. El Business Delegate acta como una abstraccin de negocio del lado del cliente; proporciona una abstraccin para, y por lo tanto oculta, la implementacin de los servicios del negocio. Utilizando Business Delegate se reduce el acoplamiento entre los clientes de la capa de presentacin y los servicios de negocio del sistema. Dependiendo de la estrategia de implementacin, Business Delegate podra aislar a los clientes de la posible volatilidad en la implementacin del API de los servicios de negocio. Potencialmente, esto reduce el nmero de cambios que se deben hacer en el cdigo de cliente de la capa de presentacin cuando cambie el API del servicio de negocio o su implementacin subyacente. Sin embargo, los mtodos de interface en el Business Delegate an podra requerir modificaciones si cambia el API del servicio de negocio. Si bien es cierto, que los cambios se harn con ms probabilidad en el servicio de negocio que en el Business Delegate. Con frecuencia, los desarrolladores son excpticos cuando un objetivo de diseo como la abstraccin de la capa de negocio provoca un trabajo adicional como pago por futuras ganancias. Sin embargo, utilizando este patrn o esta estrategia resulta slo en una pequea cantidad de trabajo extra y proporciona unos beneficios considerables. El principal beneficio es ocultar los detalles del servicio. Por ejemplo, el cliente puede ser transparente para los servicios de bsqueda y nombrado. El Business Delegate tambin maneja las excepciones de los servicios de negocio, como excepciones java.rmi.Remote, excepciones Java Messages Service (JMS), etc. El Business Delegate podra interceptar dichas excepciones a nivel de servicio y generar en su lugar excepciones a nivel de aplicacin. Las excepciones de nivel de aplicacion son fciles de manejar por los clientes, y pueden ser amigables para el usuario. El Business Delegate tambin podra realizar de forma transparene cualquier operacin de reintento o de recuperacin necesaria en el caso de un fallo en el servicio no exponer el cliente al problema hasta que se haya determinado que el problema no es solucionable. Estas ganancias representan una razn competitiva para utilizar el patrn. Otro beneficio es que el delegado podra almacenar resultados y referencias a servicios de negocio remotos. El Cach puede mejorar el rendimiento de forma significativa, porque limita los innecesarios y potencialmente costosos viajes por la red. Un Business Delegate utiliza un componente llamado Lookup Service. Este componente es el responsable de ocultar los detalles de implementacin de cdigo de bsqueda del servicio de negocio. El Lookup Service podra estar escrito como parte del Delegate, pero recomendamos que se implemente como un componento separado. Cuando el Business Delegate se utiliza con un Session Facade, normalmente hay una relacin uno-auno entre los dos. Esta relacin existe porque la lgica que podra haber sido encapsulada en un Business Delegate en relacin a su interaccin con varios servicios de negocio (creando una relacin uno-a-uno) normalmente se construye de vuelta en un Session Facade. Finalmente, se debera tener en cuenta que este patrn se podra utilizar para reducir el acoplamiento entre otra capas, no simplemente entre las capas de presentacin y de negocio.

Estructura
La siguiente figura muestra el diagrama de clases que representa al patrn Business Delegate. El cliente solicita al BusinessDelegate que le proporcione acceso al servicio de negocio subyacente. El BusinessDelegate utiliza un LookupService para localizar el componente BusinessService requerido.

Participantes y Responsabilidades
Ls siguiente figura muestra el diagrama de secuencia que ilustra las interacciones tpicas para este patrn:

El BusinessDelegate utiliza un LookupService para localizar el servicio de negocio. El servicio de negocio se utiliza para invocar a los mtodos de negocio por cuenta del cliente. El mtodo Get_ID muestra que el BusinessDelegate puede obtener una versin String del handle (como un objeto EJBHandle) para el servicio de negocio y devolverlo al cliente como un String. El cliente puede utilizar la versin String del handle ms tarde para reconectar con el servicio de negocio que estaba utilizando cuando obtuvo el handle. Esta tcnica evitar nuevas bsquedas, ya que el handle es capz de reconectar con su ejemplar del servicio de negocio. Se debera observar que los objetos handle los implementa el contenedor y podran no ser portables entre contenedores de diferentes vendedores. El diagrama de secuencia de la siguiente figura muestra la obtencin de un BusinessService (como un bean de sesin o de entidad) utilizando este handle.

BusinessDelegate
El rol de BusinessDelegate es proporcionar control y proteccin para el servicio de negocio. BusinessDelegate puede exponer dos tipos de constructores al cliente. Un tipo de peticin ejemplariza el BusinessDelegate sin una ID, mientras que el otro lo inicializa con un ID, donde ID es una versin String de la referencia al objeto remoto como un EJBHome o un EJBObject. Cuando se inicializa sin una ID, el BusinessDelegate solicita el servicio al Lookup Service, normalmente implementado como un Service Locator (ms adelante veremos el patrn Service Locator), que devuelve el Service Factory, como un EJBHome. El BusinessDelegate pide que el Service Factory localice, cree o elimine un BusinessService, como un bean enterprise. Cuando se inicializa con un ID, el BusinessDelegate usa el ID para reconectar con el BusinessService. As, el BusinessDelegate aisla al cliente de los detalles de la implementacin del BusinessService de nombrado y bsqueda. Adems, el cliente de la capa de presentacin nunca hace llamadas remotas directas sobre un BusinessSession; en su lugar, el cliente utiliza el BusinessDelegate.

LookupService
BusinessDelegate utiliza el objeto LookupService para localizar a BusinessService. LookupService encapsula los detalles de la implementacin de la bsqueda de BusinessService.

BusinessService
BusinessService

es un componente de la capa de negocio, como un bean enterprise o un componente JMS, que proprociona el servicio requerido por el cliente.

Estrategias

Delegate Proxy
El Business Delegate expone un interface que proporciona a los clientes acceso a los mtodos subyacentes del API de servicios de negocio. En esta estrategia, un Business Delegate proporciona la funcin de proxy para pasar los mtodos del cliente al bean de sesin que encapsula. Adicionalmente el Business Delegate podra hacer un cach con los datos necesarios, incluyendo las referencias remotas de los objetos home o remote del bean de sesin para mejorar el rendimiento reduciendo el nmero de bsquedas. El Business Delegate tambin podra convertir dichas referencias en identificadores de versin (IDs) y viceversa, utilizando los servicios de un Service Locator. El ejemplo de implementacin de esta estrategia se explica en la seccin Cdigo de Ejemplo de esta pgina.

Delegate Adapter
El Business Delegate parece ser bueno en un entorno B2B cuando se comunica con servicios basados en la plataforma J2EE. Los sistemas dispares podran utilizar XML como el lenguaje de integracin. Integrar un sistema en otro normalmente requiere un Adapter [GoF] para unir los dos sistemas dispares. La siguiente figura nos muestra un ejemplo:

Consecuencias

Reduce el Acoplamiento, Mejora la Manejabilidad El Business Delegate reduce el acoplamiento entre la capas de presentacin y de negocio ocultando todos los detalles de implementacin de la capa de negocio. Es fcil manejar los cambios porque estn centralizados en un slo lugar, el Business Delegate. Traduce las Excepciones del Servicio de Negocio El Business Delegate es el responsable de traducir cualquier excepcin de red o relacionada con la infraestructura en excepciones de negocio, aislando a los clientes del conocimiento de las especifidades de la implementacin. Implementa Recuperacin de Fallos y Sincronizacin de Threads Cuando el Business Delegate encuentra un fallo en el servicio de negocio, puede implementar caractersticas de recuperacin automtica sin exponer el problema al cliente. Si la recuperacin tiene xito, el cliente no necesita saber nada sobre el fallo. Si el intento de recuperacin no tiene xito, entonces el Business Delegate necesita informar al cliente del fallo. Adems, los mtodos del Business Delegate podran estar sincronizados, si fuera necesario. Expone un Interface Simple y Uniforme a la Capa de Negocio El Business Delegate, para servir mejor a sus clientes, podra proporcionar una variante del interface proporcionado por los beans enterprise subyacentes. Impacto en el Rendimiento El Business Delegate podra proporcionar servicio de cach (y un mejor rendimiento) a la capa de presentacin para las peticiones de servicios comunes. Presenta una Capa Adicional El Business Delegate podra verse como la adiccin de una capa innecesaria entre el cliente y el servicio, y con eso incrementar la complejidad y disminuir la flexibilidad. Algunos desarrolladores podran sentir esto coomo un esfuerzo extra para desarrollar Business Delegates con implementaciones que utilizan la estrategia Delegate Proxy. Oculta los elementos Remotos Aunque la localizacin transparente es uno de los beneficios de este patrn, podra surgir un problema diferente debido a que el desarrolador est tratanto con un servicio remoto como si

fuera un servicio local. Esto podra suceder si el desarrollador del cliente no entiende que el Business Delegate es cliente-proxy a un servicio remoto. Normalmente, unas llamadas a mtodos en el Business Delegate resultan en unas llamadas a mtodos remotos bajo la envoltura. Ignorando esto, el desarrollador podra tender a realiaar varias llamadas a mtodos para realizar una sola tarea, lo que incrementar el trfico en la red.

Cdigo de Ejemplo: Implementar el Patrn Business Delegate


Consideremos una Aplicacin de Servicios Profesional (PSA), donde un cliente de la capa Web necesita acceder a un bean de sesin que implementa el patrn Session Facade. Se puede aplicar el patrn Business Delegate para disear un clase Delegate como ResourceDelegate, que ecapsula la complejidad de tratar con el bean de sesin ResourceSession. En el siguientre fragmento de cdigo podemos ver la implementacin de la clase ResourceDelegate:

// imports ... public class ResourceDelegate { // Remote reference for Session Facade private ResourceSession session; // Class for Session Facade's Home object private static final Class homeClazz = corepatterns.apps.psa.ejb.ResourceSessionHome.class; // Default Constructor. Looks up home and connects // to session by creating a new one public ResourceDelegate() throws ResourceException { try { ResourceSessionHome home = (ResourceSessionHome) ServiceLocator.getInstance().getHome( "Resource", homeClazz); session = home.create(); } catch(ServiceLocatorException ex) { // Translate Service Locator exception into // application exception throw new ResourceException(...); } catch(CreateException ex) { // Translate the Session create exception into // application exception throw new ResourceException(...); } catch(RemoteException ex) { // Translate the Remote exception into // application exception throw new ResourceException(...); } } // Constructor that accepts an ID (Handle id) and // reconnects to the prior session bean instead // of creating a new one public BusinessDelegate(String id) throws ResourceException { super(); reconnect(id); } // Returns a String ID the client can use at a // later time to reconnect to the session bean public String getID() { try { return ServiceLocator.getId(session); } catch (Exception e) { // Throw an application exception } } // method to reconnect using String ID public void reconnect(String id) throws ResourceException { try { session = (ResourceSession) ServiceLocator.getService(id); } catch (RemoteException ex) { // Translate the Remote exception into // application exception throw new ResourceException(...); } }

// // // // // //

The following are the business methods proxied to the Session Facade. If any service exception is encountered, these methods convert them into application exceptions such as ResourceException, SkillSetException, and so forth.

public ResourceTO setCurrentResource( String resourceId) throws ResourceException { try { return session.setCurrentResource(resourceId); } catch (RemoteException ex) { // Translate the service exception into // application exception throw new ResourceException(...); } } public ResourceTO getResourceDetails() throws ResourceException { try { return session.getResourceDetails(); } catch(RemoteException ex) { // Translate the service exception into // application exception throw new ResourceException(...); } } public void setResourceDetails(ResourceTO vo) throws ResourceException { try { session.setResourceDetails(vo); } catch(RemoteException ex) { throw new ResourceException(...); } } public void addNewResource(ResourceTO vo) throws ResourceException { try { session.addResource(vo); } catch(RemoteException ex) { throw new ResourceException(...); } } // all other proxy method to session bean ... }

El siguiente fragmento de cdigo representa el interface remoto correspondiente al bean Session Facade ResourceSession:

// imports ... public interface ResourceSession extends EJBObject { public ResourceTO setCurrentResource( String resourceId) throws RemoteException, ResourceException; public ResourceTO getResourceDetails() throws RemoteException, ResourceException; public void setResourceDetails(ResourceTO resource) throws RemoteException, ResourceException; public void addResource(ResourceTO resource) throws RemoteException, ResourceException; public void removeResource() throws RemoteException, ResourceException; // methods for managing blockout time by the // resource public void addBlockoutTime(Collection blockoutTime) throws RemoteException, BlockoutTimeException; public void updateBlockoutTime( Collection blockoutTime) throws RemoteException, BlockoutTimeException;

public void removeBlockoutTime( Collection blockoutTime) throws RemoteException, BlockoutTimeException; public void removeAllBlockoutTime() throws RemoteException, BlockoutTimeException; // methods for resource skillsets time by the //resource public void addSkillSets(Collection skillSet) throws RemoteException, SkillSetException; public void updateSkillSets(Collection skillSet) throws RemoteException, SkillSetException; public void removeSkillSet(Collection skillSet) throws RemoteException, SkillSetException; ... }

Patrones Relacionados

Service Locator El patrn Service Locator se podra utilizar para crear el servicio de bsqueda del Business Delegate, ocultando los detalles de implementacin de cualquier servicio de bsqueda y cdigo de acceso. Proxy [GoF] Un Business Delegate podra actuar como un proxy, proporcionando suplentes para los objetos en la capa de negocio. Adapter [GoF] Un Business Delegate podra utilizar el patrn Adapter para proporcionar acoplamiento para sistemas dispares. Broker [POSA1] Un Business Delegate realiza el rol de un broker para desacoplar los objetos de la capa de negocio de los clientes de otras capas.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Service Locator o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Patrn Service Locator Implementar la Estrategia Type Checked Service Locator o Patrones Relacionados

Service Locator
Contexto
La bsqueda y creacin de servicios implican interfaces complejos y operaciones de red.

Problema
Los clientes J2EE interactan con componentes de servicio, como componentes JavaBeans Enterprise (EJB) y Java Message Service (JMS), que proporcionan servicios de negocio y capacidades de persistencia. Para interactar con estos componentes, los clientes deben o lcalizar el componente de servicio (referido como una operacin de bsqueda) o crear un nuevo componente. Por ejemplo, un cliente EJB debe localizar el objeto home del bean enterprise, que el cliente puede utilizar para encontrar un objeto o para crear uno o ms beans enterprise. De forma similar, un cliente JMS primero debe localizar la Factora de Conexiones JMS para obtener una Conexin JMS o una Sesin JMS. Todos los clientes de aplicaciones J2EE utilizan la facilidad JNDI para buscar y crear componentes EJB o JMS. El API JNDI permite a los clientes obtener un objeto Contexto Inicial que contiene el nombre del componente a uniones de objetos. El cliente empieza obteniendo el contexto inicial para un objeto home de un bean. El contexto inicial permanece vlido mientras sea vlida la sesin del cliente. El cliente proporciona el nombre registrado en JNDI del objeto requerido para obtener una referencia a un objeto administrado. En el contexto de una aplicacin EJB, un objeto administrado tpico es un objeto home de un bean enterprise. Para aplicaciones JMS, el objeto administrado puede ser una Factora de Conexiones JMS (para un Topic o una Queue) o un Destino JMS (un Topic o una Queue). Por eso, localizar un objeto servicio administrado JNDI es un tarea comn para todos los clientes que necesiten acceder al objeto de servicio. Por ejemplo, es fcil ver que muchos tipos de clientes utilizan repetidamente el servicio JNDI, y que el cdigo JNDI aparece varias veces en esos clientes. Esto resulta en una duplicacin de cdigo innecesaria en los clientes que necesitan buscar servicios. Tambin, crear un objeto de contexto JNDI inicial y realizar una bsqueda para objeto home EJB utiliza muchos recursos. Si varios clientes requieren de forma repetitiva el mismo objeto home de un bean, dicha duplicacin de esfuerzos puede impactar de forma negativa en el rendimiento de la aplicacin. Examinemos el proceso de bsqueda y creacin de varios componentes J2EE. 1. La bsqueda y creacin de Beans Enterprise trata sobre lo siguiente: o Una correcta configuracin del entorno JNDI para que se conecte con el servicio de nombrado y directorio utilizado por la aplicacin. Esta configuracin proporciona la

2.

localizacin del servicio de nombrado y las credenciales de autentificaciones necesarias para acceder a ese servicio. o Entonces el servicio JNDI puede proporcionar al cliente un contexto inicial que acta como un almacen para las uniones de componentes nombre-a-objeto. El cliente solicita a este contexto inicial que busque el objeto EJBHome del bean enterprise requerido proporcionando un nombre JNDI para ese objeto EJBHome. o Encontrar el objeto EJBHome utilizando el contexto de bsqueda inicial o Despus de obtener el objeto EJBHome, crea, elimina o encuentra el bean enterprise utilizando los mtodos create, move o find (solo para beans de entidad) del objeto EJBHome. La bsqueda y creacin de componentes JMS (Topic, Queue, QueueConnection, QueueSession, TopicConnection, TopicSession, etc.) implica los siguientes pasos. Observa que en estos pasos, Topic se refiere al modelo de mensajera publica/subscribe y que Queue se refiere al modelo de mensajera punto-a-punto. o Una correcta configuracin del entorno JNDI para que se conecte con el servicio de nombrado y directorio utilizado por la aplicacin. Esta configuracin proporciona la localizacin del servicio de nombrado y las credenciales de autentificaciones necesarias para acceder a ese servicio. o Obtener el contexto inicial para el proveedor de servicio JMS desde el servicio de nombrado JNDI. o Utilizar el contexto inicial para obtener un Topic o un Queue suministrando el nombre JNDI para ese Topic o Queue. Ambos son objetos JMSDestination. o Utilizar el contexto inicial para obtener un TopicConnectionFactory o un QueueConnectionFactory suministrando el nombre JNDI para la factora adecuada. o Usar el TopicConnectionFactory para obtener un TopicConnection o el QueueConnectionFactory para obtener un QueueConnection. o Utilizar el TopicConnection para obtener un TopicSession o el QueueConnection para obtener un QueueSession. o Utilizar el TopicSession para obtener un TopicSubscriber o un TopicPublisher para el Topic Requerido. Utilizar el QueueSession para obtener un QueueReceiver o un QueueSender para el Queue requerido.

El proceso de bsqueda y creacin de componentes implica una implementacin de una factoria de contextos suministrada por un vendedor. Esto introduce dependencias del vendedor en los clientes de la aplicacin que necesitan utilizar la facilidad de bsqueda JNDI para localizar beans enterprise y componentes JMS.

Causas

Los clientes EJB necesitan utilizar el API JNDI para buscar objetos EJBHome utilizando el nombre registrado del bean enterprise. Los clientes JMS necesitan utilizar el API JNDI para buscar componentes JMS utilizando los nombres registrados en JDNI para esos componentes JMS. La factora de contextos utilizada para la creacin del contexto inicial JNDI la proporciona el vendedor del proveedor del servicio y por lo tanto es dependiente del vendedor. La factora de contexto tambin es dependiente del tipo de objeto que se est buscando. El contexto para una JMS es diferente que el contexto para EJBs, con diferentes proveedores. La bsqueda y creacin de componentes de servicio podra ser compleja y se podra utilizar repetidamente en mltiples clientes en la aplicacin. La creacin del contexto inicial y el servicio de bsqueda de objetos, si se utiliza frecuentemente, puede consumir muchos recursos e impactar en el rendimiento de la aplicacin. Esto es especialmente cierto si los clientes y los servicios estn localizados en diferentes capas. Los clientes EJB podran necesitar reestablecer conexiones a un ejemplar de bean enterprise al que se ha accedido prviamente, teniendo solamente su objeto Handle.

Solucin
Utilizar un objeto Service Locator para abstraer toda la utilizacin JNDI y para ocultar las complejidades de la creacin del contexto inicial, de busqueda de objetos home EJB y de recreacin de objetos EJB. Varios clientes pueden reutilizar el objeto Service Locator para reducir la complejidad del cdigo, proporcionando un punto de control, y mejorando el rendimiento proporcionando facilidades de cach.

Este patrn reduce la complejidad del cliente que resulta de las dependencias del cliente y de la necesidad de realizar los procesos de bsqueda y creacin, que consumen muchos recursos. Para eliminar estos problemas, este patrn proporciona un mecanismo para abstraer todas las dependencias y detalles de red dentro del Service Locator.

Estructura
La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrn Service Locator.

Participantes y Responsabilidades
La siguiente figura contiene el diagrama de secuencia que muestra la interaccin entre los distintos participantes en el patrn Service Locator.

Client
Este es el cliente del Service Locator. El cliente es un objeto que normalmente requiere acceder a objetos de negocio como un Business Delegate.

Service Locator
El Service Locator abstrae el API de los servicios de bsqueda (nombrado), las dependencias del vendedor, las complejidades de la bsqueda, y la creacin de objetos de negocio, y proporciona un interface simple para los clientes. Esto reduce la complejidad del cliente. Adems, el mismo cliente y otros clientes pueden reutilizar el Service Locator.

InitialContext
El objeto InitialContext es el punto de inicio para los procesos de bsqueda y creacin. Los proveedores de servicio proporcionan el objeto context, que vara dependiendeo del tipo de objetos de negocio proporcionados por el servicio de bsqueda y creacin del Service Locator. Un Service Locator que proporciona los servicios para varios tipos de objetos de negocio (como beans enterprise, componentes JMS, etc.) utiliza varios tipos de objetos context, cada uno obtenido de un proveedor diferente (por ejemplo, el proveedor de contexto para un servidor de aplicaciones EJB podra ser diferente del proveedor de contexto para un servicio JMS).

ServiceFactory
El objeto ServiceFactory representa un objeto que proporciona control del ciclo de vida para objetos BusinessService. El objeto ServiceFactory para beans enterprise es un objeto EJBHome. El ServiceFactory

para componentes JMS puede ser un objeto ConnectionFactory, como un TopicConnectionFactory o un QueueConnectionFactory.

BusinessService
BusinessService es un rol que cumple el servicio que el cliente ha solicitado. El objeto BusinessService se crea, se busca o se elimina mediante el objeto ServiceFactory. El objeto BusinessService en el contexto de una aplicacin EJB es un bean enterprise. El objeto BusinessService en el contexto de una aplicacin JMS puede ser un TopicConnection o un QueueConnection. TopicConnection y QueueConnection se pueden entonces utilizar para producir un objeto JMSSession, como un TopicSession o un QueueSession respectivamente.

Estrategias

EJB Service Locator


El Service Locator para componentes bean enterprise utiliza objetos EJBHome, como un BusinessHome en el rol del ServiceFactory. Una vez obtenido el objeto EJBHome, se puede almacenar en el ServiceLocator para un uso posterior y evitar as otra bsqueda JNDI cuando el cliente necesite de nuevo el objeto home. Dependiendo de la implementacin, el objeto home puede ser devuelto al cliente, que puede entonces utilizarlo para buscar, crear o eliminar beans enterprise. Por otro lado, el ServiceLocator puede retener (en el cach) el objeto home y ganar la responsabilidad adicional de hacer de proxy de todas las llamadas de clientes al objeto home. En la siguiente figura podemos ver el diagram de clases para la Estrategia EJB Service Locator:

La interacin entre todos los participantes en un Service Locator para un bean enterprise se puede ver en la siguiente figura:

JMS Queue Service Locator


Esta estrategia se aplica para los requerimientos de mensajera punto-a-punto. El Service Locator para componentes JMS utiliza objetos QueueConnectionFactory en el rol del ServiceFactory. Se busca el QueueConnectionFactory utilizando su nombre JNDI. El ServiceLocator puede almacenar (en el cach) el objeto QueueConnectionFactory para un uso posterior. Esto evita repetidas llamadas JNDI para buscarlo cuando el cliente lo necesite de nuevo. Por otro lado, el ServiceLocator podra enviar el QueueConnectionFactory al cliente. Entonces, el cliente puede utilizarlo para crear una QueueConnection. Se necesita una QueueConnection para poder obtener una QueueSession o para crear un Message, un QueueSender (para enviar mensajes a la cola), o un QueueReceiver (para recibir mensajes de la cola). En la siguiente figura podemos ver el diagrama de clases para esta estrategia. En este diagrama, La cola es un objeto JMS Destination registrado como un objeto JNDI-administered que representa la cola. El objeto Queue se puede obtener directamente desde el contexto buscndolo por su nombre JNDI.

La interaccin entre los participantes en un Service Locator para mensajera punto-a-punto utilizando Queues JMS se puede ver en la siguiente figura:

JMS Topic Service Locator

Esta estraregia es aplicable para requerimientos de mensajeria publica/subscribe. El Service Locator para componentes JMS utiliza objetos TopicConnectionFactory en el rol del ServiceFactory. Se busca el objeto TopicConnectionFactory utilizando sun nombre JNDI. El TopicConnectionFactory se puede almacenar (en el cach) mediante el ServiceLocator para su uso posterior. Esto evita repetidas llamadas JNDI para buscarlo cuando el cliente lo necesite de nuevo. Por otro lado, el ServiceLocator podra enviar el TopicConnectionFactory al cliente. Entonces el cliente puede utilizarlo para crear una TopicConnection. Se necesita una TopicConnection para poder obtener una TopicSession o para crear un Message, un TopicPublisher (para publicar un menaje para un topic), o un TopicSubscriber (para subscribirse a un topic). En la siguiente figura podemos ver el diagrama de clases para la estrategia JMS Topic Service Locator. En este diagrama, el Topic es un objeto JMS Destination registrado como un objeto adiministrado JNDI que representa el topic. El objeto Topic se puede obtener directamente desde el contexto buscndolo por su nombre JNDI.

Topics

La interaccin entre los participantes en un Service Locator para mensajera pubicar/subscribir utilizando JMS se puede ver en la siguiente figura:

Combined EJB and JMS Service Locator


Estas estrategias para EJB y JMS se pueden utilizar para proporcionar implementaciones independientes de Service Locator, ya que los clientes para EJB y JMS podra ser ms o menos mutuamente exclusivos. Sin embargo, si hay la necesidad de combinar estas estrategias, es posible hacerlo pafra proporcionar el Service Locator para todos los objetos bean enterprise y componentes JMS.

Type Checked Service Locator


Los dos ltimos diagramas proporcionan facilidades de bsqueda pasndole el nombre en el servicio de bsqueda. Para una bsqueda de un bean enterprise, el Service Locator necesita una clase como parmetro del mtodo PortableRemoteObject.narrow(). El Service Locator puede proporcionar un mtodo getHome(), que acepta como argumento el nombre del servicio JNDI y el nombre de la clase del objeto EJBHome del bean enterprise. Utilizando este mtodo de pasar nombres en servicios JNDI y clases de objetos EJBHome se pueden provocar errores en los clientes. Otra aproximacin es definir estticamente los servicios en el ServiceLocator, en lugar de pasarlos como parmetros string, el cliente los pasa como constantes. Esta estrategia tiene inconvenientes. Reduce la flexibilidad de la bsqueda, que est en la estrategia Services Property Locator, pero aade chequeo de tipos en el paso de una constante al mtodo ServiceLocator.getHome().

Service Locator Properties


Esta estrategia ayuda a corregir los inconvenientes de la estrategia anterior. Aqu se sugiere el uso de ficheros de propiedades y/o descriptores de ficheros para especificar los nombres JNDI y los nombres de las clases EJBHome. Para los clientes de la capa de presentacin, dichas propiedades se pueden especificar en los descriptores de despliegue de la capa de presentacin o en ficheros de propiedades. Cuando la capa de presentacin accede a la capa de negocio, normalmente utiliza el patrn Business Delegate.

El patrn Business Delegate interacta con el Service Locator para localizar los componentes de negocio. Si la capa de presentacin carga las propiedades durante la inicializacin y puede proporcionar un servicio para manejar los nombres JNDI y los nombres de las clases EJB para los beans enterprise requeridos, el Business Delegate podra solicitar a este servicio que los obtuviera. Una vez que el Business Delegate tiene el nombre JNDI y el nombre de la clase EJBHome, puede pedirle al Service Locator el EJBHome pasndole estas propiedades como argumentos. Entonces el Service Locator puede utilizar el mtodo Class.forName(EJBHome ClassName) para obtener el objeto EJBHome y utilizar el mtodo Portable RemoteObject.narrow() para forzar el objeto, segn se ver en el mtodo getHome() en el ejemplo de ServiceLocator. Lo nico que cambia es de donde vienen los nombres JNDI y los objetos Class . Por lo tanto, esta estrategia evita introducir en el cdigo los nombres JNDI y proporciona flexibilidad para su despliegue.

Consecuencias

Abstrae la Complejidad El patrn Service Locator encapsula la complejidad de este proceso de bsqueda y creacin (descrito en el problema) y lo mantiene oculto del cliente. El cliente no necesita tratar con la bsqueda de componentes ni factoras de objetos (EJBHome, QueueConnectionFactory, y TopicConnectionFactory, entre otros) porque se ha delegdo esta responsabilidad en el ServiceLocator. Proporciona a los Clientes un Acceso Uniforme a los Servicios El patrn Service Locator abstrae todas las complejidades, como acabamos de ver. Haciendo esto, proporciona un interface muy til y preciso que todos los clientes pueden utilizar. Este interface asegura que todos los tipos de clientes de la aplicacin acceden de forma uniforme a los objetos de negocio, en trminos de bsqueda y creacin. Esta uniformidad reduce la sobrecarga de desarrollo y mantenimiento. Facilita la Adiccin de Nuevos Componentes de Negocio Como los clientes de beans enterprise no se preocupan de los objetos EJBHome, es posible aadir nuevos objetos EJBHome para beans enterprise y desplegarlos posteriormente sin impactar en los clientes. Los clientes JMS no se preocupan directamente de las factoras de conexiones JMS, por eso se pueden aadir nuevas factoras sin impactar en los clientes. Mejora el Rendimiento de la Red Los clientes no estn implicados en la bsqueda JNDI y la creacin de objetos (factory/home). Como el Service Locator realiza este trabajo, puede asumir las llamadas de red requeridas para buscar y crear objetos de negocio. Mejora el Rendimiento del Cliente mediante el Cach El Service Locator puede poner en un cach los objetos y referencias a objetos del contexto inicial para eliminar actividad JNDI inncesaria que ocurre cuando se obtiene el contexto inicial u otro objetos. Esto mejora el rendimiento de la aplicacin.

Cdigo de Ejemplo
Implementar el Patrn Service Locator
Aqu podemos ver un ejemplo de cdigo para la implementacin del patrn Service Locator.

package corepatterns.apps.psa.util; import java.util.*; import javax.naming.*; import java.rmi.RemoteException; import javax.ejb.*; import javax.rmi.PortableRemoteObject; import java.io.*; public class ServiceLocator { private static ServiceLocator me; InitialContext context = null; private ServiceLocator() throws ServiceLocatorException { try { context = new InitialContext(); } catch(NamingException ne) { throw new ServiceLocatorException(...); } }

// Returns the instance of ServiceLocator class public static ServiceLocator getInstance() throws ServiceLocatorException { if (me == null) { me = new ServiceLocator(); } return me; } // Converts the serialized string into EJBHandle // then to EJBObject. public EJBObject getService(String id) throws ServiceLocatorException { if (id == null) { throw new ServiceLocatorException(...); } try { byte[] bytes = new String(id).getBytes(); InputStream io = new ByteArrayInputStream(bytes); ObjectInputStream os = new ObjectInputStream(io); javax.ejb.Handle handle = (javax.ejb.Handle)os.readObject(); return handle.getEJBObject(); } catch(Exception ex) { throw new ServiceLocatorException(...); } } // Returns the String that represents the given // EJBObject's handle in serialized format. protected String getId(EJBObject session) throws ServiceLocatorException { try { javax.ejb.Handle handle = session.getHandle(); ByteArrayOutputStream fo = new ByteArrayOutputStream(); ObjectOutputStream so = new ObjectOutputStream(fo); so.writeObject(handle); so.flush(); so.close(); return new String(fo.toByteArray()); } catch(RemoteException ex) { throw new ServiceLocatorException(...); } catch(IOException ex) { throw new ServiceLocatorException(...); } return null; } // Returns the EJBHome object for requested service // name. Throws ServiceLocatorException If Any Error // occurs in lookup public EJBHome getHome(String name, Class clazz) throws ServiceLocatorException { try { Object objref = context.lookup(name); EJBHome home = (EJBHome) PortableRemoteObject.narrow(objref, clazz); return home; } catch(NamingException ex) { throw new ServiceLocatorException(...); } } }

Implementar la Estrategia Type Checked Service Locator


Abajo puedes ver el cdigo de ejemplo para la implementacin de la estrategia Type Checked Service Locator:

package corepatterns.apps.psa.util; // imports ... public class ServiceLocator { // singleton's private instance private static ServiceLocator me; static { me = new ServiceLocator();

} private ServiceLocator() {} // returns the Service Locator instance static public ServiceLocator getInstance() { return me; } // Services Constants public class Services final public static final public static } Inner Class - service objects { int PROJECT = 0; int RESOURCE = 1;

// Project EJB related constants final static Class PROJECT_CLASS = ProjectHome.class; final static String PROJECT_NAME = "Project"; // Resource EJB related constants final static Class RESOURCE_CLASS = ResourceHome.class; final static String RESOURCE_NAME = "Resource"; // Returns the Class for the required service static private Class getServiceClass(int service){ switch( service ) { case Services.PROJECT: return PROJECT_CLASS; case Services.RESOURCE: return RESOURCE_CLASS; } return null; } // returns the JNDI name for the required service static private String getServiceName(int service){ switch( service ) { case Services.PROJECT: return PROJECT_NAME; case Services.RESOURCE: return RESOURCE_NAME; } return null; } /* gets the EJBHome for the given service using the ** JNDI name and the Class for the EJBHome */ public EJBHome getHome( int s ) throws ServiceLocatorException { EJBHome home = null; try { Context initial = new InitialContext(); // Look up using the service name from // defined constant Object objref = initial.lookup(getServiceName(s)); // Narrow using the EJBHome Class from // defined constant Object obj = PortableRemoteObject.narrow( objref, getServiceClass(s)); home = (EJBHome)obj; } catch( NamingException ex ) { throw new ServiceLocatorException(...); } catch( Exception ex ) { throw new ServiceLocatorException(...); } return home; } }

El cdigo de cliente para utilizar el Service Locator mediante est estratega, se podra parecer a esto:

public class ServiceLocatorTester { public static void main( String[] args ) { ServiceLocator serviceLocator = ServiceLocator.getInstance(); try {

ProjectHome projectHome = (ProjectHome) serviceLocator.getHome( ServiceLocator.Services.PROJECT ); } catch( ServiceException ex ) { // client handles exception System.out.println( ex.getMessage( )); } } }

Esta estrategia trata sobre como aplicar el chequeo de tipos a la bsqueda del cliente. Encapsula los valores estticos del servicio dentro del ServiceLocator y crea una clase Services interna, que declara las constantes del servicio (PROJECT y RESOURCE). El cliente de prueba obtiene un ejemplar del ServiceLocator y llama a getHome(), pasndole PROJECT. Entonces ServiceLocator obtiene el nombre de la entrada JNDI y la clase Home y devuelve el EJBHome.

Patrones Relacionados

Business Delegate El patrn Business Delegate utiliza a Service Locator para obtener acceso a los objetos de negocio. Esto separa la complejidad de la localizacin del servicio del Business Delegate, rebajando el acoplamiento entre ellos e incrementando la manejabilidad. Session Facade El patrn Session Facade utiliza a Service Locator para obtener acceso a beans enterprise que estn implicados en el flujo de trabajo. Session Facade podra utilizar directamente el patrn Service Locator o delegar el trabajo en un Business Delegate. Transfer Object Assembler El patrn Transfer Object Assembler utiliza a Service Locator para obtener acceso a varios beans enterprise que necesita para acceder a construir su objeto Transfer Object compuesto. Este patrn podra utilizar directamente el patrn Service Locator o delegar el trabajo en un Business Delegate.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Session Facade o Contexto o Problema o Causas o Solucin Estructura Participantes y Colaboraciones Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Session Facade o Patrones Relacionados

Session Facade
Contexto
Los Beans Enterprise encapsulan lgica y datos de negocio y exponen sus interfaces, y con ellos la complejidad de los servicios distribuidos, a la capa de cliente.

Problema
En un entorno de la aplicaciones multicapa de la Plataforma Java 2, se pueden encontrar los siguientes problemas:

Acoplamiento fuerte, que provoca la dependencia directa entre los clientes y los objetos de negocio. Demasiadas llamadas a mtodos entre el cliente y el servidor, abocando a problemas de rendimiento de la red. Falta de una estrategia de acceso uniforme de los clientes, exponiendo los objetos de negocio a una mala utilizacin.

Una aplicacin J2EE multicapa tiene numerosos objetos del lado del servidor que se implementan como beans enterprise. Adems, otros objetos arbitrarios podran proporcionar servicios, datos o las dos cosas. A estos objetos los conocemos colectivamente como objetos de negocio, ya que encapsulan datos y lgica de negocio. Las aplicaciones J2EE implementan objetos de negocio que proporcionan servicios de procesamiento como beans de sesin. Los objetos de negocio genricos que representan una vista de un objeto de almacenamiento persistente y que es compartido por varios usuarios, normalmente se implementan como beans de entidad. Los clientes de la aplicacin necesitan acceder a los objetos de negocio para cumplir sus responsabilidades y para cumplir los requerimientos del usuario. Los clientes pueden interactar directamente con estos objetos de negocio porque stos exponen sus interfaces. Cuando exponemos nuestros objetos de negocio al cliente, el cliente debe entender y ser responsable de las relaciones con los objetos de datos de negocio, y debe poder manejar el flujo del proceso de negocio. Sin embargo, la interaccin directa entre el cliente y los objetos de negocio implica un acoplamiento fuerte entre los dos, y dicho acoplamiento hace que el cliente dependa de la implementacin de los objetos de negocio. Dependencia directa significa que el cliente debe representar e implementar las interacciones complejas teniendo en cuenta la bsqueda y creacin de objetos, y debe manejar la relacin entre los

objetos de negocio participantes as como entender la responsabilidad de la demarcacin de transaciones. Segn se van incrementando los requerimientos del cliente, tambin se incrementa la complejidad de las interacciones entre los distintos objetos de negocio. El cliente se hace de mayor tamao y ms complejo para cumplir esos requerimientos. El cliente se vuelve muy susceptible a los cambios en la capa de objetos de negocio; adems, exponemos inncesariamente el cliente a las complejidades subyacentes del sistema. El acoplamiento fuerte entre objetos tambin se obtiene cuando los objetos manejan sus relaciones entre ellos mismos. Fruecuentemente, no est claro donde se manejan las relaciones. Esto provoca la complejidad de las relaciones entre los objetos de negocio y la rigidez en la aplicacin. Esta falta de flexibilidad hace las aplicaciones menos manejables cuando se necesita hacer cambios. Cuando acceden a beans enterprise, los clientes interactan con objetos remotos. Se podran producir problemas de rendimiento de red si el cliente interacta directamente con todos los objetos de negocio participantes. Cuando se invoca a beans enterprise, cada llamada del cliente potencialmente es una llamada a un mtodo remoto. Segn se incrementa el nmero de participantes en un escenario, se incrementa el nmero de estas llamadas remotas. Y segn aumentan las llamadas remotas, tambin se incrementa "el parloteo" entre el cliente y los objetos de negocio del lado del servidor . Esto podra resultar en una degradacin del rendimiento de la red, porque el gran volumen de llamadas a mtodos remotos incrementa la cantidad de interacciones sobre la capa de red. Aparece otro problema cuando un cliente interacta directamente con los objetos de negocio. Como los objetos de negocio se exponen directamente a los clientes, no hay una estrategia unificada para acceder a ellos. Sin dicha estrategia uniforme de acceso por parte del cliente, los objetos de negocio se ven expuestos a los clientes y se podra reducir su utilizacin consistente.

Causas

Proporcionar a los clientes un interface sencillo que oculte todas interacciones complejas entre los componentes de negocio. Reducir el nmero de objetos de negocio que se exponen al cliente a travs de la capa de servicio sobre la red. Ocultar al cliente las interacciones y las interdependencias entre los componentes de negocio. Esto proporciona una mejor manejabilidad, centralizacin de interacciones (responsabilidades), mayor flexibilidad, y mayor habilidad para soportar los cambios. Proporcionar una capa de servicio uniforme para separar la implementacin de los objetos de negocio de la abstraccin del servicio de negocio. Evitar la exposicin directa de los objetos de negocio a los clientes para mantener el acoplamiento entre las dos capas al mnimo.

Solucin
Usar un bean de sesin como una fachada (facade) para encapsular la complejidad de las interacciones entre los objetos de negocio participantes en un flujo de trabajo. El Session Facade maneja los objetos de negocio y proporciona un servicio de acceso uniforme a los clientes. Session Facade abstrae las interacciones de los objetos de negocio y proporciona una capa de servicio que expone slo los interfaces requeridos. As, oculta a la vista de los clientes las interacciones complejas entre los participantes. El Session Facade controla las interacciones entre los datos de negocio y los objetos de servicio de negocio que participan en el flujo de trabajo, y encapsula la lgica de negocio asociada con los requerimientos, As, el bean de sesin (representando al Session Facade) maneja las relaciones entre los objetos de negocio. El bean de sesin tambin maneja el ciclo de vida de los participantes creando, localizando (buscando), modificando, y borrndolos segn lo requiera el flujo de trabajo. En una aplicacin compleja, el Session Facade podra delegar este control del estilo de vida en un objeto separado. Por ejemplo, para controlar el estilo de vida de los beans de sesin e identidad participantes, Session Facade podra delegar este trabajo a un objeto Service Locator. Es importante examinar las relaciones entre los objetos de negocio. Algunas de estas relaciones son temporales, lo que significa que la relacin es aplicable slo a esa interaccin o escenario. Otras relaciones podran ser ms permanentes. Las relaciones temporales se modelan mejor como flujos de trabajo en una fachada, donde la fachada maneja las relaciones entre los objetos de negocio. Las

relaciones permanentes entre dos objetos de negocio deberan estudiarse para determinar qu objeto de negocio (si no mbos) mantiene la relacin.

Casos de Utilizacin y Session Facades Entonces, cmo podemos identificar el Session Facades estudiando casos de uso? Mapear cada caso a un Session Facade resultar en demasiados Session Facades. Esto derrota la intencin de tener menos beans de sesin genricos. En su lugar,cuando derivemos los Session Facades durante nuestro modelado, debemos consolidarlos dentro de un menor nmero de beans de sesin basndonos en algn particionamiento lgico. Por ejmplo, para una aplicacin de banca, podramos agrupar las interacciones relacionadas parar manejar una cuenta en una sola fachada. Los casos de utilizacin Crear una Nueva Cuenta, Cambiar Informacin de la Cuenta, Ver informacin de la Cuente, etc. tratarn con un objeto de entidad genrico llamado Account. No se recomienda crear una fachada para cada caso de utilizacin. As, las funciones requeridas para soportar estos usos relacionados se podran agrupar en un slo Session Facade llamado AccountSessionFacade. En este caso, el Session Facade se convertir en un controlador genrico con mtodos de alto nivel que puede facilitar cada interaccin (es decir, createNewAccount, changeAccount, getAccount). Por lo tanto, recomendamos que disees los Session Facades para agregar un grupo de interacciones relacionadas en un slo Session Facade. Esto resulta en menos Session Facades para la aplicacin, y aprovecha los beneficios del patrn Session Facade.
Estructura
La siguiente figura representa el diagrama de clases del patrn Session Facade.

Participantes y Colaboraciones

La siguiente figura contiene el diagrama de secuencia que muestra las interacciones de un Session Facade con dos beans de entidad, un bean de sesin y un DAO, todos actuando como participantes en el cumplimiento de la peticin del cliente.

Client
Representa al cliente del Session Facade, que necesita acceder al servicio de negocio. Este cliente puede ser otro bean de sesin (Session Facade) en la misma capa de negocio o un Business Delegate en otra capa.

SessionFacade
El SessionFacade se implementa como un bean de sesin. Maneja la relaciones entre varios objetos de negocio y proporciona una abstraccin de alto nivel para el cliente. El SessionFacade ofrece acceso genrico a los BusinessObject participantes representados por la llamada Invoke en el bean de sesin.

BusinessObject
BusinessObject

es un objeto de rol que facilita la aplicacin de diferentes estraegias, como beans de sesin, de entidad o DAO. Un BusinessObject proporciona datos y/o algn servicio del diagrama de clases. El SessionFacade interacta con varios ejemplares de BusinessObject para proporcionar el servicio.

Estrategias
Session Facade es un objeto controlador de la capa de negocio que controla las interacciones entre el cliente y los datos de negocio y los objetos de servicio de negocio. En una aplicacin compleja, podra haber numerosos Session Facades que pueden intermediar entre el cliente y esos objetos. Podemos identificar dnde podra ser til un Session Facade estudiando los requerimientos e interacciones del cliente que normalmente se documentan en casos de utilizacin y escenarios. Este anlisis nos permite identificar una capa controladora -- compuesta de Session Facades -- que puede actuar como fachadas para estos escenarios.

Stateless Session Facade

Cuando se implemente Session Facade, primero debemos decidir si el bean del Facade Session va a ser un bean de sesin con o sin estado. Basamos esta decesin en los procesos de negocio que el Session Facade est modelando. Un proceso de negocio que slo necesita una llamada a un mtodo para completar el servicio es un proceso de negocio no conversacional. Dichos procesos son ideales para implementarlos utilizando beans de sesin sin estado. Un estudio cuidadoso de estos casos de utilizacin y escenarios nos permite determinar las definiciones del Session Facade. Si el caso de utilizacin no es conversacional, los clientes inician la utilizacin con un nico mtodo en el Session Facade. Cuando el mtodo se completa, el caso de utilizacin tambin se completa. No hay necesidad de grabar el estado conversacional entre una llamada al mtodo y la siguiente. En este escenario, el Session Facade se puede implementar como un bean de sesin sin estado.

Stateful Session Facade


Un proceso de negocio que necesita varias llamadas a mtodos para completar el servicio es un proceso de negocio conversacional. El estado conversacional debe grabarse entre cada invocacin del mtodo por parte del cliente. En este escenario, sera una mejor aproximacin utilizar un bean de sesin con estado para implementar el Session Facade. En las dos estrategias anteriores, el rol del objeto de negocio se puede cumplir de diferentes formas, como se explica ms abajo.

Estrategias para Objetos de Negocio


Podemos implementar un objeto de negocio como un bean de sesin, un bean de entidad, DAO, o un objeto normal Java. Las siguientes estrategias discuten todas estas opciones:

Session Bean
El objeto de negocio se puede implementar como un bean de sesin. El bean de sesin normalmente proporciona un servicio de negocio y, en algunos casos, tambin podra proporcionar datos de negocio. Cuando dicho bean de sesin necesite acceder a los datos, podra utilizar un DAO para manipularlos. El Session Facade puede envolver uno o ms beans de sesin orientados a servicio u orientados a datos actuando como objetos de negocio.

Entity Bean
Representar el objeto de negocio mediante un bean de entidad es el uso ms comn de Session Facade. Cuando varios beans de entidad participan en el caso de utilizacin, no es necesario exponerlos todos al cliente. En su lugar, el Session Facade puede envolver estos beans de entidad y proporcionar mtodos genricos para realizar las funciones de negocio requeridas, y as ocultar la complejidad de las interacciones de beans de entidad.

Data Access Object (DAO)


El Session Facade puede utilizar directamente uno o ms DAOs para representar los datos de negocio. Esto se hace cuando la aplicacin es tan simple que no requiere beans de entidad, o cuando la arquitectura de la aplicacin est basada slo en beans de sesin y no utiliza beans de entidad. Utilizando DAOs dentro de beans de sesin se simula parcialmente la naturaleza persistente de los beans de entidad. La aplicacin podra necesitar los servicios porporcionados por un objeto Java normal (es decir, un objeto que no es un bean enterprise ni un DAO, aunque un DAO se podra considerar un objeto Java normal). En dicho caso, el Session Facade accede a este objeto arbitrario para proporcionar las funcionalidades necesarias.

Consecuencias

Introduce la Capa Controladora para la Capa de Negocio Los Session Facades pueden representar una capa controladora entre los clientes y la capa de negocios, identificado en el anlisis del modelo. Un Session Facade acompasa las interacciones entre el cliente y los componentes de negocio. En una aplicacin sofisticada, podemos identicar numerosos Session Facades que pueden intermediar entre el cliente y los objetos de la capa de negocio. Para aplicaciones ms simples, se podra creer que un Session Facade no aade mucho valor, ya que acta principalmente como un proxy entre las peticiones del cliente y un componente de negocio. Sin embargo, segn se van complicando las aplicaciones con el tiempo, utilizar un Session Facade desde el principio nos benficiar en un estado posterior. Expone un Interface Uniforme Las interacciones entre los componentes de negocio pueden ser muy complejas. Un patrn Session Facade abstrae esta complejidad y le presenta al cliente un interface sencillo que es fcil de entender y de utilizar. Aplicando un Session Facade, podemos disear una capa de servicio que exponga interfaces sencillos al sistema como una totalidad. As una fachada proporciona una capa de acceso uniforme para todos los tipos de clientes y puede proteger y ocultar los componentes de negocio participantes. Reduce el Acoplamiento, Incrementa la Manejabilidad Utilizar un Session Facade desacopla los objetos de negocio de los clientes, y as reduce el fuerte acoplamiento y la dependencia de los clientes de los objetos de negocio. Es mejor utilizar un Session Facade para manejar el flujo de trabajo entre los objetos de negocio, en vez de hacer que los objetos de negocio se preocupen unos de otros. Un objeto de negocio slo debera ser responsable de su propio control (datos y lgica). Las interacciones de objetos de negocio se puede abstraer dentro de un flujo de trabajo en una fachada. Esto proporciona una mejor manejabilidad, centralizacin de interacciones (responsabilidad y flujo de trabajo), mayor flexibilidad, y mayor habilidad para soportar los cambios. Separar el flujo de trabajo en un Session Facade elimina la dependencia directa del cliente de los objetos participantes y promueve un diseo flexible. Aunque los cambios en los participantes podran requerir cambios en el Session Facade, centralizar el flujo de trabajo en la fachada hace que dichos cambios sean ms manejables. Podemos cambiar slo el Session Facade en vez de tener que cambiar todos los clientes. El cdigo de los clientes tambin se simplifica porque ahora delegan las responsabilidades del flujo de trabajo en el Session Facade. El cliente ya no maneja las interacciones complejas del flujo de trabajo entre los objetos de negocio, ni se preocupa de las interdependencias entre los objetos de negocio. Mejora el Rendimiento, Reduce los Mtodos Especficos Session Facade tambin impacta en el rendimiento. Reduce la sobrecarga de la red entre el cliente y el servidor porque su uso elimina la interaccin directa entre el cliente y los datos y objetos de negocio. En su lugar, todas las interacciones se enrutan mediante el Session Facade de manera genrica. El Session Facade y sus participantes se acercan unos a otros, haciendo ms eficiente para la fachada el manejo de las interacciones entre los objetos participantes. Todas las trasferencias de datos y las llamadas a mtodos desde la fachada a los participantes se realizan presumiblemente sobre una red de relativa alta velocidad. El rendimiento de red se puede ajustar proporcionando una mxima salida aplicando el patrn Transfer Object donde se pueda aplicar a los objetos participantes. Proporciona Acceso Genrico Session Facade se ha pensado para ser una abstracin genrica del flujo de trabajo. As, no es deseable tener un Session Facade por cada interaccin con un bean de entidad, que podra representar una abstraccin especfica en vez de una genrica. Se debe analizar la interaccin entre el cliente y los servicios de la aplicacin, utilizando casos de utilizacin y escenarios para determinar la bulgaridad de la fachada. Determinamos la especificidad ptima del Session Facade para la aplicacin particionando la aplicacin en subsistemas lgicos y proporcionando un Session Facade para cada subsistema. Sin embargo, proporcionar una sla fachada para todo el sistema puede resultar en un Session Facade muy grande cuyos numerosos mtodos lo hagan ineficiente. Un slo Session Face podra ser suficiente para aplicaciones muy simples que no requieran subsistemas. Centraliza el Control de Seguridad Las polticas de seguridad de la aplicacin se pueden controlar al nivel del Session Facade, ya que sta es la capa presentada a los clientes. Debido al acceso genrico del Session Facade, es ms fcil y ms manejable definir polticas de seguridad en este nivel que al nivel de los componentes de negocio. Los componentes de negocio ofrecen puntos de control especficos. Es ms fcil manejar la seguidad mediante Session Facades que proporcionan acceso genrico, porque son relativamente pocos los mtodos genricos que tenemos que manejar de forma segura. Centraliza el Control de Transaciones Como el Session Facade representa el flujo de trabajo para los casos de utilizacin, es ms

lgico aplicar el control de transaciones a nivel del Session Facade. El control de transacin centralizado tiene ventajas similares a las de la seguridad centralizada. La fachada ofrece un lugar central para manejar y definir el control de transaciones de un forma genrica. Hay mucho ms trabajo que hacer cuando el control de transacin se individualiza para cada componentes de negocio, especialmene porque son ms especficos que la fachada. La no utilizacin de un Session Facade, adems de hacer que el cliente acceda directamente a los beans enterprise, pone los lmites de la transacin en el lado de cliente y puede producir resultados no deseados. Expone Menos Interfaces Remotos a los Clientes Los clientes que interactan directamente con los datos y servicios de negocio causan un incremento de la charlatanera entre el cliente y el servidor. Este incremento podra degradar el rendimiento de la red. Todos los accesos a los objetos de negocio se deben hacer mediante un alto nivel de abstraccin representado en el fachada. Como la fachada presenta un mecanismo de acceso genrico a los componentes de negocio, se reduce el nmero de componentes de negocio que se exponen al cliente. Por lo tanto, se reduce el mbito para la degradacin del rendimiento de la aplicacin debido al nmero limitado de interacciones entre los clientes y el Session Facade en comparacin a la interaccin directa entre el cliente y los componentes de negocio individuales.

Cdigo de Ejemplo
Implementar el Session Facade
Considerando una Aplicacin de Servicios Profesionales (PSA), donde el flujo de trabajo relacionado con los beans de entidad (como Project, Resource) se encapsula en ProjectResourceManagerSession, implementado utilizando el patrn Session Facade. El siguiente fragmento de cdigo muestra la interaccin con los beans de entidad Resource y Project, as como con otros componentes de negocio, como Value List Handlers y Transfer Object Assemblers.

package corepatterns.apps.psa.ejb; import import import import import import import java.util.*; java.rmi.RemoteException; javax.ejb.*; javax.naming.*; corepatterns.apps.psa.core.*; corepatterns.util.ServiceLocator; corepatterns.util.ServiceLocatorException;

// Note: all try/catch details not shown for brevity. public class ProjectResourceManagerSession implements SessionBean { private SessionContext context; // Remote references for the // entity Beans encapsulated by this facade private Resource resourceEntity = null; private Project projectEntity = null; ... // default create public void ejbCreate() throws CreateException { } // create method to create this facade and to // establish connections to the required entity // beans // using primary key values public void ejbCreate( String resourceId, String projectId, ...) throws CreateException, ResourceException { try { // locate and connect to entity beans connectToEntities(resourceId, projectId, ...); } catch(...) { // Handle exceptions } } // method to connect the session facade to its // entity beans using the primary key values private void connectToEntities (

String resourceId, String projectId) throws ResourceException { resourceEntity = getResourceEntity(resourceId); projectEntity = getProjectEntity(projectId); ... } // method to reconnect the session facade to a // different set of entity beans using primary key // values public resetEntities(String resourceId, String projectId, ...) throws PSAException { connectToEntities(resourceId, projectId, ...); } // private method to get Home for Resource private ResourceHome getResourceHome() throws ServiceLocatorException { return ServiceLocator. getInstance().getHome( "ResourceEntity", ResourceHome.class); } // private method to get Home for Project private ProjectHome getProjectHome() throws ServiceLocatorException { return ServiceLocator. getInstance().getHome( "ProjectEntity", ProjectHome.class); } // private method to get Resource entity private Resource getResourceEntity( String resourceId) throws ResourceException { try { ResourceHome home = getResourceHome(); return (Resource) home.findByPrimaryKey(resourceId); } catch(...) { // Handle exceptions } } // private method to get Project entity private Project getProjectEntity(String projectId) throws ProjectException { // similar to getResourceEntity ... } // Method to encapsulate workflow related // to assigning a resource to a project. // It deals with Project and Resource Entity beans public void assignResourceToProject(int numHours) throws PSAException { try { if ((projectEntity == null) || (resourceEntity == null)) { // SessionFacade not connected to entities throw new PSAException(...); } // Get Resource data ResourceTO resourceTO = resourceEntity.getResourceData(); // Get Project data ProjectTO projectTO = projectEntity.getProjectData(); // first add Resource to Project projectEntity.addResource(resourceTO); // Create a new Commitment for the Project CommitmentTO commitment = new CommitmentTO( ...); // add the commitment to the Resource projectEntity.addCommitment(commitment); } catch(...) { // Handle exceptions } } // Similarly implement other business methods to // facilitate various use cases/interactions public void unassignResourceFromProject()

throws PSAException { ... } // Methods working with ResourceEntity public ResourceTO getResourceData() throws ResourceException { ... } // Update Resource Entity Bean public void setResourceData(ResourceTO resource) throws ResourceException { ... } // Create new Resource Entity bean public ResourceTO createNewResource(ResourceTO resource) throws ResourceException { ... } // Methods for managing resource's blockout time public void addBlockoutTime(Collection blockoutTime) throws RemoteException,BlockoutTimeException { ... } public void updateBlockoutTime( Collection blockoutTime) throws RemoteException, BlockoutTimeException { ... } public Collection getResourceCommitments() throws RemoteException, ResourceException { ... } // Methods working with ProjectEntity public ProjectTO getProjectData() throws ProjectException { ... } // Update Project Entity Bean public void setProjectData(ProjectTO project) throws ProjectException { ... } // Create new Project Entity bean public ProjectTO createNewProject(ProjectTO project) throws ProjectException { ... } ... // Other session facade method examples // This proxies a call to a Transfer Object Assembler // to obtain a composite Transfer Object. // See Transfer Object Assembler pattern public ProjectCTO getProjectDetailsData() throws PSAException { try { ProjectTOAHome projectTOAHome = (ProjectTOAHome) ServiceLocator.getInstance().getHome( "ProjectTOA", ProjectTOAHome.class); // Transfer Object Assembler session bean ProjectTOA projectTOA = projectTOAHome.create(...); return projectTOA.getData(...); } catch (...) { // Handle / throw exceptions } } // These method proxies a call to a ValueListHandler // to get a list of projects. See Value List Handler // pattern. public Collection getProjectsList(Date start, Date end) throws PSAException { try { ProjectListHandlerHome projectVLHHome = (ProjectVLHHome) ServiceLocator.getInstance().getHome(

"ProjectListHandler", ProjectVLHHome.class); // Value List Handler session bean ProjectListHandler projectListHandler = projectVLHHome.create(); return projectListHandler.getProjects( start, end); } catch (...) { // Handle / throw exceptions } } ... public void ejbActivate() { ... } public void ejbPassivate() { context = null; } public void setSessionContext(SessionContext ctx) { this.context = ctx; } public void ejbRemove() { ... } }

En el siguiente ejemplo podemos ver el interface remoto para el Session Facade:

package corepatterns.apps.psa.ejb; import java.rmi.RemoteException; import javax.ejb.*; import corepatterns.apps.psa.core.*; // Note: all try/catch details not shown for brevity. public interface ProjectResourceManager extends EJBObject { public resetEntities(String resourceId, String projectId, ...) throws RemoteException, ResourceException ; public void assignResourceToProject(int numHours) throws RemoteException, ResourceException ; public void unassignResourceFromProject() throws RemoteException, ResourceException ; ... public ResourceTO getResourceData() throws RemoteException, ResourceException ; public void setResourceData(ResourceTO resource) throws RemoteException, ResourceException ; public ResourceTO createNewResource(ResourceTO resource) throws ResourceException ; public void addBlockoutTime(Collection blockoutTime) throws RemoteException,BlockoutTimeException ; public void updateBlockoutTime(Collection blockoutTime) throws RemoteException,BlockoutTimeException ; public Collection getResourceCommitments() throws RemoteException, ResourceException; public ProjectTO getProjectData() throws RemoteException, ProjectException ; public void setProjectData(ProjectTO project) throws RemoteException, ProjectException ; public ProjectTO createNewProject(ProjectTO project) throws RemoteException, ProjectException ; ...

public ProjectCTO getProjectDetailsData() throws RemoteException, PSAException ; public Collection getProjectsList(Date start, Date end) throws RemoteException, PSAException ; ... }

En el siguiente cdigo podemos ver el interface home para el Session Facade:

package corepatterns.apps.psa.ejb; import import import import javax.ejb.EJBHome; java.rmi.RemoteException; corepatterns.apps.psa.core.ResourceException; javax.ejb.*;

public interface ProjectResourceManagerHome extends EJBHome { public ProjectResourceManager create() throws RemoteException,CreateException; public ProjectResourceManager create(String resourceId, String projectId, ...) throws RemoteException,CreateException; }

Patrones Relacionados

Facade [GoF] Session Facade est basada en el patrn de diseo Facade. Data Access Object Una de las estrategias para los componentes de negocio del patrn Session Facade es utilizar el DAO. Este puede ser el caso de aplicaciones simples diseadas utilizando beans de sesin y DAOs en lugar de beans de entidad. Service Locator Session Facade es un objeto genrico que permite la encapsulacin del flujo de trabajo manejando datos de negocio y servicios de negocio. Los objetos de datos de negocio pueden ser beans de entidad o DAOs, y los servicios de negocio pueden ser beans de sesin u otros objetos que proporcionen servicios. Session Facade puede utilizar el patrn Service Locator para reducir la complejidad del cdigo y explotar los beneficios ofrecidos por Service Locator. Business Delegate Busines Delegate utiliza un Session Facade cuando el cliente solicita acceso a servicios de negocio. El Business Delegate hace de proxy o adapta la peticin del cliente a un Session Facade que proporciona el servicio requerido. Broker [POSA1] Session Facade realiza el rol de un broker para desacoplar los beans de entidad de sus clientes.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Transfer Object o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el patrn Transfer Object Implementar la Estrategia Updatable Transfer Objects Implementar la Estrategia Multiple Transfer Objects Implementar la Estrategia Entity Inherits Transfer Object Implementar la Estrategia Transfer Object Factory o Patrones Relacionados

Transfer Object
Contexto
Las aplicaciones cliente necesitan intercambiar datos con Beans Enterprise.

Problema
Las aplicaciones de la plataforma J2EE implementan componentes de negocio del lado del servidor como beans de sesin y de entidad. Algunos mtodos expuestos por los componentes de negocio devuelven datos al cliente. Algunas veces, el cliente invoca a los mtodos get de un objeto de negocio varias veces para obtener todos los valores de los atributos. Los beans de sesin representan los servicios de negocio y no se comparten entre usuarios. Un bean de sesin proporciona mtodos de servicios genricos cuando se implementan para el patrn Session Facade. Por otro lado, los beans de entidad, son objetos transacionales, multiusuario que representan datos persistentes. Un bean de entidad expone los valores de los atributos proporcionando un mtodo accesor (tambin referidos como mtodos get) por cada atributo que desea exponer. Toda llamada a mtodo hecha al objeto de servicio de negocio, ya sea a un bean de entidad o a un bean de sesin, potencialmente es una llamada remota. As, en una aplicacin de JavaBeans Enterprise (EJB) dichas llamadas remotas usan la capa de red sin importar la proximidad del cliente al bean, creando una sobrecarga en la red. Las llamadas a mtodos de beans enterprise podra penetrar las capas de red incluso si tanto el cliente como el contenedor EJB que mantiene el bean de entidad se estn ejecutando en la misma JVM (Mquina Virtual Java), el mismo Sistema Operativo o mquina fsica. Algunos vendedores podran implementar mecanismos para reducir esta sobrecarga utilizando una aproximacin de acceso ms directa pasando por encima de la red. Segn se incrementa la utilizacin de estos mtodos remotos, el rendimiento de la aplicacin se puede degradar significativametne. Por lo tanto, utilizar varias llamadas a mtodos get que devuelven simples valores de atributos es ineficiente para obtener valores de datos desde un bean enterprise.

Causas

Todos los accesos a un bean enterprise se realizan mediante interfaces remotos. Cada llamada a un bean enterprise potencialmente es una llamada a un mtodo remoto con sobrecarga de red. Normalmente, las aplicaciones tienen transaciones de lectura con mayor frecuencia que las de actualizacin. El cliente solicita los datos desde la capa de negocio para su presentacin, y otros tipos de procesamientos de slo-lectura. El cliente actualiza los datos de la capa de negocio con mucha menos frecuencia con la que los lee. El cliente normalmente solicita valores que son algo ms que un atributo o que son dependendientes del objeto de un bean enterprise. As, el cliente podra invocar varias llamadas remotas para obtener los datos necesarios. El nmero de llamadas que un cliente hace al bean enterprise impactan en el rendimiento de la red. Las aplicaciones charlatanas -- aquellas que incremenetan el trafico entre las capas del cliente y del servidor -- suelen degradar el rendimiento de la red.

Solucin
Utilizar un Transfer Object para encapsular los datos de negocio. Se utiliza una nica llamada a un mtodo para envar y recuperar el Transfer Object. Cuando el cliente solicita los datos de negocio al bean enterprise, ste puede construir el Transfer Object, rellenarlo con sus valores de atributos y pasarlo por valor al cliente. Los clientes normalmente solicitan ms de un valor a un bean enterprise. Para reducir el nmero de llamadas remotas y evitar la sobrecarga asociada, es mejor el Transfer Objects para transportar los datos desde el bean enteprise al cliente. Cuando un bean enterprise utiliza un Transfer Object, el cliente hace una sola llamada a un mtodo remoto del bean enterprise para solicitar el Transfer Object en vez de numerosas llamadas remotas para obtener valores de atributos individuales. Entonces el bean enterprise construye un nuevo ejemplar Transfer Object, copia dentro los valores del objeto y lo devuelve al cliente. El cliente recibe el Transfer Object y puede entonces invocar los mtodos accesores (o get) del Transfer Object para obtener los valores de atributos individuales del objeto Transfer Object. O, la implementacin del Transfer Object podra hacer que todos los atributos fueran pblicos. Como el Transfer Object se pasa por valor al cliente, todas las llamadas al ejemplar Transfer Object son llamadas locales en vez de invocaciones de mtodos remotos.

Estructura
Ls siguiente figura muestra el diagrama de clases que representa el patrn Transfer Object en su forma ms simple:

Como se ve en este diagrama de clases, el Transfer Object lo construye bajo pedido el bean enterprise y lo devuelve al cliente remoto. Sin embargo, el patrn Transfer Object puede adoptar varias estrategias, dependendiendo de los requerimientos.

Participantes y Responsabilidades
La siguiente figura contiene el diagrama de secuencia que muestra las interacciones del patrn Transfer Object:

Client
Representa al cliente del bean enterprise. El cliente puede ser una aplicacin final de usuario, como es el caso de una aplicacin que ha sido diseada para acceder directamente a beans enterprise. El cliente puede utilizar Business Delegate u otro BusinessObject diferente.

BusinessObject
Representa un rol en este patrn que puede cumplir un bean de sesin, un bean de entidad, o un Data Access Object (DAO). BusinessObject es el responsable de crear el Transfer Object y devolverlo al cliente bajo pedido. El BusinessObject tambin podra recibir datos desde el cliente en la forma de un Transfer Object y utilizar esos datos para realizar una actualizacin.

TransferObject
es un objeto Java serializable referenciado como un Transfer Object. Una clase Transfer Object podra proporcionar un constructor que acepte todos los atributos requeridos para crear el Transfer Object. El constructor podra aceptar todos los valores de atributos del bean de entidad para el que se ha diseado el Transfer Object. Normalmente, los miembros del Transfer Object se definen como pblicos, as eliminan la necesidad de los mtodos get y set. Si se necesita alguna proteccin, los miembros podran definirse como protected o private, y se definiran mtodos get para sus valores. Si no ofrece mtodos set para los valores, un Transfer Object est protegido frente a modificaciones despus de su creacin. Si slo se permite la modificacin de unos pocos miembros para facilitar las actualizaciones, entonces si que se de deben proporcionar mtodos set. Por lo tanto, la creaccin del Transfer Object vara dependiendo de los requerimientos de la aplicacin.
TransferObject

Estrategias
Las dos primeras estrategias sen aplican cuando el bean enterprise se implementa como un bean de sesin o un bean de entidad.

Las estrategias posteriores son aplicables slo cuando el BusinessObject se iplementa como un bean de entidad.

Updatable Transfer Objects


En esta estrategia, el Transfer Object no slo lleva los valores desde el BusinessObject hasta el cliente, tambin lleva los cambios realizados por el cliente de vuelta al objeto de negocio. La siguiente figura es un diagrama de clases que muestra las relaciones entre el BusinessObject y el Transfer Object:

El BusinessObject crea el Transfer Object. Recuerda que un cliente podra necesitar aceder a los valores del BusinessObject no slo para leerlos sino tambin para modificarlos. Para que el cliente pueda modificar los valores de los atributos del BusinessObject, ste debe proporcionar mtodos mutadores. A stos mtodos tambin se les conoce como mtodos set. En lugar de proporcionar mtodos set especificos para cada atributo, lo que resultara en una sobrecarga de la red, el BusinessObject puede exponer un mtodo setData() genrico que acepta un objeto Transfer Object como argumento. El Transfer Object pasado a este mtodo contiene los valores actualizados por el cliente. Como el Transfer Object tiene que ser mutable, su clase tiene que proporcionar mtodos set para todos los atributos que pueda modificar el cliente. Los mtodos set del objeto Transfer Object pueden incluir validaciones a nivel de campo y chequeos de integridad si son necesarios. Una vez que el cliente obtiene un Transfer Object desde el BusinessObject, puede invocar localmente los mtodos set necesarios para cambiar los valores de los atributos. Dichos cambios locales no impactan en el objeto BusinessObject hasta que se llame al mtodo setData(). El mtodo setData() serializa la copia que tiene el cliente del Transfer Object y la enva al El BusinessObject recibe el Transfer Object modificado desde el cliente y mezcla los cambios con sus propios atributos. La operacion de mezcla podra complicar el diseo del BusinessObject y del Transfer Object; la seccin sobre "Consecuencias" discute estas potenciales complicaciones. Una estrategia a utilizar aqu es actualizar slo los atributos que han cambiado, en vez de actualizar todos los atributos. Una bandera de 'cambiado' situada en el Transfer Object se podra utilizar para determinar los atributos a actualizar, en vez de hacer una comparacin directa.
BusinessObject.

Hay un impacto en el diseo cuando se usa esta estrategia en trminos de propagacin de actualizacin, sincronizacin y control de versin. La siguiente figura muestra el diagram para toda la interaccin de actualizacin:

Multiple Transfer Objects


Algunos objetos de negocio de las aplicaciones pueden ser muy complejos. En dichos casos, es posible que un slo objeto de negocio produzca diferentes Transfer Objects, dependiendo de la peticin del cliente. Existe una relacin uno-a-muchos entre el objeto de negocio y los muchos Transfer Objects que puede producir. En estas circunstancias debemos considerar la utilizacin de esta estrategia. Por ejemplo, cuando el objeto de negocio se implementa como un bean de sesin, normalmente aplicando el patrn Session Facade, el bean podra interactar con numerosos componentes de negocio para proporcionar el servicio. El bean de sesin produce su Transfer Object desde diferentes fuentes. De forma similar, cuando se implementa el BusinessObject como un bean de entidad genrico, normalmente aplicando el patrn Composite Entity, el bean de entidad tendr relaciones complejas con varios objetos dependientes. En ambos casos, es una buena prctica proporcionar mecanismos para producir Transfer Objects que realmente representen a partes de los componentes genricos. Por ejemplo, en una aplicacin tradicional, un Composite Entity que representa la cartera de un cliente puede ser un componente genrico muy complejo que puede producir Transfer Objects que proporcionen datos de las partes de la cartera, como informacin del cliente, lista de stocks, etc. Un ejemplo similar es un bean de sesin que maneja clientes y que proporciona servicios interactuando con otros muchos BusinessObjects y otros componentes para proporcionar su servicio. El bean controlador de clientes puede producir pequeos Transfer Objects, como direcciones de clientes, lista de contactos, etc., para representar partes de su modelo.

Para mbos escenarios, es posible adoptar y aplicar la estrategia Multiple Transfer Objects para que los componentes de negocio, tanto si son beans de sesin como de entidad, puedan crear varios tipos de Transfer Objects. En esta estrategia, la entidad de negocio proporciona varios mtodos para obtener diferentes Transfer Objects. Cada uno de esos mtodos crea y devuelve un tipo diferente de Transfer Object. En la siguiente figura podemos ver el diagrama de clases para esta estrategia.

Cuando un cliente necesita un Transfer Object del tipo TransferObjectA, lama al mtodo getDataA() de la entidad, pidiendo un TransferObjectA. Cuando necesita un Transfer Object del tipo TransferObjectB, llama al mtodo getDataB() de la entidad, pidiendo un TransferObjectB, etc. Esto se puede ver en la siguiente figura:

Entity Inherits Transfer Object


Cuando el BusinessObject se implementa como un bean de entidad y los clientes normalmente necesitan acceder a todos los datos del bean de entidad, entonces el bean de entidad y el Transfer Object tienen los mismos atributos. En este caso, como existe una relacin uno-a-uno entre el bean de entidad y su Transfer Object, el bean de entidad podra ser capaz de utilizar la herencia para evitar la duplicacin de cdigo. En esta estrategia, el bean de entidad extiende (o desdeciende de) la clase del Transfer Object. La nica asumpcin es que el bean de entidad y el Transfer Object comparten las mismas definiciones de atributos. En la siguiente figura podemos ver el diagrama de clases para esta estrategia:

El TransferObject implementa uno o ms mtodos getData() como explicamos en la estrategia anterior. Cuando el bean de entidad desciende de esta clase Transfer Object, el cliente invoca un mtodo getData() heredado del bean de entidad para obtener un Transfer Object.

As, esta estrategia elimina la duplicacin de cdigo entre el bean de entidad y el Transfer Object. Tambin ayuda a manejar los cambios en los requerimientos del Transfer Object aislando los cambios de la clase Transfer Object y previniendo que los cambios afecten al bean de entidad. Esta estrategia tiene un inconveniente relacionado con la herencia. Si el Transfer Object se comparte a travs de su herencia, los cambios que se hagan en la clase Transfer Object afectarn a todas sus subclases, obligando potencialmente a modificar toda su descendencia. El diagrama de secuencia de la siguiente figura demuestra esta estrategia:

En la seccin de Cdigo de Ejemplo veremos esta implementacin.

Transfer Object Factory


La estrategia Entity Inherits Transfer Object se puede extender para que un bean de entidad soporte mltiples Transfer Objects empleando una factora de Transfer Object para crear Transfer Objects bajo demanda utilizando reflection. Esto resulta en una estrategia an ms dinmica para la creacin de Transfer Object. Para conseguir esto, definimos un interface diferente para cada tipo de Transfer Object que se debe devolver. La implementacin que hace el bean de entidad de la superclase de Transfer Object debe implementar todos esos interfaces. Adems, debemos crear una clase separada para implementar todos los interfaces definidos, como se muestra en el diagrama de clases de la siguiente figura.

TransferObjectFactory

Una vez que se han definido e implementado todos los interfaces, creamos un mtodo en la clase al que se le pasan dos argumentos:

El ejemplar del bean de entidad para el que se debe crear el Transfer Object. El interface que identifica el tipo de Transfer Object a crear.

Entonces el TransferObjectFactory puede ejemplarizar un objeto de la clase correcta, configurar sus valores, y devolver el ejemplar de Transfer Object recientemente creado. En la siguiente figura podemos ver el diagrama de secuencia para esta estrategia:

El cliente le solicita un Transfer Object al BusinessEntity. ste le pasa la clase del objeto Transfer Object requerido a TransferObjectFactory, que crea un nuevo Transfer Object de esa clase dada. El TransferObjectFactory usa reflection para obtener dinmicamente la informacin de clase para la clase del Transfer Object y construir un nuevo ejemplar. La obtencin de los valores para el BusinessEntity que realiza el TransferObjectFactory se consigue utilizando invocacin dinmica. Estos son los beneficios de aplicar la estrategia Transfer Object Factory:

Se tiene que escribir menos cdigo para crear Transfer Objects. La misma factora de clases Transfer Object puede ser reutilizada por diferentes beans enterprise. Cuando cambia la definicin de una clase Transfer Object, la factora de objetos Transfer Object maneja estos cambios sin ningn esfuerzo de codificacin adicional. Esto incrementa la manejabilidad y es menos propenso a errores cuando se cambian las definiciones del Transfer Object.

La estrategia Transfer Object Factory tiene las siguienes consecuencias:

Esta basada en el hehco de que la implementacin del bean enterprise extiende (desciende) de la clase general Transfer Object.

El Transfer Object general necesita implementar todos los interfaces definidos para diferentes Transfer Objects que se necesiten suministar al bean de entidad. Se deben cumplir las convenciones de nombrado para poder hacer que esta estrategia funcione. Como se utiliza reflection para inspeccionar y construir dinmicamente Transfer Objects, hay una ligera prdida de rendimiento en su construccin.Sin embargo, si se considera el tiempo total de comunicacin, dicha prdida es mnima en su comparacin.

Hay un inconveniente asociado con esta estrategia. Su poder y flexibilidad se deben sopesar en comparacin con la sobrecarga de rendimiento asociada con la utilizacin de reflection en tiempo de ejecucin.

Consecuencias

Simplifica el Bean de Entidad y el Interface Remoto El bean de entidad proporciona un mtodo getData() para obtener el Transfer Object que contiene los valores de los atributos. Esto podra eliminarse implementando mltiples mtodos get en el bean y definindolos en el interface remoto del bean. De forma similar, si el bean de entidad proporciona un mtodo setData() para actualizar los valores de atributos del bean de entidad con una sola llamada a mtodo, se podra eliminar implementando varios mtodos set en el bean. Transfiere Ms Datos en Menos Llamadas Remotas En lugar de realizar mltiples llamadas sobre la red al BusinessObject para obtener los valores de los atributos, esta solucin proporciona una sola llamada a un mtodo. Al mismo tiempo, esta nica llamada obtiene una mayor cantidad de datos. Cuando consideremos la utilizacin de este patrn, debemos tener en cuenta el inconveniente dee el menor nmero de lamadas contra la mayor transmisin de datos por cada llamada. Alternativamente, podemos proporcionar mbos tipos de mtodos: mtodos get y set especficos y mtodos get y set genricos. El desarrollador puede elegir la tcnica apropiada segn sus requerimentos. Reduce el Trfico de Red Un Transfer Object transfiere los valores desde el bean de entidad al cliente en una llamada a un mtodo remoto. El Transfer Object acta como un transportista de datos y reduce el nmero de llamadas remotas requeridas para obtener los valores de los atributos del bean; y esto significa un mejor rendimiento de la red. Reduce la Duplicacin de Cdigo Usando las estrategias Entity Inherits Transfer Object y Transfer Object Factory, es posible reducir o eliminar la duplicacin de cdigo entre el bean de entidad y el Transfer Object. Sin embargo, con el uso de la estrategia Transfer Object Factory, se podra incrementar la complejidad de la implementacin. Tambin hay un coste asociado a la prdida de rendimiento con esta estrategia al utilizar reflection dinmicamente. En la mayora de los casos, la estrategia Entity Inherits Transfer Object podra ser suficiente para cumplir nuestras necesidades. Podra Introducir Transfer Objects Obsoletos Adoptando la estrategia Updatable Transfer Objects se permite al cliente realizar modificaciones en la copia local del Transfer Object. Una vez que se han completado las modificaciones, el cliente puede invocar el mtodo setData() del bean de entidad y pasarle el Transfer Object modificado. El bean recibe las modificaciones y las mezcla con los valores que l tiene. Sin embargo, podra haber un problema con Transfer Objects obsoletos. El bean de entidad actualiza sus valores, pero no tiene en cuenta si otros clientes han solicitado el mismo Transfer Object con anterioridad. Estos clientes podran contener en su copia local ejemplares de Transfer Object que no reflejan las copia real de los datos del bean. Como el bean no tiene en cuenta a estos clientes, es posible propagar la actualizacin de Transfer Objects obsoletos que mantienen otros clientes. Podra Incrementar la Complejidad Debido a la Sincronizacin y el Control de Versin El bean de entidad mezcla los valores modificados con sus propios valores cuando los recibe en un Transfer Object de un cliente. Sin embargo, el bean debe manejar la situacin donde dos o ms clientes simultneamente solicitan actualizaciones conflictivas de los valores del bean. Permitir estas actualizaciones podra resultar en conflictos de datos. El control de versin es una forma de evitar estos conflictos. El bean de entidad puede incluir como uno de sus atributos un nmero de versin o una fecha de ltima-modificacin. Este nmero de versin se copiara en el Transfer Object. Una transacin de actualizacin puede resolver conflictos utilizando el atributo del nmero de versin. Si un cliente que contiene un Transfer Object obsoleto intenta actualizar el bean, ste puede detectar el nmero de versin obsoleto e informar al cliente de esta condicin de error. Entonces el cliente tiene que obtener el ltimo Transfer Object y reintentar la actualizacin. En casos extremos esto podra resultar en un cliente hambriento -- el cliente nunca puede terminar su actualizacin.

Accesos y Transaciones Concurrentes Cuando dos o ms clientes acceden de forma concurrente al BusinessObject, el contenedor aplica la semntica de transaciones de la arquitectura EJB. Si, para un bean entreprise, el nivel de aislamiento de transaciones se selecciona a TRANSACTION_SERIALIZED en el descriptor de despliegue, el contenedor proporciona la mxima proteccin a la transacin y se asegura de su integridad. Por ejemplo, supongamos que el flujo de trabajo para la primera transacin implica obtener un Transfer Object, luego el proceso contnua modificando el objeto BusinessObject. La segunda transacin, como se han aislado las transaciones serializadas, obtendr el Transfer Object con los valores correctos (los ms actualizados). Sin embargo, para transaciones con menos restricciones, la proteccin es menos rgida, permitiendo inconsistencias en el Transfer Objects por accesos concurrentes. Adems, tendremos que tratar con problemas relacionados con la sincronizacin, el control de versin y los Transfer Objects obsoletos.

Cdigo de Ejemplo
Implementar el patrn Transfer Object
Consideremos un ejemplo donde se ha modelado un objeto de negocio llamado Project y se ha implementado como un bean de entidad. El bean de entidad Project necesita enviar datos a sus clientes en un Transfer Object cuando el cliente llame al mtodo getProjectData(). Abajo podemos ver el cdigo de la clase Transfer Object para este ejemplo, ProjectTO:

// Transfer Object to hold the details for Project public class ProjectTO implements java.io.Serializable { public String projectId; public String projectName; public String managerId; public String customerId; public Date startDate; public Date endDate; public boolean started; public boolean completed; public boolean accepted; public Date acceptedDate; public String projectDescription; public String projectStatus; // Transfer Object constructors... } ]>> </codigo> <para> Abajo podemos ver el cdigo para el bean de entidad de este ejemplo: </para> <codigo> <![CDATA[ ... public class ProjectEntity implements EntityBean { private EntityContext context; public String projectId; public String projectName; public String managerId; public String customerId; public Date startDate; public Date endDate; public boolean started; public boolean completed; public boolean accepted; public Date acceptedDate; public String projectDescription; public String projectStatus; private boolean closed; // other attributes... private ArrayList commitments; ... // Method to get Transfer Object for Project data public ProjectTO getProjectData() { return createProjectTO(); } // method to create a new Transfer Object and // copy data from entity bean into the value // object private ProjectTO createProjectTO() { ProjectTO proj = new ProjectTO();

proj.projectId = projectId; proj.projectName = projectName; proj.managerId = managerId; proj.startDate = startDate; proj.endDate = endDate; proj.customerId = customerId; proj.projectDescription = projectDescription; proj.projectStatus = projectStatus; proj.started = started; proj.completed = completed; proj.accepted = accepted; proj.closed = closed; return proj; } ... }

Implementar la Estrategia Updatable Transfer Objects


El ejemplo anterior se puede ampliar para implementar la estrategia Updatable Transfer Objects. En este caso, el bean de entidad debera proporcionar un mtodo setProjectData() para actualizar el bean de entidad pasndole un Transfer Object que contenga los datos utilizados para realizar la actualizacin. Abajo est el cdigo para esta estrategia:

... public class ProjectEntity implements EntityBean { private EntityContext context; ... // attributes and other methods as in Example 8.4 ... // method to set entity values with a Transfer Object public void setProjectData(ProjectTO updatedProj) { mergeProjectData(updatedProj); } // method to merge values from the Transfer Object into // the entity bean attributes private void mergeProjectData(ProjectTO updatedProj) { // version control check may be necessary here // before merging changes in order to // prevent losing updates by other clients projectId = updatedProj.projectId; projectName = updatedProj.projectName; managerId = updatedProj.managerId; startDate = updatedProj.startDate; endDate = updatedProj.endDate; customerId = updatedProj.customerId; projectDescription = updatedProj.projectDescription; projectStatus = updatedProj.projectStatus; started = updatedProj.started; completed = updatedProj.completed; accepted = updatedProj.accepted; closed = updatedProj.closed; } ... }

Implementar la Estrategia Multiple Transfer Objects


Consideremos un ejemplo donde los clientes acceden a un bean de entidad Resource para pedirle diferentes Transfer Objects. El primer tipo de Transfer Object, ResourceTO, se utiliza para transferir datos de un pequeo conjunto de atributos. El segundo tipo de Transfer Object, ResourceDetailsTO, se usa para transferir datos de un conjunto mayor de atributos. El cliente puede utilizar el primer Transfer Object si slo necesita los datos bsicos representados por ese Transfer Object, y puede utilizar el segundo si necesita informacin ms detalla. Observa que esta estrategia se puede aplicar para producir dos o ms Transfer Objects que contengan diferentes datos, y no slo a un subconjunto o un superconjunto como se muestra aqu. Cdigo de ejemplo para el primer objeto Transfer Objects, ResourceTO:

// ResourceTO: This class holds basic information // about the resource

public class ResourceTO implements java.io.Serializable { public String resourceId; public String lastName; public String firstName; public String department; public String grade; ... }

Cdigo de ejemplo para el segundo objeto Transfer Objects, ResourceDetailsTO:

// ResourceDetailsTO This class holds detailed // information about resource public class ResourceDetailsTO { public String resourceId; public String lastName; public String firstName; public String department; public String grade; // other data... public Collection commitments; public Collection blockoutTimes; public Collection skillSets; }

Cdigo del bean de entidad Resource:

// imports ... public class ResourceEntity implements EntityBean { // entity bean attributes ... // entity bean business methods ... // Multiple Transfer Object method : Get ResourceTO public ResourceTO getResourceData() { // create new ResourceTO instance and copy // attribute values from entity bean into TO ... return createResourceTO(); } // Multiple Transfer Object method : Get // ResourceDetailsTO public ResourceDetailsTO getResourceDetailsData() { // create new ResourceDetailsTO instance and copy // attribute values from entity bean into TO ... return createResourceDetailsTO(); } // other entity bean methods ... }

Cdigo de Ejemplo del cliente del bean de entidad:

... private ResourceEntity resourceEntity; private static final Class homeClazz = corepatterns.apps.psa.ejb.ResourceEntityHome.class; ... try { ResourceEntityHome home = (ResourceEntityHome) ServiceLocator.getInstance().getHome( "Resource", homeClazz); resourceEntity = home.findByPrimaryKey( resourceId);

} catch(ServiceLocatorException ex) { // Translate Service Locator exception into // application exception throw new ResourceException(...); } catch(FinderException ex) { // Translate the entity bean finder exception into // application exception throw new ResourceException(...); } catch(RemoteException ex) { // Translate the Remote exception into // application exception throw new ResourceException(...); } ... // retrieve basic Resource data ResourceTO vo = resourceEntity.getResourceData(); ... // retrieve detailed Resource data ResourceDetailsTO = resourceEntity.getResourceDetailsData(); ...

Implementar la Estrategia Entity Inherits Transfer Object


Consideremos un ejemplo donde un bean de entidad, ContactEntity hereda todas sus propiedades de un Transfer Object ContactTO. El siguiente ejemplo muestra el codigo para el Transfer Object ContactTO que ilustra esta estrategia:

// This is the Transfer Object class inherited by // the entity bean public class ContactTO implements java.io.Serializable { // public members public String firstName; public String lastName; public String address; // default constructor public ContactTO() {} // constructor accepting all values public ContactTO(String firstName, String lastName, String address){ init(firstName, lastName, address); } // constructor to create a new TO based // using an existing TO instance public ContactTO(ContactTO contact) { init (contact.firstName, contact.lastName, contact.address); } // method to set all the values public void init(String firstName, String lastName, String address) { this.firstName = firstName; this.lastName = lastName; this.address = address; } // create a new Transfer Object public ContactTO getData() { return new ContactTO(this); } }

En el siguiente ejemplo podemos ver el cdigo ms importante del bean de entidad para esta estrategia:

public class ContactEntity extends ContactTO implements javax.ejb.EntityBean { ... // the client calls the getData method // on the ContactEntity bean instance. // getData() is inherited from the Transfer Object // and returns the ContactTO Transfer Object ...

Implementar la Estrategia Transfer Object Factory


El siguiente fragmento de cdigo demuestra la estrategia Transfer Object Factory. El bean de entidad extiende un Transfer Object general llamado CustomerContactTO. El CustomerContactTO implementa dos interfaces, Customer y Contact. El Transfer Object CustomerTO implementa Customer, y el Transfer Object ContactTO implementa Contact.

public interface Contact extends java.io.Serializable { public String getFirstName(); public String getLastName(); public String getContactAddress(); public void setFirstName(String firstName); public void setLastName(String lastName); public void setContactAddress(String address); } public class ContactTO implements Contact { // member attributes public String firstName; public String lastName; public String contactAddress; // implement get and set methods per the // Contact interface here. ... } public interface Customer extends java.io.Serializable { public String getCustomerName(); public String getCustomerAddress(); public void setCustomerName(String customerName); public void setCustomerAddress(String customerAddress); } public class CustomerTO implements Customer { public String customerName; public String customerAddress; // implement get and set methods per the // Customer interface here. ... } public class CustomerContactTO implements Customer, Contact { public String firstName; public String lastName; public String contactAddress; public String customerName; public String customerAddress; // implement get and set methods per the // Customer and Contact interfaces here. ... }

En el siguiente codigo tenemos el bean de entidad para obtener estos tres Transfer Objects diferentes:

public class CustomerContactEntity extends CustomerContactTO implements javax.ejb.EntityBean { // implement other entity bean methods...not shown // define constant to hold class name // complete Transfer Object. This is required by // the TransferObjectFactory.createTransferObject(...) public static final String COMPLETE_TO_CLASSNAME = "CustomerContactTO"; // method to return CustomerContactTO Transfer Object public CustomerContactTO getCustomerContact() { return (CustomerContactTO) TransferObjectFactory.createTransferObject( this, "CustomerContactTO",

COMPLETE_TO_CLASSNAME); } // method to return CustomerTO Transfer Object public CustomerTO getCustomer() { return (CustomerTO) TransferObjectFactory.createTransferObject( this, "CustomerTO", COMPLETE_TO_CLASSNAME); } // method to return ContactTO Transfer Object public ContactTO getContact() { return (ContactTO) TransferObjectFactory.createTransferObject( this, "ContactTO", COMPLETE_TO_CLASSNAME); } // other entity bean business methods ... }

Abajo tenemos el cdigo de la clase TransferObjectFactory:

import java.util.HashMap; import java.lang.*; /** * The factory class that creates a Transfer Object for a * given EJB. */ public class TransferObjectFactory { /** * Use a HashMap to cache class information for * Transfer Object classes */ private static HashMap classDataInfo = new HashMap(); /** * Create a Transfer Object for the given object. The * given object must be an EJB Implementation and have * a superclass that acts as the class for the entity's * Transfer Object. Only the fields defined in this * superclass are copied in to the Transfer Object. */ public static java.io.Serializable createTransferObject(Object ejb, String whichTOType, String completeTOType) { try { // Get the class data for the complete // Transfer Object type ClassData cData = getClassData (completeTOType); // Get class data for the requested TO type ClassData voCData = getClassData (whichTOType); // Create the Transfer Object of the requested // Transfer Object type... java.lang.Object whichTO = Class.forName(whichTOType).newInstance(); // get the TO fields for the requested TO // from the ClassData for the requested TO java.lang.reflect.Field[] voFields = voCData.arrFields; // get all fields for the complete TO // from the ClassData for complete TO java.lang.reflect.Field[] beanFields = cData.arrFields; // copy the common fields from the complete TO // to the fields of the requested TO for (int i = 0; i < voFields.length; i++) { try { String voFieldName = voFields[i].getName(); for (int j=0; j < beanFields.length; j++) { // if the field names are same, copy value if ( voFieldName.equals( beanFields[j].getName())) { // Copy value from matching field

// from the bean instance into the new // Transfer Object created earlier voFields[i].set(whichTO, beanFields[j].get(ejb)); break; } } } catch (Exception e) { // handle exceptions that may be thrown // by the reflection methods... } } // return the requested Transfer Object return (java.io.Serializable)whichTO; } catch (Exception ex) { // Handle all exceptions here... } return null; } /** * Return a ClassData object that contains the * information needed to create * a Transfer Object for the given class. This information * is only obtained from the * class using reflection once, after that it will be * obtained from the classDataInfo HashMap. */ private static ClassData getClassData(String className){ ClassData cData = (ClassData)classDataInfo.get(className); try { if (cData == null) { // Get the class of the given object and the // Transfer Object to be created java.lang.reflect.Field[] arrFields ; java.lang.Class ejbTOClass = Class.forName(className); // Determine the fields that must be copied arrFields = ejbTOClass.getDeclaredFields(); cData = new ClassData(ejbTOClass, arrFields); classDataInfo.put(className, cData); } } catch (Exception e) { // handle exceptions here... } return cData; } } /** * Inner Class that contains class data for the * Transfer Object classes */ class ClassData { // Transfer Object Class public Class clsTransferObject; // Transfer Object fields public java.lang.reflect.Field[] arrFields; // Constructor public ClassData(Class cls, java.lang.reflect.Field[] fields) { clsTransferObject = cls; arrFields = fields; } }

Patrones Relacionados

Session Facade Session Facade, que es el interface de negocio para clientes de aplicaciones J2EE, frecuentemente utiliza Transfer Objects como mecanismo de intercambio con beans de entidad. Cuando la fachada acta como un proxy para los servicios de negocio, el Transfer Object obtenido de los beans de entidad se puede pasar al cliente.

Transfer Object Assembler Transfer Object Assembler es un patrn que construye Transfer Objects compuestos desde diferentes fuentes de datos. Las fuentes de datos suelen ser beans de sesin o de entidad a los que se podra solicitar que proporcionaran sus datos al Transfer Object Assembler como Transfer Objects. Estos objetos se considerarn parte del objeto compuesto que ensambla el Transfer Object Assembler. Value List Handler Value List Handler es otro patrn que proporciona una lista de Transfer Objects construidos dinmicamente accediendo al almacenamiento persistente en el momento de la solicitud. Composite Entity El patrn Transfer Object corrige la necesidad de obtener los datos de BusinessObjects a travs de las capas. Ciertamente este es uno de los aspectos de consideracin de diseo para los beans de entidad. El patrn Composite Entity explica los problemas implicados en el diseo de beans de entidad genricos. Este patrn corrige los requerimientos complejos y explica los factores y consideraciones implicados en el diseo de beans de entidad.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Transfer Object Assembler o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Transfer Object Assembler o Patrones Relacionados

Transfer Object Assembler


Contexto
En una aplicacin de la plataforma J2EE, los componentes de negocio del lado del servidor se implementan utilizando beans de sesin, beans de entidad, DAOs, etc. Los clientes de la aplicacin necesitan acceder a datos que frecuentemente se componen de mltiples objetos.

Problema
Los clientes de aplicaciones normalmente solicitan los datos del modelo o parte del modelo para presentarlos al usuario o para usarlos en un paso de procesamiento intermedio antes de proporcionar algn servicio. El modelo de la aplicacin es una abstraccin para los datos de negocio y la lgica de negocio implementada en el lado del servidor como componentes de negocio. Un modelo se podra se expresar como una coleccin de objetos que se han juntado de una manera organizada. En una aplicacin J2EE, el modelo es una coleccin de objetos distribuidos como beans de sesin, beans de entidad, DAOs u otros objetos. Para que un cliente obtenga los datos del modelo, debe acceder individualmente a cada objeto distribuido que define el modelo. Esta aproximacin tiene varios inconvenientes:

Como el cliente debe acceder a todos los componentes distribuidos individualmente, hay un acoplamiento fuerte entre el cliente y los componentes de negocio del modelo sobre la red. El cliente acede a los componentes distribuidos mediante la capa de red, y eso puede provocar una degradacin del rendimiento si el modelo es complejo y con nmerosos componentes distribuidos. La degradacin de la red y del cliente ocurre cuando el modelo de la aplicacn implementa varios componentes de negocio distribuidos y el cliente interacta directamente con esos componentes para obtener los datos del modelo. Todos esos accesos resultan en llamadas a mtodos remotos que sobrecargan la red e incrementan las charlatanera entre el cliente y la capa de negocio. El cliente debe reconstruir el modelo despus de obtener sus partes desde los componentes distribuidos. Por lo tanto, el cliente necesita tener suficiente lgica de negocio para construir el modelo. Si la construccin del modelo es compleja y se ven implicados en su definicin numerosos objetos, podra haber una sobrecarga adicional en el rendimiento del cliente debido al proceso de construccin. Adems, el cliente debe contener lgica de negocio para manejar las relaciones entre los componentes, lo que resultar en un cliente ms complejo y todava ms grande. Cuando el cliente construye el modelo de la aplicacin, la cosntruccin sucede en el lado del cliente. La construccin de modelos complejos podra resultar en una sobrecarga importante en el rendimiento del lado del cliente para clientes con recursos limitados. Como el cliente est fuertemente acoplado con el modelo, los cambios en el modelo requieren cambios en el cliente. Adems, si hay diferentes tipos de clientes, es ms difcil manejar los cambios entre todos los tipos de cliente. Cuando hay acoplamiento fuerte entre el clente y la implementacin del modelo, lo que ocurre cuando el cliente tiene conocimiento directo del

modelo y maneja las relaciones de los componentes de negocio, los cambios en el modelo necesitan cambios en el cliente. Adems, hay otro problema de duplicacin de cdigo para acceder al modelo, lo que ocurre cuando una aplicacin tiene muchos tipos de clientes. Esta duplicacin hace que los clientes (su cdigo) sea difcil de manejar cuando el modelo cambia.

Causas

Se requiere la separacin de la lgica de negocio entre el cliente y los componentes del lado del servidor. Como el modelo consta de componentes distribuidos, el acceso a cada componente est asociado con un una sobrecarga de red. Es deseable minimizar el nmero de llamadas a mtodos remotos. Normalmente el cliente slo necesita obtener el modelo para presentarlo al usuario. Si el cliente debe interactar con varios componentes para construir el modelo "al vuelo", se incrementa la comunicacin entre el cliente y el servidor. Dicha sobrecarga de comunicacin podra reducir el rendimiento de la red. Incluso si el cliente quiere realizar un actualizacin, normalmente slo actualiza ciertas partes del modelo, y no el modelo completo. Los clientes no necesitan preocuparse de las intrincadas dependencias en la implementacin del modelo. Es deseable perder acoplamiento entre los clientes y los componentes de negocio que implementan el modelo de la aplicacin. Los clientes no necesitan poseer la lgica de negocio adicional requerida para construir el modelo partiendo de varios componentes de modelo.

Solucin
Utilizar un Transfer Object Assembler para construir el modelo o submodelo requerido. El Transfer Object Assembler usa Transfer Objects para recuperar los datos de los distintos objetos de negocio y otros objetos que definen el modelo o una parte del modelo. El Transfer Object Assember construye un Transfer Object compuesto que representa los datos de diferentes componentes de negocio. El Transfer Object transporta datos del modelo al cliente en una sla llamada a mtodo. Como los datos del modelo pueden ser complejos, se recomienda que el Transfer Object no sea modificable. Es decir, el cliente obtiene esos Transfer Objects con el nico propsito de usarlos para presentaciones y procesamientos de slo-lectura. Si est permitido que los clientes hagan cambios en los Transfer Objects. Cuando el cliente necesita los datos del modelo, y si el modelo est representado por un nico componente genrico (como un Composite Entity), el proceso de obtencin del modelo es muy simple. El cliente simplemente solicita el componente genrico para su Transfer Object compuesto. Sin embargo, la mayora de las aplicaciones del mundo real tienen un modelo compuesto de una combinacin de muchos componentes genricos y especficos. En este caso, el cliente debe interactuar con numerosos componentes de negocio para obtener todos los datos necesarios para representar el modelo. El inconveniente inmediato de esta aproximacin se puede ver en que los clientes se convierte en fuertemente acoplados con la implementacin del modelo (elementos del modelo) y que los los clientes tienden a realizar numerosas llamadas a mtodos remotos para obtener los datos de cada componente individual. En algunos casos, un nico componente genrico proporciona el modelo o parte del modelo como nico objeto Transfer Object (simple o compuesto). Sin embargo, cuando varios componentes representan el modelo, un nico Transfer Object (simple o compuesto) podria no representar todo el modelo. Para representar el modelo, es necesario obtener Transfer Objects de varios componentes y ensamblarlos en un Transfer Object Compuesto. El servidor, no el cliente, debera realizar la construccin del modelo "alvuelo".

Estructura
La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrn Transfer Object Assembler:

Participantes y Responsabilidades
El diagrama de secuencia de la siguiente figura muestra la interaccin entre los distintos participantes en el patrn Transfer Object Assembler:

TransferObjectAssembler
El TransferObjectAssembler es la clase principal de este patrn. Construye un nuevo Transfer Object basado en los requerimientos de la aplicacin cuando el cliente solicita un Transfer Object compuesto. Entonces TransferObjectAssembler localiza los ojemplares BusinessObject requeridos para recuperar los datos para construir el Transfer Object compuesto. Los BusinessObjects son objetos de la capa de negocio como beans de entidad o de sesin, DAOs, etc.

Cliente
Si el TransferObjectAssembler se implementa como un objeto Java normal, el cliente normalmente es un Session Facade que proporciona la capa controladora para la capa de negocio. Si el TransferObjectAssembler se implementa como un bean de sesin, el cliente puede ser un Session Facade o un Business Delegate.

BusinessObject
participa en la construccin del nuevo Transfer Object proporcionando los datos requeridos por el TransferObjectAssembler. Por lo tanto, el BusinessObject es un rol que cumple un bean de sesin, un bean de entidad, un DAO, o un objeto normal de Java.
BusinessObject

TransferObject
TransferObject es un Transfer Object compuesto construido por TransferObjectAssembler y devuelto al cliente. Este representa los datos complejos de varios componentes que definen el modelo de la aplicacin.

BusinessObject
BusinessObject es un rol que pueden cumplir un bean de sesin, un bean de entidad, o un DAO. Cuando el ensamblador necesita obtener los datos directamente desde el almacenamiento persistente, para

construir el Transfer Object, puede utilizar un DAO. Esto se puede ver en los diagramas como el objeto DataAccessObject.

Estrategias
Esta seccin explica las diferentes estrategias para implementar el patrn Transfer Object Assembler.

Java Object
El TransferObjectAssembler puede ser un objeto normal de Java y no necesariamente un bean enterprise. En dichas implementaciones, se sita enfrente del TransferObjectAssembler un bean de sesin. Este bean de sesin normalmente es un Session Facade que realiza otras tareas relacionadas con proporcionar servicios de negocio. El TransferObjectAssembler se ejecuta en la capa de negocio, sin importar las estrategias de implementacin. La motivacin para esto es evitar las llamadas remotas desde el TransferObjectAssembler hacia los objetos fuente sin cruzar de capa.

Session Bean
Esta estrategia implementa el TransferObjectAssembler como un bean de sesin. Si se prefiere la implementacin de un bean de sesin para proporcionar el TransferObjectAssembler como un servicio de negocio, normalmente se implementa como un bean de sesin sin estado. Los componentes de negocio que componen el modelo de la aplicacin estn constantemente implicados en transaciones con otros clientes. Como resultado, cuando un TransferObjectAssembler construye un nuevo Transfer Object desde varios componentes de negocio, produce una "foto" del modelo en el momento de la construccin. El modelo podra cambiar inmediatamente despus si otro cliente modifica uno o ms de sus componentes de negocio, cambiando efectivamente el modelo de negocio de la aplicacin. Por lo tanto, implementar TransferObjectAssembler como un bean de sesin con estado no proporciona ningn beneficio sobre su implementacin como un bean de sesin sin estado, ya que es intil preservar el estado del modelo compuesto cuando est cambiando el modelo subyacente. Si cambia ste modelo, hace que el Transfer Object contenido por el Assembler sea obsoleto. Cuando luego se le pide al TransferObjectAssembler, el Transfer Object, o devuelve un estado obsoleto o reconstruye el Transfer Object para obtener una imagen ms reciente. Por lo tanto, se recomienda que el Assembler sea un bean de sesin sin estado. Sin embargo, si el modelo subyacente no cambia o lo hace muy raramente, el ensamblador podra ser un bean de sesin con estado para retener el Transfer Object recientemente construido. En este caso, el TransferObjectAssembler debe incluir mecanismos para reconocer los cambios en el modelo subyacente y reconstruir el modelo para la prxima peticin del cliente.

Business Object
Existen diferentes objetos que pueden soportar el rol del BusinessObject

Puede ser un bean de sesin. El Transfer Object Assembler podra utilizar un Service Locator para localizar el bean de sesin requerido. El Transfer Object Assembler le pide a este bean de sesin que le proporcione los datos para construir el Transfer Object compuesto. El BusinessObject tambin puede ser un bean de entidad. El Transfer Object Assembler podra utilizar un Service Locator para localizar el bean de entidad requerido. El Transfer Object Assembler le pide a este bean de entidad que le proporcione los datos para construir el Transfer Object compuesto. O puede se run DAO. El Transfer Object Assembler le pide a este DAO que le proporcione los datos para construir el Transfer Object compuesto. Tambin puede ser un objeto Java normal. El Transfer Object Assembler le pide a este objeto Java que le proporcione los datos para construir el Transfer Object compuesto. Por ltimo, el BusinessObject puede ser otro Transfer Object Assembler. El primer Transfer Object Assembler le pide al segundo Transfer Object Assembler que le proporcione los datos para construir el Transfer Object compuesto.

Consecuencias

Independiza la Lgica de Negocio Cuando el cliente incluye lgica para manejar las interacciones con componentes distribuidos, es ms dficil separar claramente la lgica de negocio de la capa de cliente. El Transfer Object Assembler contiene la lgica de negocio para mantener las relaciones entre objetos y para construir el Transfer Object compuesto que representa el modelo. El cliente no necesita conocer cmo construir el modelo o los distintos componentes que proporcionan los datos para ensamblar el modelo. Reduce el Acoplamiento entre los Clientes y el Modelo de la Aplicacin El Transfer Object Assembler oculta a los clientes la complejidad de la construccin de los datos del modelo y establece un acoplamiento ligero entre los clientes y el modelo. Con este acoplamiento ligero, si el modelo cambia, el Transfer Object Assembler tambin requerir ese cambio. Sin embargo, el cliente no depende de la constuccin del modelo ni de las relaciones entre los componentes del modelo de negoico, por eso los cambios en el modelo no afectan directamente al cliente. Mejora el Rendimiento de Red El Transfer Object Assembler reduce drsticamente la sobrecarga de red que producen las llamadas a mtodos remotos. El cliente puede solicitar datos del modelo de la aplicacin desde el Transfer Object Assembler con una sla llamada a mtodo. El ensamblador construye y devuelve el Transfer Object compuesto. Sin embargo, este Transfer Object compuesto podra contener una gran cantidad de datos. As, aunque el Transfer Object Assembler reduce el nmero de llamadas a travs de la red, hay un incremento en la cantidad de datos transportados en cada llamada. Este inconveniente se debe tener en cuenta cuando apliquemos este patrn. Mejora el Rendimiento del Cliente El Transfer Object Assembler del lado del servidor construye el modelo como un Transfer Object compuesto sin utilizar ningn recurso del cliente. El cliente no utiliza su tiempo para ensamblar el modelo. Mejora el Rendimiento de la Transacin Normalmente, las actualizaciones se aslan en una parte muy pequea del modelo y se pueden realizar mediante transaciones especficas. Estas transaciones se enfocan en las partes aisladas del modelo en lugar de bloquear el objeto genrico (modelo). Despus de que el cliente obtiene el modelo y lo muestra o procesa localmente, el usuario (o cliente) podra necesitar actualizar o modificar el modelo. El cliente puede interactar directamente con un Session Facade para conseguir esto a un nivel de especificidad aceptable. El Transfer Object Assembler no est implicado en la transacin para actualizar o modificar el modelo. Hay un mejor control del rendimiento porque el trabajo de transaciones con el modelo sucede con el nivel de especificidad apropiado. Podra Presentar Transfer Objects Obsoletos El Transfer Object Assembler construye Transfer Objects bajo pedido. Estos Transfer Objects son fotografas del estado actual del modelo, representadas por varios componentes de negocio. Una vez que el cliente obtiene un Transfer Object del ensamblador, este Transfer Object es enteramente local al cliente. Como los Transfer Objects no se preocupan de la red, otros cambios hechos a los componentes de negocio usados para construir el Transfer Object no se vern reflejados en ste. Por lo tanto, despues de obtener el Transfer Object, se puede convertir en obsoleto rpidamente si hay transaciones sobre los componentes de negocio.

Cdigo de Ejemplo
Implementar el Transfer Object Assembler
Consideremos una aplicacin de control de proyectos donde varios componentes de la capa de negocio definen el modelo complejo. Supongamos que un cliente quiere obtener el modelo de datos compuesto de datos de varios objetos de negocio, como:

Informacin del Proyecto desde el componente Project. Informacin del Manager del Proyecto desde el componente ProjectManager. Lista de Tareas del Proyecto desde el componente Project. Informacin de Recursos desde el componente Resource.

Se puede definir un Transfer Object compuesto como se ve en el siguiente ejemplo. Se puede implementar un Transfer Object Assembler para ensamblar este Transfer Object.

public class ProjectDetailsData { public ProjectTO projectData;

public ProjectManagerTO projectManagerData; public Collection listOfTasks; ... }

El listado de tareas de ProjectDetailsData es una collection de objetos TaskResourceTO. TaskResourceTO es una combinacin de TaskTO y ResourceTO. Abajo podemos ver estas clase: Ejemplo de la clase TaskResourceTO:

public class TaskResourceTO { public String projectId; public String taskId; public String name; public String description; public Date startDate; public Date endDate; public ResourceTO assignedResource; ... public TaskResourceTO(String projectId, String taskId, String name, String description, Date startDate, Date endDate, ResourceTO assignedResource) { this.projectId = projectId; this.taskId = taskId; ... this.assignedResource = assignedResource; } ... }

Ejemplo de la clase TaskTO:

public class TaskTO { public String projectId; public String taskId; public String name; public String description; public Date startDate; public Date endDate; public assignedResourceId; public TaskTO(String projectId, String taskId, String name, String description, Date startDate, Date endDate, String assignedResourceId) { this.projectId = projectId; this.taskId = taskId; ... this.assignedResource = assignedResource; } ... }

Ejemplo de la clase ResourceTO:

public class ResourceTO { public String resourceId; public String resourceName; public String resourceEmail; ... public ResourceTO (String resourceId, String resourceName, String resourceEmail, ...) { this.resourceId = resourceId; this.resourceName = resourceName; this.resourceEmail = resourceEmail; ... } }

En el siguiente listado tenemos la clase ProjectDetailsAssembler que ensambla el objeto ProjectDetailsData:

public class ProjectDetailsAssembler implements javax.ejb.SessionBean { ... public ProjectDetailsData getData(String projectId){ // Construct the composite Transfer Object ProjectDetailsData pData = new ProjectDetailsData(); //get the project details; ProjectHome projectHome = ServiceLocator.getInstance().getHome( "Project", ProjectEntityHome.class); ProjectEntity project = projectHome.findByPrimaryKey(projectId); ProjectTO projTO = project.getData(); // Add Project Info to ProjectDetailsData pData.projectData = projTO; //get the project manager details; ProjectManagerHome projectManagerHome = ServiceLocator.getInstance().getHome( "ProjectManager", ProjectEntityHome.class); ProjectManagerEntity projectManager = projectManagerHome.findByPrimaryKey( projTO.managerId); ProjectManagerTO projMgrTO = projectManager.getData(); // Add ProjectManager info to ProjectDetailsData pData.projectManagerData = projMgrTO; // Get list of TaskTOs from the Project Collection projTaskList = project.getTasksList(); // construct a list of TaskResourceTOs ArrayList listOfTasks = new ArrayList(); Iterator taskIter = projTaskList.iterator(); while (taskIter.hasNext()) { TaskTO task = (TaskTO) taskIter.next(); //get the Resource details; ResourceHome resourceHome = ServiceLocator.getInstance().getHome( "Resource", ResourceEntityHome.class); ResourceEntity resource = resourceHome.findByPrimaryKey( task.assignedResourceId); ResourceTO resTO = resource.getResourceData(); // construct a new TaskResourceTO using Task // and Resource data TaskResourceTO trTO = new TaskResourceTO( task.projectId, task.taskId, task.name, task.description, task.startDate, task.endDate, resTO); // add TaskResourceTO to the list listOfTasks.add(trTO); } // add list of tasks to ProjectDetailsData pData.listOfTasks = listOfTasks; // add any other data to the Transfer Object ... // return the composite Transfer Object return pData; } ...

Patrones Relacionados

Transfer Object Transfer Object Assembler usa el patrn Transfer Object para poder crear y transportar Transfer Objects al cliente. Los Transfer Objects creados llevan los datos que representan el modelo de la aplicacin desde la capa de negocio hasta los clientes que han solicitado los datos. Composite Entity El patrn Composite Entity promueve el diseo de un bean de entidad genrico, donde las entidades pueden producir Transfer Objects compuestos similares al producido por el Transfer Object Assembler. Sin embargo, el Transfer Object Assembler es ms aplicable cuando el Transfer Object compuesto construido se deriva de varios componentes (beans de sesin, beans de entidad, DAOs, etc.), mientras que el patrn Composite Entity construye el Transfer Object desde sus propios datos (es decir, un nico bean de entidad). Session Facade El Transfer Object Assembler se implementa tpicamente como un bean de sesin sin estado. Como tal, podra ser visto como una aplicacin especial limitada del patrn Session Facade. Ms importante, Transfer Object Assembler construye Transfer Objects que no se pueden modificar. Por lo tanto, el cliente que lo recibe slo puede utilizarlo para propsitos de presentacin y procesamiento. El cliente no puede actualizar el Transfer Object. Si el cliente necesita actualizar los objetos de negocio de los que deriva el Transfer Object compuesto, podra tener que acceder al Session Facade (bean de sesin) que proporciona ese servicio de negocio. Data Access Object Una posible estrategia para el Transfer Object Assembler implica obtener datos para el Transfer Object compuesto desde almacenamiento persistente sin utilizar beans enterprise. En estos casos se puede aplicar el patrn Data Access, y aprovecharnos de sus beneficios parar proporcionar acceso al almacenamiento persistente al Transfer Object Assembler. Service Locator El Transfer Object Assembler necesita localizar y utilizar varios objetos de negocio. Se puede utilizar el patrn Service Locator en conjuncin con el patrn Transfer Object Assembler siempre que sea necesario localizar un objeto o servicio de negocio.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Value List Handler o Contexto o Problema o Causas o Solucin Estructura Participantes y Colaboraciones Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Value List Handler como un objeto Java o Patrones Relacionados

Value List Handler


Contexto
El cliente le pide al servicio una lista de tems para su presentacin. El nmero de tems de la lista no se conoce y puede ser muy grande en muchas circunstancias.

Problema
La mayora de las aplicaciones de la plataforma J2EE tienen un requerimiento de bsqueda y consulta para buscar y listar ciertos datos. En algunos casos, dichas operaciones de bsqueda y consulta podran traer resultados que pueden ser bastante grandes. No es prctico devolver toda la hoja de resultados cuando los requerimientos del cliente son moverese por los resultados, en vez de procesar el conjunto completo. Normalmente, un cliente usa los resultados de una consulta para propsitos de slo-lectura, como mostrar una lista de resultados. Muchas veces el cliente slo ve los primeros registros que devuelve la bsqueda, y podra descargar los registros restantes e intentar otra nueva consulta. La prctica de obtener uns lista de valores representados en un bean de entidad llamando al mtodo ejbFind(), que devuelve una collection de objetos remotos, y luego llamar a cada bean de entidad para obtener el valor, consume muchos recursos de red y se considera una mala prctica. Hay algunas consecuencias asociadas con el uso de los mtodos bscadores de EJB que resultan en grandes conjuntos de datos. Cada implementacin de contenedor tiene una cierta cantidad de mtodos bscadores para crear una coleccin de referencias EJBObject. El rendimiento del mtodo de bsqueda vara, dependiendo de la implementacin del contenedor. De acuerdo a la especificacin EJB, un contenedor podra invocar a mtodos ejbActivate() sobre entidades encontradas con los mtodos de bsqueda. Como mnimo, un mtodo de bsqueda devuelve las claves primarias de las entidades encontradas, que el contenedor devuelve al cliente como una coleccin de referencias EJBObject. Este comportamiento se aplica para todas las implementaciones de contenedores. Algunas implementaciones podran introducir una sobrecarga de mtodos de bsqueda asociando los ejemplares de beans de entidad a esos ejemplares EJBObject para darle acceso al cliente a esos beans de entidad. Sin embargo, este es un uso pobre de los recursos si el cliente no est interesado en acceder al bean o en invocar sus mtodos. Esta sobrecarga puede impedir el rendimiento de la aplicacin si sta incluye consultas que producen muchos resultados.

Causas

La aplicacin cliente necesita una facilidad de consulta eficiente para evitar tener que llamar al mtodo ejbFind() de cada bean e invocar a cada objeto remoto devuelto. Se necesita una mecanismo de cach en la capa-servidor para servir a los clientes que no pueden recibir y procesar el cojunto de resultados completo.

Se puede optimizar una consulta que se ejecuta repetidamente sobre unos datos razonablemente estticos para proporcionar resultados ms rpidos. Esto depende de la aplicacin y de la implementacin de este patrn. Los mtodos de bsqueda EJB no son apropiados para navegar por tablas enteras en la bases de datos o para buscar grandes conjuntos de resultados en una tabla. Los mtodos de bsqueda se podran considerar sobrecargados cuando se utilizan para encontrar grandes cantidades de resultados. El contenedor podra crear un gran nmero de objetos de infraestructura para facilitar las bsquedas. Los mtodos de bsqueda EJB no sin apropiados para realizar cach de resultados. El cliente podra no ser capaz de manejar el conjunto completo de resultados en una sla llamada. Si es as, el cliente podra necesitar un cach en el lado del cliente y funciones de navegacin para moverese por el conjunto de resultados. Los mtodos de bsqueda EJB tiene consultas predeterminadas y ofrecen una flexibilidad mnima. La especificacin EJB 2.0 permite un lenguaje de consulta, EJB QL, para beans de entidad manejados por el contenedor. EJB QL hace ms fcil escribir mtodos de bsqueda portables y ofrece una mayor flexibilidad. El cliente quiere moverse hacia adelante o hacia atrs dentro de la hoja de resultados.

Solucin
Utilizar un Value List Handler para controlar la bsqueda, hacer un cach con los resultados, y proporcionar los resultados al cliente en una hoja de resultados cuyo tamao y desplazamiento cumpla los requerimientos del cliente. Este patrn crea un ValueListHandler para controlar la funcionalidad de la ejecucin de la consulta y el cach de resultados. El ValueListHandler accede directamente a un DAO que puede ejecutar la consulta requerida. El ValueListHandler almacena los resultados obtenidos del DAO como una coleccin de Transfer Objects. El cliente le pide al ValueListHandler que proporcione resultados de la consulta segn los necesite. El ValueListHandler implementa un patrn Iterator [GoF] para proporcionar la solucin.

Estructura
La siguiente figura muestra el diagrama de clases para el patrn Value List Handler:

Participantes y Colaboraciones
La siguiente figura muestra el diagrama de secuencia del patrn Value List Handler:

ValueListIterator

Este interface podra proporcionar la facilidad de iteracin con los siguientes mtodos de ejemplo:

obtiene el tamao de la hoja de resultados. obtiene el Transfer Object actual de la lista. getPreviousElements(int howMany) obtiene una coleccin de Transfer Objects que son anteriores en la lista al elemento actual. getNextElements(int howMany) obtiene una coleccin de Transfer Objects que son posteriores en la lista al elemento actual. resetIndex() reinicia el ndice para ir al inicio de la lista.
getSize() getCurrentElement()

Dependiendo de las necesidades, se pueden incluir otros mtodos de conveniencia en el interface


ValueListIterator.

ValueListHandler
Este es el objeto que implementa el interface ValueListIterator. ValueListHandler ejecuta la consulta requerida cuando se lo solicita el cliente. Obtiene los resultados de la consulta, que maneja en una coleccin privada representada por el objeto ValueList. ValueListHandler crea y manipula la coleccin ValueList. Cuando el cliente solicita los resultados, ValueListHandler obtiene los Transfer Objects desde el ValueList cacheado, crea una nueva coleccin de Transfer Objects, serializa la coleccin y la enva de vuelta alcliente. ValueListHandler tambin sigue la pista del ndice actual y del tamao de la lista.

DataAccessObject
ValueListHandler

puede hacer uso de un DataAccessObject para mantener separada la implementacin del acceso a la base de datos. DataAccessObject proporciona un API sencillo para acceder a la base de datos (o cualquier otro almacenamiento persistente), ejecuta consultas y recupera resultados.

ValueList
ValueList

es una coleccin (una lista) que contiene los resultados de la consulta. Los resultados se almacenan como objetos Transfer Objects. Si falla la consulta y no se devuelven resultados, entonces esta lista est vaca. El bean de sesin ValueListHandler puede almacenar ValueList para evitar repeticiones innecesarias de la consulta.

TransferObject
TransferObject representa una vista de un registro individual de los resultados de la consulta. Es un objeto serializable no modificable que proporciona un espacio para los datos de los atributos de cada registro.

Estrategias

Java Object
Se puede implementar el ValueListHandler como un objeto Java arbitario. En este caso, el ValueListHandler puede ser utilizado por cualquier cliente que necesite esa funcionalidad. Para aplicaciones que no usan beans enterprise, esta estrategia es muy til. Por ejemplo se podra construir aplicaciones sencillas utilizando servlets, JSPs, Business Delegates, y DAOs. En este escenario, el Business Delegates puede utilizar un ValueListHandler implementado como un objeto Java para obtener una lista de valores.

Stateful Session Bean


Cuando una aplicacin utiliza beans enterprise en la capa de negocio, se podra preferir implementar un bean de sesin que utilice el ValueListHandler. En este caso, el bean de sesin simplemente se enfrenta a un ejemplar de ValueListHandler. As, el bean de sesin se podra implementar como un bean de sesin con estado para contener la lista y su estado, y esto simplemente podra actar como una fachada o como un proxy.

Consecuencias

Proporciona Alternativas a los mtodos find() de EJB para Grandes Consultas Normalmente, un mtodo de bsqueda EJB es una forma cara de obtener una lista de tems, ya que implica un nmero de referencias EJBObject. Value List Handler implementa un bean de sesin que utiliza un DAO para realizar la consulta y para proporcionar una coleccin de Transfer Objects que cumplen el criterio de bsqueda. Como los Transfer Objects tienen poca sobrecarga en comparacin con las referencias EJBObject y su infraestructura asociada, este patrn proporciona beneficios cuando las aplicaciones clientes requieren grandes cantidades de resultados. Crea un Cach de Resultados de la Consulta en el Lado del Servidor Se necesita cachear los resultados obtenidos de la ejecucin de la consulta cuando un cliente debe mostrarlos en pequeas partes en vez de una gran lista. Sin embargo, no todos los clientes basados en navegador puede realizar dicho cach. Cuando no pueden, el servidor debe proporcionar esta funcioalidad. El patrn Value List Handler proporciona una facilidad de cach en el bean de sesin para contener los resultados de la consulta. El conjunto de resultados es una coleccin de Transfer Objects que se puede serializar si es necesario. Cuando el cliente solicita una coleccin, o un subconjunto de una coleccin, el baen manejador devuelve los resultados solicitados como una coleccin serializada de Transfer Objects. El cliente recibe la coleccin y ahora tiene una copia local de la informacin, que el cliente puede mostrar o procesar. Cuando el cliente necesita un subconjunto adicional de resultados, le solicita al manejador que devuelva otra coleccin serializada que contenga los resultados necesarios. El cliente puede procesar la consulta en trozos ms pequeos y manejables. El bean manejador tambin le proporciona al cliente facilidades de navegacin (anterior y siguiente) para que pueda moverse por la lista de la forma necesaria. Proporciona una Mayor Flexibilidad de Consulta Aadir una nueva consulta podra requerir la creacin de un nuevo mtodo finder o modificar uno existente, especialmente cuando se utilizan beans de entidad manejados por el bean (con beans de entidad manejados por el bean, el desarrollador implementa los mtodos de bsqueda en la implementacin del bean). Con un bean de entidad manejado por el contenedor, el desarrollador especifica los mtodos finder del bean de entidad en el descriptor de despliegue del bean. Los cambios en una consulta para bean manejado por el contenedor requieren cambios en el descriptor de despliegue. Por lo tanto, estos mtodos no son muy adecuados cuando los requerimientos de la consulta cambian dinmicamente. Podemos implementar un Value List Handler para que sea ms flexible que los mtodos del EJB proporcionado facilidades de consultas dinmicas, construyendo los argumentos de la consulta en el momento de la ejecucin utilizando plantillas de mtodos, etc. En otras palabras, un desarrollador de un Value List Handler puede implementar bsqueda inteligente y algoritmos de cach sin verse limitado por los mtodos finder. Mejora el Rendimiento de Red El rendimiento de la red se ve mejorado porque slo los datos solicitados, en vez de todos los datos, se envan (serializados) al cliente sobre unas necesidades bsicas. Si el cliente muestra los primeros resultados y luego abandona la consulta, no se ha ocupado el ancho de banda de la red, ya que los datos se almacenan en el servidor y nunca se han envado al cliente. Sin embargo, si el cliente procesa todos los resultados, hace varias llamadas remotas al servidor. Cuando el cliente conoce por adelantado que necesita todos los resultados, el bean manejador puede proporcionar un mtodo que los enve al cliente en una sola llamada a mtodo, y no se utiliza el cach. Permite Atrasar las Transaciones del Bean de Entidad El cach de los resultados en el lado del servidor permite minimizar la sobrecarga de la bsqueda y podra mejorar el control de transaciones. Cuando el cliente est listo para procesar un bean de entidad, accede al bean dentro de un contexto de transacin definido por el caso de utilizacin. Por ejemplo, una consulta para mostrar una lista de libros utiliza un Value List Handler para obtener la lista. Cuando el usuario quiere ver los detalles de un libro, implica al bean de entidad del libro en la transacin.

Cdigo de Ejemplo
Implementar el Value List Handler como un objeto Java
Consideremos un ejemplo donde se va a recuperar y mostrar una lista de objetos de negocio de un Proyecto. En este caso se puede aplicar el patrn Value List Handler. En el siguiente ejemplo tenemos la clase ProjectListHandler, que es responsable de proporcionar la lista de proyectos. Esta clase extiende la

clase base ValueListHandler, que proporciona la funcionalidad de iteracin genricoa para todas las implementaciones de Value List Handler de esta aplicacin.

package corepatterns.apps.psa.handlers; import import import import java.util.*; corepatterns.apps.psa.dao.*; corepatterns.apps.psa.util.*; corepatterns.apps.psa.core.*;

public class ProjectListHandler extends ValueListHandler { private ProjectDAO dao = null; // use ProjectTO as a template to determine // search criteria private ProjectTO projectCriteria = null; // Client creates a ProjectTO instance, sets the // values to use for search criteria and passes // the ProjectTO instance as projectCriteria // to the constructor and to setCriteria() method public ProjectListHandler(ProjectTO projectCriteria) throws ProjectException, ListHandlerException { try { this.projectCriteria = projectCriteria; this.dao = PSADAOFactory.getProjectDAO(); executeSearch(); } catch (Exception e) { // Handle exception, throw ListHandlerException } } public void setCriteria(ProjectTO projectCriteria) { this.projectCriteria = projectCriteria; } // executes search. Client can invoke this // provided that the search criteria has been // properly set. Used to perform search to refresh // the list with the latest data. public void executeSearch() throws ListHandlerException { try { if (projectCriteria == null) { throw new ListHandlerException( "Project Criteria required..."); } List resultsList = dao.executeSelect(projectCriteria); setList(resultsList); } catch (Exception e) { // Handle exception, throw ListHandlerException } } }

En el siguiente cdigo tenemos la clase ValueListHandler que implementa el interface del iterador genrico ValueListIterator, que veremos en siguientes listados.

package corepatterns.apps.psa.util; import java.util.*; public class ValueListHandler implements ValueListIterator { protected List list; protected ListIterator listIterator; public ValueListHandler() { } protected void setList(List list) throws IteratorException { this.list = list; if(list != null) listIterator = list.listIterator(); else throw new IteratorException("List empty"); }

public Collection getList(){ return list; } public int getSize() throws IteratorException{ int size = 0; if (list != null) size = list.size(); else throw new IteratorException(...); //No Data return size; } public Object getCurrentElement() throws IteratorException { Object obj = null; // Will not advance iterator if (list != null) { int currIndex = listIterator.nextIndex(); obj = list.get(currIndex); } else throw new IteratorException(...); return obj; } public List getPreviousElements(int count) throws IteratorException { int i = 0; Object object = null; LinkedList list = new LinkedList(); if (listIterator != null) { while (listIterator.hasPrevious() && (i < count)){ object = listIterator.previous(); list.add(object); i++; } }// end if else throw new IteratorException(...); // No data return list; } public List getNextElements(int count) throws IteratorException { int i = 0; Object object = null; LinkedList list = new LinkedList(); if(listIterator != null){ while( listIterator.hasNext() && (i < count) ){ object = listIterator.next(); list.add(object); i++; } } / / end if else throw new IteratorException(...); // No data return list; } public void resetIndex() throws IteratorException{ if(listIterator != null){ listIterator = list.ListIterator(); } else throw new IteratorException(...); // No data } ... }

Abajo tenemos el cdigo importante para acceder al objeto ProjectDAO, utilizado por ValueListHandler para ejecutar la consulta y obtener los resultados.

package corepatterns.apps.psa.dao; public class ProjectDAO {

final private String tableName = "PROJECT"; // select statement uses fields final private String fields = "project_id, name," + "project_manager_id, start_date, end_date, " + " started, completed, accepted, acceptedDate," + " customer_id, description, status"; // the methods relevant to the ValueListHandler // are shown here. // See Data Access Object pattern for other details. ... private List executeSelect(ProjectTO projCriteria) throws SQLException { Statement stmt= null; List list = null; Connection con = getConnection(); StringBuffer selectStatement = new StringBuffer(); selectStatement.append("SELECT "+ fields + " FROM " + tableName + "where 1=1"); // // // if append additional conditions to where clause depending on the values specified in projCriteria (projCriteria.projectId != null) { selectStatement.append (" AND PROJECT_ID = '" + projCriteria.projectId + "'");

} // check and add other fields to where clause ... try { stmt = con.prepareStatement(selectStatement); stmt.setString(1, resourceID); ResultSet rs = stmt.executeQuery(); list = prepareResult(rs); stmt.close(); } finally { con.close(); } return list; } private List prepareResult(ResultSet rs) throws SQLException { ArrayList list = new ArrayList(); while(rs.next()) { int i = 1; ProjectTO proj = new ProjectTO(rs.getString(i++)); proj.projectName = rs.getString(i++); proj.managerId = rs.getString(i++); proj.startDate = rs.getDate(i++); proj.endDate = rs.getDate(i++); proj.started = rs.getBoolean(i++); proj.completed = rs.getBoolean(i++); proj.accepted = rs.getBoolean(i++); proj.acceptedDate = rs.getDate(i++); proj.customerId = rs.getString(i++); proj.projectDescription = rs.getString(i++); proj.projectStatus = rs.getString(i++); list.add(proj); } return list; } ... }

Cdigo de ejemplo de la clase ValueListIterator:

package corepatterns.apps.psa.util; import java.util.List; public interface ValueListIterator { public int getSize() throws IteratorException; public Object getCurrentElement() throws IteratorException;

public List getPreviousElements(int count) throws IteratorException; public List getNextElements(int count) throws IteratorException; public void resetIndex() throws IteratorException; // other common methods as required ... }

Patrones Relacionados

Iterator [GoF] El patrn Value List Handler est basado en el patrn Iterator, descrito en el libro de Gof: Design Patterns: Elements of Reusable Object-Oriented Software. Session Facade Como el Value List Handler es un bean de sesin, podra aparecer como un Session Facade especializado. Sin embargo, aisladamente, es un bean de sesin especializado en vez de un Session Facade. Un Session Facade tiene otras motivaciones y caractersticas y es mucho ms genrico.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Composite Entity o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Codigo de Ejemplo Implementacin del patrn Composite Entity Implementar la Estrategia Lazy Loading Implementar la Estrategia Store Optimization (Dirty Marker) Implementar la Estrategia Composite Transfer Object o Patrones Relacionados o Bean de Entidad como un Objeto Dependiende: Problemas y Recomendaciones

Composite Entity
Contexto
Los beans de entidad no se han pensado para representar todos los objetos persistentes del modelo. Los beans de entidad son mejores para objetos de negocio persistentes genricos.

Problema
En una aplicacin de la plataforma J2EE, los clientes -- como aplicaciones, pginas JSP, servlets, componentes JavaBeans -- acceden a los beans de entidad mediante sus interfaces remotos. As, toda llamada de cliente potencialmente se enruta a travs de los stubs (trozos) y skeletons (esqueletos), incluso si el cliente y el bean enterprise estn en la misma Mquina Virtual Java, en el mismo sistema operativo o en la misma mquina fsica. Cuando los beans enterprise son objetos especficos, los clientes tienden a invocar los mtodosdel bean de forma ms individual, resultando en una gran sobrecarga en la red. Los beans de entidad representan objetos persistentes de negocio distribuidos. Siempre que desarrollemos o migremos una aplicacin a la plataforma J2EE, la especificad de los objetos es muy importante cuando decidimos implementarlos como beans de entidad. Los beans de entidad deberan representar objetos de negocio genricos, como aquellos que proporcionan un comportamiento complejo ms all de simplemente obtener y seleccionar valores de campos. Estos objetos genricos normalmente tienen objetos dependientes. Un objeto dependiente es un objeto que no tiene un significado real cuando no est asociado con su padre genrico. Un problema recurrente es el mapeo directo del modelo a un modelo de JavaBeans Enterpise (especificamente beans de entidad). Esto crea una relacin entre los objetos beans de entidad en su consideracin de genricos contra objetos especficos (o dependientes). Determinar cuando utilizar objetos genricos o especificados es muy dificil y se puede hacer mejor utilizando un modelo de relaciones mediante Unified Modeling Language (UML). Hay varias reas que se ven impactadas por la aproximacin del diseo del bean de entidad especfico:

Relaciones de Entidades - Mapear directamente un objeto de modelo a un modelo EJB no tiene en cuenta el impacto de las relaciones entre objetos. Las relaciones inter-objetos se transforman directamente en relaciones inter-beans. Como resultado, un bean de entidad podra contener o almacenar una referencia remota a otro bean de entidad. Sin embargo, mantener referencias

remotas a objetos distribuidos implica tcnicas y semnticas diferentes a la de mantener referencias a objetos locales. Junto con el incremento de complejidad del cdigo, se reduce la flexibilidad porque el bean de entidad debe cambiar si cambia alguna de sus relaciones. Adems, no hay garantas de la validez de las referencias de un bean de entidad a otro bean de entidad en el tiempo. Dichas referencias se establecen dinmicamente utilizando el objeto home de la entidad y la clave primaria para ese ejemplar de bean. Esto implica una alta sobrecarga de mantenimiento para el chequeo de validez de la referencia por cada referencia de bean-deentidad-a-bean-de-entidad. Manejabilidad - Implementar objetos especficos como beans de entidad resulta en un mayor nmero de beans de entidad en el sistema, el desarrollador debe proporcionar clases para el interface home, el interface remote, la implementacin del bean y la clave primaria. Adems, el contenedor podra generar clases para soportar la implementacin del bean de entidad. Cuando se crea el bean, esta clases se convierten en objetos reales en el contenedor. En breve, el contenedor crea varios objetos para soportar cada ejemplar de bean de entidad. Un mayor nmero de beans de entidad significa ms clases y cdigo que mantener por el equipo de desarrollo. Tambin resulta en un mayor nmero de objetos en el contenedor. Esto puede impactar negativamente en el rendimiento de la aplicacin. Rendimiento de Red -- los beans de entidad especficos, potencialmente tienen ms relaciones inter-beans. Los beans de entidad son objetos distribuidos. Cuando un bean de entidad invoca un mtodo de otro bean de entidad, el contenedor trata esa llamada como una llamada remota, incluso si ambos beans estn en el mismo contenedor. Si el nmero de relaciones bean-deentidad-a-bean-de-entidad se incrementa, se reduce la escalabilidad del sistema debido a la fuerte sobrecarga de la red. Dependencia del Esquema de Base de Datos - Cuando los beans de entidad son especficos cada ejemplar normalmente representa una sla fila de la base de datos. Esto no es una aplicacin apropiada del diseo de beans de entidad, ya que los beans de entidad son ms apropiados para componentes genricos. La implementacin de beans de entidad especficos normalmente es una representacin directa del esquema de la base de datos subyacente en el diseo del bean de entidad. Cuando los clientes utilizan estos beans de entidad especficos, estn operando esencialmente a nivel de fila en la base de datos, ya que cada bean de entidad efectivamente es una nica fila. Como el bean de entidad modela directamente una sola fila de la base de datos, los clientes dependen del esquema de la base de datos. Cuando el esquema cambia, tambin deben cambiar las definiciones del bean de entidad. Adems, como los clientes estn operando con la misma especificidad, deben observar y reaccionar ante estos cambios. Esta dependencia del esquema causa una prdida de flexibilidad e incrementa la sobrecarga de mentenimiento requerida cuando cambia el esquema. Especificidad del Objeto (Genrico frente a Especfico) -- La especificidad del objeto impacta en la transferencia de datos entre el bean enterprise y el cliente. En muchas aplicaciones, los clientes necesitan un trozo de datos mayor que una o dos filas de la tabla. En dichos casos, implementar cada unos de estos objetos especficos como un bean de entidad significa que el cliente tendra que manejar las relaciones entre todos esos objetos especficos. Dependiendo de los requerimientos de datos, el cliente podra tener que realizar muchas bsquedas de varios beans de entidad para obtener la informacin necesaria.

Causas

Los beans de entidad son mejores para implementar objetos genricos debido a la alta sobrecarga asociada con todo bean de entidad. Todo bean de entidad se implementa utilizando muchos objetos, como el objeto home, el objetoremote, la implementacin del bean, y la clave primaria, y todos son controlados por los servicios del contenedor. Las aplicaciones que mapean directamente un esquema de una base de datos relacional a beans de entidad (donde cada fila de la tabla se representa como un ejemplar de un bean de entidad) tienden a tener un mayor nmero de beans de entidad especficos. Es deseable mantener el nmero de beans de entidad genricos y reducir el nmero de beans de entidad de la aplicacin, y as reducir el nmero de beans deentidad de la aplicacin. Mapear directamente el modelo de objetos al modelo EJB trae beans de entidad especficos. Estos beans normalmente se mapean al esquema de la base de datos. Este mapeo de entidades-a-fila-de-base-de-datos causa problemas relacionados con el rendimiento, la manejabilidad, la seguridad y el manejo de transaciones. Las relaciones entre las tablas se implementan como relaciones entre beans de entidad, lo que significa que los beans de entidad contienen referencias a otros beans de entidad para implementar las relaciones especficas. Es muy costoso manejar las relaciones entre estos beans porque deben establecerse dinmicamente, utilizando los objetos home de los beans de entidad y las claves primarias de los beans enterprise.

Los clientes no necesitan conocer la implementacin del esquema de la base de datos para utilizar y soportar los beans de entidad. Con beans de entidad especficos, el mapeo se hace normalmente para que cada ejemplar de bean de entidad corresponda con una sla fila de la base de datos. Este mapeo especfico crea una dependencia entre el cliente y el esquema de la base de datos subyacente, ya que el cliente trata con beans especficos y stos esencialmente son una representacin directa del esquema subyacente. Esto resulta en un fuerte acoplamineto entre el esquema de la base de datos y los beans de entidad. Un cambio en el esquema causa el cambio correspondiente en el bean de entidad, y adems requiere el cambio correspondiente en los clientes. Hay un incremento de la charlatanera de las aplicaciones debido a la intercomunicacin entre los beans especficos. Esta excesiva comunicacin entre los beans especficos frecuentemente provoca un cuello de botella en el rendimiento. Toda llamada a mtodo del bean de entidad se hace mediante la capa de red, incluso si el llamador est en el mismo espacio de direcciones que el bean llamado (es decir, si tanto el cliente como el bean de entidad estn en el mismo contenedor). Aunque algunos contenedores han optimizado este escenario, el desarrollador no puede esperar esta optimizacin en todos los contenedores. Se puede observar una charlataneria adicional entre el cliente y los beans de entidad porque el cliente podra tener que comunicar con muchos beans de entidad especficos para cumplir los requerimientos. Es deseable reducir la comunicacin entre los beans de entidad para reducir la charlataneria entre el cliente y la capa del bean de entidad.

Solucin
Utilizar Composite Entity para modelar, representar y manejar un conjunto de objetos persistentes relacionados en vez de representarlos como beans de entidad especficos individuales. Un bean Composite Entity representa un grupo de objetos. Para entender esta solucin, primero definamos que significan los objetos persistentes y discutiremos sus relaciones. Un objeto persistente es un objeto que se almacena en algn tipo de almacenamiento. Normalmente mltiples clientes comparten los objetos persistentes. Los objetos persistentes se pueden clasificar en dos tipos: objetos genricos y objetos dependientes. Un objeto genrico es autosuficiente. Tiene su propio ciclo de vida y maneja sus relaciones con otros objetos. Todo objeto genrico podra referenciar o contener uno o ms objetos. El objeto genrico normalmente maneja el ciclo devida de estos objetos. De ah, que esos objetos sean conocidos como objetos dependientes. Un objeto dependiente puede ser un simple objeto auto-contenido o podra a su vez contener otros objetos dependientes. El ciclo de vida de un objeto dependiente est fuertemente acoplado al ciclo de vida del objeto genrico. Un cliente slo podra acceder al objeto dependiente atravs del objeto genrico. Es decir, los objetos dependientes no se exponen directamente a los clientes porque su objeto padre (genrico) los maneja. Los objetos dependientes no pueden existir por s mismos. En su lugar, siempre necesitan tener su objeto genrido (o padre) para justificar su existencia. Normalmente, podemos ver la relaciones entre un objeto genrico y sus objetos dependientes como un rbol. El objeto genrico es la raz del rbol (el nodo raz). Cada objeto dependiente puede ser un objeto dependientes solitario (un nodo hoja) que es hijo del objeto genrico. O, el objeto dependiente puede tener relaciones padre-hijo con otros objetos dependientes, en cuyo caso se considera un nodo rama. Un bean Composite Entity puede representar un objeto genrico y todos sus objetos dependientes relacionados. Esta combinacin de objetos persistentes relacionados dentro de un slo bean de entidad reduce drsticamente el nmero de beans de entidad requeridos por la aplicacin. Esto genera un bean de entidad altamente genrico que puede obtener mejor los beneficios de los beans de entidad que un bean de entidad especfico. Sin la aproximacin Composite Entity, hay una tendencia a ver todos los objetos genricos y dependientes como beans de entidad separados, suponiendo un gran nmero de beans de entidad.

Estructura

Aunque hay muchas estrategias para implementar el patrn Composite Entity, la primera que vamos a explicar est representada en el siguiente diagrama de clases. Aqu el Composite Entity contiene el objeto genrico, y ste contiene objetos dependientes:

El diagrama de secuencia de la siguiente imagen muestra las interacciones para este patrn:

Participantes y Responsabilidades

CompositeEntity
CompositeEntity

es un bean de entidad genrico. Podra ser un objeto genrico, o podra contener una referencia a un objeto genrico.

Coarse-Grained Object
Un objeto genrico es un objeto que tiene su propio ciclo de vida y que maneja sus propias relaciones con otros objetos. Un objeto genrico puede ser un objeto Java contenido en el CompositeEntity. O, el propio Composite Entity puede ser un objeto genrico que contiene objetos dependientes.

DependentObject1, DependentObject2, y DependentObject3


Un objeto dependiente es un objeto que depende de un objeto genrico el cual gobierna el ciclo de vida del objeto dependiente. Un objeto dependiente puede contener otros objetos dependientes; as podra existir un rbol de objetos dentro del Composite Entity.

Estrategias
Esta seccin explica las diferentes estrategias para implementar el patrn Composite Entity. Las estrategias consideran posibles alternativas y opciones para objetos persistentes (genricos y dependientes), y la utilizacin deTransfer Objects.

El Composite Entity Contiene Objetos Genricos


En esta estrategia, el Composite Entity almacena o contiene el objeto genrico. Este objeto genrico contina teniendo relaciones con sus objetos dependientes. La seccin Estructuradescribe esta estrategia principal.

El Composite Entity Implementa el Objeto Genrico


En esta estrategia, el propio Composite Entity es el objeto genrico y tiene atributos y mtodos de objeto genrico. Los objetos dependientes son atributos del Composite Entity. Como el Composite Entity es el objeto genrico, el bean de entidad expresa y maneja todas las relaciones entre el objeto genrico y los objetos dependientes. La siguiente figura muestra el diagrama de clases de esta estrategia:

En esta otra figura podemos ver el diagrama de secuencia para esta estrategia:

Lazy Loading
Un Composite Entity puede estar compuesto de muchos niveles de objetos dependientes en su rbol de objetos. Cargar todos los objetos dependientes cuando el contendor EJB llama al ejbLoad() del bean puede utilizar mucho tiempo y recursos. Una forma de optimizar esto es utilizar esta estrategia para cargar los objetos dependientes. Cuando se llama al mtodo ejbLoad(), primero slo carga aquellos objetos dependientes que son ms cruciales para los clientes deComposite Entity. Luego, cuando el cliente accede a un objeto dependiente que no se haya cargado de la base de datos, el Composite Entity puede realizar una carga bajo demanda. As, si no se utilizan algunos objetos dependientes, stos no sern cargados en la inicializacin. Sin embargo, cuando el cliente necesita dichos objetos dependientes, los carga en cualquier momento. Una vez que se han cargado los objetos dependientes, las siguientes llamadas al mtodo ejbLoad() deben incluir esos objetos dependientes para recargar o sincronizar los cambios con el almacenamiento persistente.

Store Optimization (Dirty Marker)


Un problema comn con la persistencia controlada por el bean ocurre cuando almacenamos todo el conjunto de objetos durante una operacin ejbStore(). Como el contendor EJB no tiene forma de conocer que datos han cambiado en el bean de entidad y en sus objetos dependientes, pone el baln en el lado del desarrollador para que determine qu y como almacenar. Algunos contenedores EJB proporcionan una caracterstica para indentificar qu objetos del Composite Entity se necesita almacenar debido a una actualizacin anterior. Esto se podra hacer si los desarrolladores implementaran un mtodo especial en los objetos dependientes, como isDirty(), al que llame el contenedor para comprobar si el objeto se ha actualizado desde la ltima operacin ejbStore(). Una solucin genrica podra ser utilizar un interface, DirtyMarker, como se ve en el diagrama de la siguiente figura. La idea es hacer que los objetos dependientes implementen el interface DirtyMarker para dejarle al llamador (normalmente el mtodo ejbStore()) saber si el estado del objeto dependiente ha cambiado. De esta forma, el llamador puede elegir si obtener los datos para su almacenamiento posterior.

La siguiente figura contiene un diagrama de secuencia que muestra un ejemplo de interaccin para esta estrategia.

El cliente realiza un actualizacin del Composite Entity, que resulta en un cambio en DependentObject3. Se accede a DependentObject3 mediante su padre DependentObject2. El Composite Entity es el padre de DependentObject2. Cuando se realiza la actualizacin, se llama al metodo setDirty() en DependentObject3. Posteriormente, cuando el contenedor llama al mtodo ejbStore() sobre este ejemplar de Composite Entity, el mtodo ejbStore() puede chequear qu objetos dependientes se han cambiado y grabar selectivamente en la base de datos aquellos que han cambiado. La marca dirty se resetea despus de que la grabacin haya tenido xito. El interface DirtyMarker tambin puede incluir mtodos que reconozcan otros estados de persistencia del objeto dependiente. Por ejemplo, si se incluye un nuevo objeto dependiente dentro del Composite Entity, el mtodo ejbStore() debera poder reconocer qu operacin utilizar en este caso, el objeto dependiente no se ha modificado, sino que es nuevo. Extendiendo el interface DirtyMarker para incluir un mtodo llamado isNewz(), el mtodo ejbStore() puede invocar una operacin de insercin en lugar de una operacin de actualizacin. De forma similar, incluyendo un mtodo llamado isDeleted(), el mtodo ejbStore() puede invocar una operacin de borrado cuando sea necesario. En casos donde se llama a ejbStore() sin actualizaciones intermedias, del Composite Entity, ninguno de los objetos dependientes ha sido actualizado. Esta estrategia evita la gran sobrecarga de tener que persistir todos los objetos dependientes en la base de datos siempre que el contenedor llame al mtodo ejbStore().

Nota: La especificacin EJB 2.0 corrige las estrategias Lazy Loading y Store Optimization. Es posible utilizar estas estrategias en implementaciones anteriores a la EJB 2.0.

Composite Transfer Object


Con un Composite Entity, un cliente puede obtener toda la informacin requerida con slo una llamada a un mtodo. Como el Composite Entity o implementa o contiene el objeto genrico y la herencia (o rbol) de objetos dependientes, puede crear el Transfer Object requerido y devolverlo al cliente aplicando el

patrnTransfer Object. En la siguiente imagen podemos ver el diagrama de secuencia para esta estrategia:

El Transfer Object puede ser un objeto simple o compuesto que tenga subobjetos, dependiendo de los datos solicitados por el cliente. El Transfer Object es serializable y se pasa por valor al cliente. ElTransfer Object funciona slo como un mero transmisor de objetos; no tiene responsabilidades con respecto a la seguridad, las transaciones, y la lgica de negocio. El Transfer Object empaqueta toda la informacin en un objeto, obteniendo la informacin con una llamada remota en vez de con mltiples llamadas. Una vez que el cliente recibe el Transfer Object, todas las llamadas posteriores del cliente al Transfer Object son llamadas locales. La discusin apunta a cmo la entidad puede empaquetar todos sus datos en un Transfer Object compuesto y devolver este al cliente. Sin embargo,esta estrategia tambin permite al bean de entidad devolver slo los datos que el cliente ha solicitado. Si el cliente slo necesita los datos de un subconjunto de objetos dependientes, entonces el Transfer Object compuesto devuelto puede contener los datos derivados slo de aquellas partes requeridas y no de todos los objetos dependientes. Esto podra ser una aplicacin de la estrategia Multiple Transfer Objects del patrn Transfer Object.

Consecuencias

Elimina las Relaciones Inter-Entidades Utilizando el patrn Composite Entity, los objetos dependientes se unen en un slo bean de entidad, eliminando todas las relaciones entre beans de entidad. Este patrn proporciona un lugar central para manejar las relaciones y la herencia de los objetos. Mejora la Manejabilidad Reduciendo los Beans de Entidad Como se ha explicado, la implementacin de objetos persistentes como beans de entidad especficos resulta en un mayor nmero de clases que necesitamos desarrollar y mantener. Utilizar Composite Entity reduce el nmero de clases EJB y el cdigo, y hace ms fcil el mantenimiento. Mejora la manejabilidad de la aplicacin teniendo un menor nmero de componentes genricos en lugar de tener muchos ms componentes especficos. Mejora el Rendimiento de Red La unin de objetos dependientes mejora el rendimiento general. Esta unin elima toda la comunicacin especfica entre objetos dependientes a travs de la red. Si todos los objetos dependientes se disearan como beans de entidad especficos, provocara una sobrecarga en la red debido a la comunicacin entre los beans de entidad. Reduce la Dependencia del Esquema de la Base de Datos Cuando se utiliza el patrn Composite Entity, resulta en implementaciones de beans de entidad genricos. El esquema de la base de datos est oculto para los clientes, ya que el mapeo entre el bean de entidad y el esquema es interno del bean de entidad. Los cambios en el esquema de la base de daos podran requerir cambios en los beans de CompositeEntity. Sin embargo, los clientes no se ven afectados porque los beans Composite Entity no exponen el esquema al mundo exterior.

Incrementa la Generalidad del Objeto Con un Composite Entity, el cliente normalmente busca un slo bean de entidad en lugar de una gran cantidad de beans de entidad especficos. El cliente le pide los datos al Composite Entity. ste puede crear un Transfer Object compuesto que contenga todos los datos del bean de entidad y devolverlo al cliente en una nica llamada a mtodo. Facilita la Creacin de Transfer Object Compuestos Utilizando esta estrategia, se reduce la comunicacin entre el cliente y el bean de entidad, ya que el bean Composite Entity puede devolver un Transfer Object compuesto proporcionando un mecanismo para enviar Transfer Objects serializados. Aunque un Transfer Object devuelva todos los datos en una llamada remota, la cantidad de datos devueltos con esta nica llamada es mucho mayor que la cantidad de datos devuelta por llamadas remotas independientes para obtener propiedades de beans de entidad individuales. Este inconveniente se puede sobrellevar cuando el objetivo es evitar la repeticin de llamadas remotas y bsquedas mltiples. Sobrecarga de Grupos de Objetos Dependientes Multi-Nivel Si el conjunto de objetos dependientes manejado por el Composite Entity tiene muchos niveles, entonces se incrementa la carga y almacenamiento de objetos dependientes. Esto se puede reducir utilizando estrategias de optimizacin para la carga y almacenamiento, peo entonces podra aparecer otra sobrecarga asociada con el chequeo de objetos obsoletos para su almacenamiento y la carga de los objetos requeridos.

Codigo de Ejemplo
Consideremos una aplicacin de Servicio Profesional de automatizacin (PSA) donde se implementa un objeto de negocio: Resource utilizando el patrn Composite Entity. Resource representa el recurso "empleado" que est asignado a los proyectos. Cada objeto Resource puede tener diferentes objetos dependientes, de esta forma:

- Este objeto dependiente representa el periodo de tiempo que el recurso no est disponible por razones como formacin, vacaciones, das libres, etc. Como cada recurso puede tener varios periodos de absentismo, la relacin Resource-a-BlockOutTime es de uno-a-muchos. SkillSet - Este objeto dependiente representa las "Habilidades" (Skills) que posee un recurso. Como cada recurso puede tener mtiples habilidades, la relacin de Resource-a-SkillSet es de uno a muchos.
BlockOutTime

Implementacin del patrn Composite Entity


El patrn para el objeto de negocio Resource se implementa como un Composite Entity (ResourceEntity), como se ve en el siguiente cdigo. La relacin uno-a-muchos con sus objetos dependientes (objetos BlockOutTime y SkillSet) se implementa utilizando collections.

package corepatterns.apps.psa.ejb; import import import import import import import corepatterns.apps.psa.core.*; corepatterns.apps.psa.dao.*; java.sql.*; javax.sql.*; java.util.*; javax.ejb.*; javax.naming.*;

public class ResourceEntity implements EntityBean { public String employeeId; public String lastName; public String firstName; public String departmentId; public String practiceGroup; public String title; public String grade; public String email; public String phone; public String cell; public String pager; public String managerId; // Collection of BlockOutTime Dependent objects public Collection blockoutTimes; // Collection of SkillSet Dependent objects public Collection skillSets;

... private EntityContext context; // Entity Bean methods implementation public String ejbCreate(ResourceTO resource) throws CreateException { try { this.employeeId = resource.employeeId; setResourceData(resource); getResourceDAO().create(resource); } catch(Exception ex) { throw new EJBException("Reason:" + ...); } return this.employeeId; } public String ejbFindByPrimaryKey(String primaryKey) throws FinderException { boolean result; try { ResourceDAO resourceDAO = getResourceDAO(); result = resourceDAO.selectByPrimaryKey(primaryKey); } catch(Exception ex) { throw new EJBException("Reason:" + ...); } if(result) { return primaryKey; } else { throw new ObjectNotFoundException(...); } } public void ejbRemove() { try { // Remove dependent objects if(this.skillSets != null) { SkillSetDAO skillSetDAO = getSkillSetDAO(); skillSetDAO.setResourceID(employeeId); skillSetDAO.deleteAll(); skillSets = null; } if(this.blockoutTime != null) { BlockOutTimeDAO blockouttimeDAO = getBlockOutTimeDAO(); blockouttimeDAO.setResourceID(employeeId); blockouttimeDAO.deleteAll(); blockOutTimes = null; } // Remove the resource from the persistent store ResourceDAO resourceDAO = new ResourceDAO(employeeId); resourceDAO.delete(); } catch(ResourceException ex) { throw new EJBException("Reason:"+...); } catch(BlockOutTimeException ex) { throw new EJBException("Reason:"+...); } catch(Exception exception) { ... } } public void setEntityContext(EntityContext context) { this.context = context; } public void unsetEntityContext() { context = null; } public void ejbActivate() { employeeId = (String)context.getPrimaryKey(); } public void ejbPassivate() { employeeId = null; } public void ejbLoad() { try { // load the resource info from ResourceDAO resourceDAO = getResourceDAO(); setResourceData((ResourceTO) resourceDAO.load(employeeId));

// Load other dependent objects, if necessary ... } catch(Exception ex) { throw new EJBException("Reason:" + ...); } } public void ejbStore() { try { // Store resource information getResourceDAO().update(getResourceData()); // Store dependent objects as needed ... } catch(SkillSetException ex) { throw new EJBException("Reason:" + ...); } catch(BlockOutTimeException ex) { throw new EJBException("Reason:" + ...); } ... } public void ejbPostCreate(ResourceTO resource) { } // Method to Get Resource Transfer Object public ResourceTO getResourceTO() { // create a new Resource Transfer Object ResourceTO resourceTO = new ResourceTO(employeeId); // copy all values resourceTO.lastName = lastName; resourceTO.firstName = firstName; resourceTO.departmentId = departmentId; ... return resourceTO; } public void setResourceData(ResourceTO resourceTO) { // copy values from Transfer Object into entity bean employeeId = resourceTO.employeeId; lastName = resourceTO.lastName; ... } // Method to get dependent Transfer Objects public Collection getSkillSetsData() { // If skillSets is not loaded, load it first. // See Lazy Load strategy implementation. return skillSets; } ... // other get and set methods as needed ... // Entity bean business methods public void addBlockOutTimes(Collection moreBOTs) throws BlockOutTimeException { // Note: moreBOTs is a collection of // BlockOutTimeTO objects try { Iterator moreIter = moreBOTs.iterator(); while(moreIter.hasNext()) { BlockOutTimeTO botTO = (BlockOutTimeTO)moreIter.next(); if (! (blockOutTimeExists(botTO))) { // add BlockOutTimeTO to collection botTO.setNew(); blockOutTime.add(botTO); } else { // BlockOutTimeTO already exists, cannot add throw new BlockOutTimeException(...); } } } catch(Exception exception) { throw new EJBException(...); } } public void addSkillSet(Collection moreSkills) throws SkillSetException { // similar to addBlockOutTime() implementation ... } ...

public void updateBlockOutTime(Collection updBOTs) throws BlockOutTimeException { try { Iterator botIter = blockOutTimes.iterator(); Iterator updIter = updBOTs.iterator(); while (updIter.hasNext()) { BlockOutTimeTO botTO = (BlockOutTimeTO) updIter.next(); while (botIter.hasNext()) { BlockOutTimeTO existingBOT = (BlockOutTimeTO) botIter.next(); // compare key values to locate BlockOutTime if (existingBOT.equals(botTO)) { // Found BlockOutTime in collection // replace old BlockOutTimeTO with new one botTO.setDirty(); //modified old dependent botTO.resetNew(); //not a new dependent existingBOT = botTO; } } } } catch (Exception exc) { throw new EJBException(...); } } public void updateSkillSet(Collection updSkills) throws CommitmentException { // similar to updateBlockOutTime... ... } ... }

Implementar la Estrategia Lazy Loading


Cuando el contenedor carga por primera vez el Composite Entity utilizando el mtodo ejbLoad(), asumimos que slo se han cargado los datos del recurso. Esto incluye los atributos listados en el bean ResourceEntity, excluyendo las colecciones de objetos dependientes. Los objetos dependientes entonces slo se pueden cargar si el cliente invoca un mtodo de negocio que necesita que se carguen esos objetos dependientes. Consiguientemente, el mtodo ejbLoad() necesita seguir la pista de los objetos dependientes cargados de esta manera e incluirlos para su recarga. Abajo podemos ver los mtodos ms importantes de la clase ResourceEntity:

... public Collection getSkillSetsData() { throws SkillSetException { checkSkillSetLoad(); return skillSets; } private void checkSkillSetLoad() throws SkillSetException { try { // Lazy Load strategy...Load on demand if (skillSets == null) skillSets = getSkillSetDAO(resourceId).loadAll(); } catch(Exception exception) { // No skills, throw an exception throw new SkillSetException(...); } } ... public void ejbLoad() { try { // load the resource info from ResourceDAO resourceDAO = new ResourceDAO(employeeId); setResourceData((ResourceTO)resourceDAO.load()); // If the lazy loaded objects are already // loaded, they need to be reloaded. // If there are not loaded, do not load them

// here...lazy load will load them later. if (skillSets != null) { reloadSkillSets(); } if (blockOutTimes != null) { reloadBlockOutTimes(); } ... throw new EJBException("Reason:"+...); } } ...

Implementar la Estrategia Store Optimization (Dirty Marker)


Para utilizar la estrategia Store Optimization, necesitamos que los objetos dependientes implementen el interface DirtyMarker, como se ve en el siguiente ejemplo:

public class SkillSetTO implements DirtyMarker, java.io.Serializable { private String skillName; private String expertiseLevel; private String info; ... // dirty flag private boolean dirty = false; // new flag private boolean isnew = true; // deleted flag private boolean deleted = false; public SkillSetTO(...) { // initialization ... // is new TO setNew(); } // get, set and other methods for SkillSet // all set methods and modifier methods // must call setDirty() public setSkillName(String newSkillName) { skillName = newSkillName; setDirty(); } ... // DirtyMarker methods // used for modified Transfer Objects only public void setDirty() { dirty = true; } public void resetDirty() { dirty = false; } public boolean isDirty() { return dirty; } // used for new Transfer Objects only public void setNew() { isnew = true; } public void resetNew() { isnew = false; } public boolean isNew() { return isnew; } // used for deleted objects only public void setDeleted() { deleted = true; } public boolean isDeleted() { return deleted; } public void resetDeleted() { deleted = false;

} }

En el siguiente ejemplo podemos ver el mtodo ejbStore() optimizado para utilizarlo con esta estrategia:

... public void ejbStore() { try { // Load the mandatory data getResourceDAO().update(getResourceData()); // // // if Store optimization for dependent objects check dirty and store Check and store commitments (skillSets != null) { // Get the DAO to use to store SkillSetDAO skillSetDAO = getSkillSetDAO(); Iterator skillIter = skillSet.iterator(); while(skillIter.hasNext()) { SkillSetTO skill = (SkillSetTO) skillIter.next(); if (skill.isNew()) { // This is a new dependent, insert it skillSetDAO.insert(skill); skill.resetNew(); skill.resetDirty(); } else if (skill.isDeleted()) { // delete Skill skillSetDAO.delete(skill); // Remove from dependents list skillSets. remove(skill); } else if (skill.isDirty()) { // Store Skill, it has been modified skillSetDAO.update(skill); // Saved, reset dirty. skill.resetDirty(); skill.resetNew(); } }

} // Similarly, implement store optimization // for other dependent objects such as // BlockOutTime, ... ... } catch(SkillSetException ex) { throw new EJBException("Reason:"+...); } catch(BlockOutTimeException ex) { throw new EJBException("Reason:"+...); } catch(CommitmentException ex) { throw new EJBException("Reason:"+...); } } ...

Implementar la Estrategia Composite Transfer Object


Ahora consideremos el requerimiento donde el cliente necesita obtener todos los datos del y no slo una parte. Esto se puede hacer utilizando la estrategia Composite Transfer Object como se muestra en el siguiente ejemplo:

ResourceEntity,

public class ResourceCompositeTO { private ResourceTO resourceData; private Collection skillSets; private Collection blockOutTimes; // Transfer Object constructors ... // get and set methods ... }

El ResourceEntity proporciona un mtodo getResourceDetailsData() para devolver el objeto Transfer Object compuesto ResourceCompositeTO:

... public ResourceCompositeTO getResourceDetailsData() { ResourceCompositeTO compositeTO = new ResourceCompositeTO (getResourceData(), getSkillsData(), getBlockOutTimesData()); return compositeTO; } ...

Patrones Relacionados

Transfer Object El patrn Composite Entity usa el patrn Transfer Object para crear el objeto que devuelve al cliente. El patrn Transfer Object se utiliza para serializar el rbol de objetos genricos y de objetos dependientes, o parte de ese rbol, segn se requiera. Session Facade Si los objetos dependientes tienden a ser beans de entidad en vez de objetos Java normales, debemos intentar de utilizar el patrn Session Facade para manejar las relaciones entre beans de entidad. Transfer Object Assembler Este patrn es similar al patrn Transfer Object. Sin embargo, en este caso, las fuentes de datos para todos los Transfer Objects del compuesto son parte del propio Composite Entity, mientras que para el Transfer Object Assembler, los datos puede ser diferentes beans de entidad, beans de sesin, DAOs, objetos Java, etc.

Bean de Entidad como un Objeto Dependiende: Problemas y Recomendaciones


Tpicamente, diseamos los objetos dependientes como objetos Java que tienen una relacin directa con el objeto genrico padre. Sin embargo, podra hacer situaciones en las que un objeto dependiente podra aparecer como un propio bean de entidad: 1. 2. Si el objeto dependiente es dependiente de dos objetos padre diferentes (como es el caso de la asociacin de clases. Si el objeto dependiente ya existe como un bean de entidad en la misma aplicacin o se importa desde una aplicacin diferente.

En estos casos, el ciclo de vida del objeto dependiente podra parecer que no est directamente relacionado y manejado por un slo objeto genrico padre. Entonces, qu podemos hacer cuando un objeto dependiente es un bean de entidad? y, cundo veamos un objeto dependiente que no es totalmente dependiente de su objeto padre? o, cundo no podamos identificar su nico objeto padre? Consideremos cada caso con un poco ms de detalle:

Caso 1: El Objeto Dependiente depende de Dos Objetos Padre. Exploremos esto con el siguiente ejemplo. Un Commitment representa una asociacin entre un Resource y un Project. La siguiente figura muestra un ejemplo de diagrama de clases con las relaciones entre Project, Resource y Commitment.

Commitment es un objeto dependiente. Projects y Resources son objetos genricos. Cada Project tiene una relacin uno-a-muchos con objetos Commitment. Entonces. Commitment es un objeto dependiente de Project o de Resource? La respuesta trata de analizar las interacciones para los casos de utilizacin que implican estos tres componentes. Si hacemos que el objeto Commitment sea dependiente del objeto Project, entonces cuando un Resource acceda a su lista de objetos Commitment, tiene que hacerlo a travs del objeto Project. Por otro lado, si Commitment es un objeto dependiente de un Resource, cuando Project acceda a su lista de objeto Commitment, tiene que hacerlo mediante el Resource. Estas dos elecciones introducen en el diseo las relaciones beande-entidad-a-bean-de-entidad.

Pero, qu pasa si Commitment es un bean de entidad en vez de un objeto dependiente? Entonces la relacin entre Project y su lista de objetos Commitment, y entre un Resource y su lista de objetos Commitment, ser una relacin entidad-a-bean-de-entidad. Esto empeora el problema en que ahora tenemos dos relaciones bean-de-entidad-a-bean-de-entidad. Este tipo de relaciones no es recomendable debido a la sobrecarga asociada con su manejo y sustentacin.

Caso 2: El Objeto Dependiente ya existe como un Bean de Entidad En este caso, podra parecer que una forma de modelar esta relacin es almacenar la clave primaria del objeto dependitne en el objeto genrico. Cuando el objeto genrico necesite acceder al objeto dependiente, el resultado ser una llamada bean-de-entidad-a-bean-de-entidad. Abajo podemos ver el diagrama de clases para este ejemplo:

Entity

En la siguiente figura podemos ver el diagrama de secuencia para este escenario. El Composite utiliza las referencias al objeto dependiente para buscar el bean de entidad requerido. En este caso el objeto dependiente es un proxy al bean de entidad dependiente:

Aunque esto podra corrige el requerimiento de utilizar un bean de entidad dependiente partiendo de un bean de entidad padre, no es una solucin elegante. En su lugar, para evitar la complejidad del diseo y manejo de las relaciones entre-entidades, consideremos la utilizacin de un bean de sesin para manejar las relaciones entre los beans de entidad. Segn nuestra experiencia, hemos encontrado que el patrn Session Facade nos ayud a solucionar este problema y nos proporcion una mejor forma de manejar las relaciones bean-de-entidad-a-beande-entidad. Por eso, recomendamos evitar las relaciones bean-de-entidad-a-bean-de-entidad como la mejor prctica, y para optimizar las relaciones dentro de un bean de sesin recomendamos la utilizacin del patrn Session Facade.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Data Access Object o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo Implementar el Patrn Data Access Object Implementar la Estrategia Factory for Data Access Objects o Patrones Relacionados

Data Access Object


Contexto
El acceso a los datos vara dependiendo de la fuente de los datos. El acceso al almacenamiento persistente, como una base de datos, vara en gran medida dependiendo del tipo de almacenamiento (bases de datos relacionales, bases de datos orientadas a objetos, ficheros planos, etc.) y de la implementacin del vendedor.

Problema
Muchas aplicaciones de la plataforma J2EE en el mundo real necesitan utilizar datos persistentes en algn momento. Para muchas de ellas, este almacenamiento persistente se implementa utilizando diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder a esos mecanismos de almacenamiento diferentes. Otras aplicaciones podran necesitar acceder a datos que residen en sistemas diferentes. Por ejemplo, los datos podran residir en sitemas mainframe, repositorios LDAP, etc. Otro ejemplo es donde los datos los proporcionan servicios a travs de sistemas externos como los sistemas de integracin negocio-a-negocio (B2B), servicios de tarjetas de crdito, etc. Normalmente, las aplicaciones utilizan componentes distribuidos y compartidos como los beans de entidad para representar los datos persistentes. Se considera que una aplicacin emplea consistencia manejada por el bean (BMP) cuando sus beans de entidad acceden explcitamente al almacenamiento persistente -- el bean de entidad incluye cdigo para hacer esto. Una aplicacin con requerimientos sencillos podra por lo tanto utilizar beans de entidad en lugar de beans de sesin o servlets para acceder al almacenamiento persistente y recuperar o modificar los datos. O, la aplicacin podra usar beans de entidad con persistencia manejada por el contenedor, y as dejar que el contenedor maneje los detalles de las transaciones y de la persistencia. Las aplicaciones pueden utilizar el API JDBC para acceder a los datos en un sistema de control de bases de datos relacionales (RDBMS). Este API permite una forma estndar de acceder y manipular datos en un almacenamineto persistente, como una base de datos ralacional. El API JDBC permite a las aplicaciones J2EE utilizar sentencias SQL, que son el mtodo estndar para acceder a tablas RDBMS. Sin embargo, incluso dentro de un entorno RDBMS, la sntaxis y formatos actuales de las sentencias SQL podran variar dependiendo de la propia base de datos en particular. Incluso hay una mayor variacin con diferentes tipos de almacenamientos persistentes. Los mecanimos de acceso, los APIs soportados, y sus caractersticas varian entre los diferentes tipos de almacenamientos persistentes, como bases de datos relacionales, bases de datos orientadas a objetos, ficheros planos, etc. Las aplicaciones que necesitan acceder a datos de un sistema legal o un sistema dispar (como un mainframe o un servicio B2B) se ven obligados a utilizar APIs que podran ser

propietarios. Dichas fuentes de datos dispares ofrecen retos a la aplicacin y potencialmente pueden crear una dependencia directa entre el cdigo de la aplicacin y el cdigo de acceso a los datos. Cuando los componentes de negocio -- beans de entidad, beans de sesin e incluso componentes de presentacin como servlets y beans de apoyo para pginas JSP -- necesitan acceder a una fuente de datos, pueden utilizar el API apropiado para conseguir la conectividad y manipular la fuente de datos. Pero introducir el cdigo de conectividad y de acceso a datos dentro de estos componentes genera un fuerte acoplamiento entre los componentes y la implementacin de la fuente de datos. Dichas dependencias de cdigo en los componentes hace difcil y tedioso migrar la aplicacin de un tipo de fuente de datos a otro. Cuando cambia la fuente de datos, tambin deben cambiar los componentes para manejar el nuevo tipo de fuente de datos.

Causas

Los componentes como los beans de entidad controlados por el bean, los beans de sesin, los servlets, y otros objetos como beans de apoyo para pginas JSP necesitan recuperar y almacenar informacin desde almacenamientos persistentes y otras fuentes de datos como sistemas legales, B2B, LDAP, etc. Los APIs para almacenamiento persistente varan dependiendo del vendedor del producto. Otras fuentes de datos podran tener APIS que no son estndar y/o propietarios. Estos APIs y sus capacidades tambin varan dependiendo del tipo de almacenamiento -- bases de datos relacionales, bases de datos orientadas a objetos, documentos XML, ficheros planos, etc. Hay una falta de APIs uniformes para corregir los requrimientos de acceso a sistemas tan dispares. Los componentes normalmente utilizan APIs propietarios para acceder a sistemas externos y/o legales para recuperar y almacenar datos. La portabilidad de los componentes se ve afectada directamente cuando se incluyen APIs y mecanismos de acceso especficos. Los componentes necesitan ser transparentes al almacenamiento persistente real o la implementacin de la fuente de datos para proporcionar una migracin sencilla a diferentes productos, diferentes tipos de almacenamiento y diferentes tipos de fuentes de datos.

Solucin
Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la fuente de datos. El DAO maneja la conexin con la fuente de datos para obtener y almacenar datos. El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos. Esta fuente de datos puede ser un almacenamiento persistente como una RDMBS, un servicio externo como un intercambio B2B, un repositorio LDAP, o un servicio de negocios al que se accede mediante CORBA Internet Inter-ORB Protocol (IIOP) o sockets de bajo nivel. Los componentes de negocio que tratan con el DAO utilizan un interface simple expuesto por el DAO para sus clientes. El DAO oculta completamente los detalles de implementacin de la fuente de datos a sus clientes. Como el interface expuesto por el DAO no cambia cuando cambia la implementacin de la fuente de datos subyacente, este patrn permite al DAO adaptarse a diferentes esquemas de almacenamiento sin que esto afecte a sus clientes o componentes de engocio. Esencialmente, el DAO acta como un adaptador entre el componente y la fuente de datos.

Estructura
La siguiente figura muestra el diagrama de clases que representa las relaciones para el patrn DAO:

Participantes y Responsabilidades
La siguiente figura muestra el diagrama de secuecnia de la interaccin entre los distintos participantes en este patrn:

BusinessObject

BusinessObject

representa los datos del cliente. Es el objeto que requiere el acceso a la fuente de datos para obtener y almacenar datos. Podramos implementar un BusinessObject como un bean de sesin, un bean de entidad o cualquier otro objeto Java, adems de como un Servlet o como un bean de apoyo.

DataAccessObject
DataAccessObject es el objeto principal de este patrn. DataAccessObject abstrae la implementacin del acceso a datos subyacente al BusinessObject para permitirle un acceso transparente a la fuente de datos. El BusinessObject tambin delega las operaciones de carga y almacenamiento en el DataAccessObject.

DataSource
Representa la implementacin de la fuente de datos. Una fuente de datos podra ser una base de datos como un RDBMS, un OODBMS, un repositorio XML, un fichero plano, etc. Tambin lo pueden ser otros sitemas (mainframes/legales), servicios (servicio B2B u oficina de tarjetas de crdito), o algn tipo de repositorio (LDAP).

TransferObject
Representa un Transfer Object utilizado para el transporte de datos. DataAccessObject podra utilizar un Transfer Object para devolver los datos al cliente. El DataAccessObject tambin podra recibir datos desde el cliente en un Transfer Object para actualizar los datos en la fuente de datos.

Estrategias

Automatic DAO Code Generation


Como cada BusinessObject corresponde a un DAO especfico, es posible establecer relaciones entre el BusinessObject, el DAO, y las implementaciones subyacentes (como en las tablas de una RDBMS). Una vez que se han establecido las relaciones, es posible escribir una utilidad de generacin-de-cdigoespecfica-de-aplicacin que genere el cdigo para todos los DAOs que necesita la aplicacin. Los metadatos para generar el DAO pueden venir de un fichero descriptor definido por el desarrollador. Como alternativa, el generador de cdigo puede inspeccionar la base de datos y proporcionar los DAOs necesarios para acceder a ella. Si los requerimientos de los DAOs son lo suficientemente complejos, debemos considerar la utilizacin de herramientas de terceras partes que proporcionan un mapeo de objeto-a-relacional para bases de datos RDBMS. Estas herramientas normalmente incluyen utilidades GUI para mapear los objetos de negocio a objetos de almacenamiento persistente y adems definir los DAOs intermedios. Estas herramientas generan el cdigo automticamente una vez que se termina el mapeo, y podran proporcionar otras caractersticas valiosas como el cach de resultados y de consultas, integracin con servidores de aplicaciones, integracin con otros productos de terceras partes, etc.

Factory for Data Access Objects


El patrn DO se puede flexibilizar adoptando los patrones Abstract Factory [GoF] y Factory Method [GoF]. Cuando el almacenamiento subyacente no est sujeto a cambios de una implemantacin a otra, esta estrategia se puede implementar utilizando el patrn Factory Method para producir el nmero de DAOs que necesita la aplicacin. En la siguiente figura podemos ver el diagrama de clases para este caso:

Cuando el almacenamiento subyacente si est sujeto a cambios de una implementacin a otra, esta estrategia se podra implementar usando el patrn Abstract Factory. Este patrn a su vez puede construir y utilizar la implementacin Factory Method. En este caso, esta estrategia proporciona un objeto factora abstracta de DAOs (Abstract Factory) que puede construir varios tipos de factoras concretas de DAOs, cada factora soporta un tipo diferente de implementacin del almacenamiento persistente. Una vez que obtenemos la factora concreta de DAOs para una implementacin especfica, la utilizamos para producir los DAOs soportados e implementados en esa implementacin. En la siguiente figura podemos ver el diagrama de clases para esta estrategia. En l vemos una factora base de DAOs, que es una clase abstracta que extienden e implementan las diferentes factoras concretas de DAOs para soportar el acceso especfico a la implementacin del almacenamiento. El cliente puede obtener una implementacin de la factora concreta del DAO como una RdbDAOFactory y utilizarla para obtener los DAOs concretos que funcionan en la implementacin del almacenamiento. Por ejemplo, el cliente puede obtener una RdbDAOFactory y utilizarlas para obtener DAOs especfcios como RdbCustomerDAO, RdbAccountDAO, etc. Los DAOs pueden extender e implementar una clase base genrica (mostradas como DAO1 y DAO2) que describa especficamente los requerimientos del DAO para el objeto de negocio que soporta. Cada DAO concreto es responsable de conectar con la fuente de datos y de obtener y manipular los datos para el objeto de negocio que soporta.

En la siguiente figura podemos ver el diagrama de secuencia para esta estrategia:

Consecuencias

Permite la Transpariencia Los objetos de negocio puede utilizar la fuente de datos sin conocer los detalles especficos de su implementacin. El acceso es transparente porque los detalles de la implementacin se ocultan dentro del DAO. Permite una Migracin ms Fcil Una capa de DAOs hace ms fcil que una aplicacin pueda migrar a una implementacin de base de datos diferente. Los objetos de negocio no conocen la implementacin de datos subyacente, la migracin implica cambios slo en la capa DAO. Adms, si se emplea la estrategia de factoras, es posible proporcionar una implementacin de factoras concretas por cada implementacin del almacenamiento subyacente. En este caso, la migracin a un almacenamiento diferente significa proporcionar a la aplicacin una nueva implementacin de la factora. Reduce la Complejidad del Cdigo de los Objetos de Negocio Como los DAOs manejan todas las complejidades del acceso a los datos, se simplifica el cdigo de los objetos de negocio y de otros clientes que utilizan los DAOs. Todo el cdigo relacionado con la implementacin (como las sentencias SQL) estn dentro del DAO y no en el objeto de negocio. Esto mejora la lectura del cdigo y la productividad del desarrollo.

Centraliza Todos los Accesos a Datos en un Capa Indenpendinte Como todas las operaciones de acceso a los datos se ha delegado en los DAOs, esto se puede ver como una capa que aisla el resto de la aplicacin de la implementacin de acceso a los datos. Esta centralizacin hace que la aplicacin sea ms sencilla de mantener y de manejar. No es til para Persistencia Manejada por el Contenedor Como el contenedor EJB maneja los beans de entidad con persistencia manejada por el contenedor (CMP), sirve automticamente todo el acceso al almacenamiento persistente. Las aplicacin que utilizan este tipo de beans no necesitan la capa DAO, ya que el servidor de aplicaciones proporciona de forma transparente esta funcionalidad. Sin embargo, los DAOS an son tiles cuando se necesita una combinacin de CMP (para beans de entidad) y BMP (para beans de sein, servlets). Aade una Capa Extra Los DAOs crean un capa de objetos adicional entre el cliente y la fuente de datos que necesitamos disear e implementar para obtener los beneficios de este patrn. Pero para obtener estos beneficios debemos pagarlos con un esfuerzo adicional. Necesita Disear un rbol de Clases Cuando se utiliza una estrategia de factoras, necesitamos disear e implementar el rbol de factoras concretas y el rbol de productos concretos producidos por las factoras. Necesitamos justificar este esfuerzo adicional para ver si merece la pena dicha flexibilidad. Esto incrementa la complejidad del diseo. Sin embargo, podemos elegir la implementacin de la estrategia de factoras empezando primero con el patrn Factory Method, y luego avanzar hasta el patrn Abstract Factory si es necesario.

Cdigo de Ejemplo
Implementar el Patrn Data Access Object
Abajo podemos ver el cdigo de un DAO de ejemplo para un objeto persistente que representa informacin de un cliente. CloudscapeCustomerDAO crea un Transfer Object Customer cuando se llama al mtodo findCustomer():

// // // // //

CloudscapeCustomerDAO implementation of the CustomerDAO interface. This class can contain all Cloudscape specific code and SQL statements. The client is thus shielded from knowing these implementation details.

import java.sql.*; public class CloudscapeCustomerDAO implements CustomerDAO { public CloudscapeCustomerDAO() { // initialization } // The following methods can use // CloudscapeDAOFactory.createConnection() // to get a connection as required public int insertCustomer(...) { // Implement insert customer here. // Return newly created customer number // or a -1 on error } public boolean deleteCustomer(...) { // Implement delete customer here // Return true on success, false on failure } public Customer findCustomer(...) { // Implement find a customer here using supplied // argument values as search criteria // Return a Transfer Object if found, // return null on error or if not found } public boolean updateCustomer(...) { // implement update record here using data // from the customerData Transfer Object // Return true on success, false on failure or // error }

public RowSet selectCustomersRS(...) { // implement search customers here using the // supplied criteria. // Return a RowSet. } public Collection selectCustomersTO(...) { // implement search customers here using the // supplied criteria. // Alternatively, implement to return a Collection // of Transfer Objects. } ... }

Abajo podemos ver el cdigo para utilizar este DAO:

... // create the required DAO Factory DAOFactory cloudscapeFactory = DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE); // Create a DAO CustomerDAO custDAO = cloudscapeFactory.getCustomerDAO(); // create a new customer int newCustNo = custDAO.insertCustomer(...); // Find a customer object. Get the Transfer Object. Customer cust = custDAO.findCustomer(...); // modify the values in the Transfer Object. cust.setAddress(...); cust.setEmail(...); // update the customer object using the DAO custDAO.updateCustomer(cust); // delete a customer object custDAO.deleteCustomer(...); // select all customers in the same city Customer criteria=new Customer(); criteria.setCity("New York"); Collection customersList = custDAO.selectCustomersTO(criteria); // returns customersList - collection of Customer // Transfer Objects. iterate through this collection to // get values. ...

La siguiente figura representa el diagrama de clases para este ejemplo:

Implementar la Estrategia Factory for Data Access Objects

Utilizar el Patrn Factory Method


Consideremos un ejemplo donde hemos implementado esta estrategia en la que una factora de DAOs produce muchos DAOs para una nica implementacin de una base de datos (por ejemplo, Oracle). La factora produce DAOs como CustomerDAO, AccountDAO, OrderDAO, etc. Abajo podemos ver el diagrama de clases para este ejemplo:

Y aqu tenemos el cdigo de ejemplo para la factora de DAOs (CloudscapeDAOFactory):

// Cloudscape concrete DAO Factory implementation import java.sql.*; public class CloudscapeDAOFactory extends DAOFactory { public static final String DRIVER= "COM.cloudscape.core.RmiJdbcDriver"; public static final String DBURL= "jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB"; // method to create Cloudscape connections public static Connection createConnection() { // Use DRIVER and DBURL to create a connection // Recommend connection pool implementation/usage } public CustomerDAO getCustomerDAO() { // CloudscapeCustomerDAO implements CustomerDAO return new CloudscapeCustomerDAO(); } public AccountDAO getAccountDAO() { // CloudscapeAccountDAO implements AccountDAO return new CloudscapeAccountDAO(); } public OrderDAO getOrderDAO() { // CloudscapeOrderDAO implements OrderDAO return new CloudscapeOrderDAO(); } ... }

Utilizar el Patrn Abstract Factory


Consideremos un ejemplo donde implementemos esta estrategia para tres bases de datos diferenets. En este caso, se puede emplear el patrn Abstract Factory. En la siguiente figura podemos ver el diagrama de clases para este ejmplo.

El siguiente fragmento de cdigo muestra parte de la clase DAOFactory. Esta factora produce DAOs como CustomerDAO, AccountDAO, OrderDAO, etc. Esta estrategia utiliza el patrn Factory Method en las factoras producidas por el Abstract Factory.

// Abstract class DAO Factory public abstract class DAOFactory { // List of DAO types supported by the factory public static final int CLOUDSCAPE = 1; public static final int ORACLE = 2; public static final int SYBASE = 3; ... // There will be a method for each DAO that can be // created. The concrete factories will have to // implement these methods. public abstract CustomerDAO getCustomerDAO(); public abstract AccountDAO getAccountDAO(); public abstract OrderDAO getOrderDAO(); ... public static DAOFactory getDAOFactory( int whichFactory) { switch (whichFactory) { case CLOUDSCAPE: return new CloudscapeDAOFactory(); case ORACLE : return new OracleDAOFactory(); case SYBASE : return new SybaseDAOFactory(); ... default : return null; } } }

El ejemplo de cdigo para CloudscapeDAOFactory se ve en el siguiente listado. La implementacin para OracleDAOFactory y SybaseDAOFactory son similares excepto para especifidades de cada implementacin, como el driver JDBC, la URL de la base de datos, y diferencias en la sntaxis SQL, si existe-

// Cloudscape concrete DAO Factory implementation import java.sql.*; public class CloudscapeDAOFactory extends DAOFactory { public static final String DRIVER= "COM.cloudscape.core.RmiJdbcDriver"; public static final String DBURL= "jdbc:cloudscape:rmi://localhost:1099/CoreJ2EEDB"; // method to create Cloudscape connections public static Connection createConnection() { // Use DRIVER and DBURL to create a connection // Recommend connection pool implementation/usage } public CustomerDAO getCustomerDAO() { // CloudscapeCustomerDAO implements CustomerDAO return new CloudscapeCustomerDAO(); } public AccountDAO getAccountDAO() { // CloudscapeAccountDAO implements AccountDAO return new CloudscapeAccountDAO(); } public OrderDAO getOrderDAO() { // CloudscapeOrderDAO implements OrderDAO return new CloudscapeOrderDAO(); } ... }

El interface CustomerDAO mostrado en el siguiente listado, define los mtodos DAO para los objetos Customer persistentes que son implementados por todas las implementaciones de DAOs concretos como CloudscapeCustomerDAO, OracleCustomerDAO, y SybaseCustomerDAO. Similares, aunque no se listan aqu, son los interfaces AccountDAO y OrderDAO que definen los metodos DAO para los objetos de negocio Account y Order respectivamente.

// Interface that all CustomerDAOs must support public interface CustomerDAO { public int insertCustomer(...); public boolean deleteCustomer(...); public Customer findCustomer(...); public boolean updateCustomer(...); public RowSet selectCustomersRS(...); public Collection selectCustomersTO(...); ... }

CloudscapeCustomerDAO implementa CustomerDAO como se ven en el siguiente listado. La implementacin de los otros DAOs, como CloudscapeOrderDAO, OracleCustomerDAO, OracleAccountDAO, etc. son similares:

// // // // //

CloudscapeCustomerDAO implementation of the CustomerDAO interface. This class can contain all Cloudscape specific code and SQL statements. The client is thus shielded from knowing these implementation details.

import java.sql.*; public class CloudscapeCustomerDAO implements CustomerDAO { public CloudscapeCustomerDAO() { // initialization } // The following methods can use // CloudscapeDAOFactory.createConnection() // to get a connection as required public int insertCustomer(...) { // Implement insert customer here. // Return newly created customer number // or a -1 on error } public boolean deleteCustomer(...) { // Implement delete customer here // Return true on success, false on failure } public Customer findCustomer(...) { // Implement find a customer here using supplied // argument values as search criteria // Return a Transfer Object if found, // return null on error or if not found } public boolean updateCustomer(...) { // implement update record here using data // from the customerData Transfer Object // Return true on success, false on failure or // error } public RowSet selectCustomersRS(...) { // implement search customers here using the // supplied criteria. // Return a RowSet. } public Collection selectCustomersTO(...) { // implement search customers here using the // supplied criteria. // Alternatively, implement to return a Collection // of Transfer Objects. } ... }

La clase Transfer Object Customer del siguiente listado la utilizan los DAOs para enviar y recibir datos desde los clientes. La utilizacin del patrn Transfer Object se explica con ms detalles en la pgina Transfer Object:

public class Customer implements java.io.Serializable { // member variables int CustomerNumber; String name; String streetAddress; String city; ... // getter and setter methods... ... }

El siguiente ejemplo muestra la utilizacin del factora de DAOs y del DAO, Si la implementacin cambiara de Cloudscape a otro producto, el nico cambio que tendramos que hacer es que el mtodo getDAOFactory() llame a la factora adecuada.

... // create the required DAO Factory DAOFactory cloudscapeFactory = DAOFactory.getDAOFactory(DAOFactory.DAOCLOUDSCAPE); // Create a DAO CustomerDAO custDAO = cloudscapeFactory.getCustomerDAO(); // create a new customer int newCustNo = custDAO.insertCustomer(...); // Find a customer object. Get the Transfer Object. Customer cust = custDAO.findCustomer(...); // modify the values in the Transfer Object. cust.setAddress(...); cust.setEmail(...); // update the customer object using the DAO custDAO.updateCustomer(cust); // delete a customer object custDAO.deleteCustomer(...); // select all customers in the same city Customer criteria=new Customer(); criteria.setCity("New York"); Collection customersList = custDAO.selectCustomersTO(criteria); // returns customersList - collection of Customer // Transfer Objects. iterate through this collection to // get values. ...

Patrones Relacionados

Transfer Object Un DAO utiliza Transfer Objects para transportar los datos desde y hacia sus clientes. Factory Method [GoF] y Abstract Factory [GoF] La Factora para la estrategia Data Access Objects usa el patrn Factory Method para implementar las factoras concretas y sus productos (DAOs). Para aadir flexibilidad, se podra emplear el patrn Abstract Factory como se explica en la seccin de estrategias. Broker [POSA1] El patrn DAO est relacionado con el patrn Broker, que describe aproximaciones para desacoplar clientes y servidores en sistemas distribuidos. El patrn DAO aplica este patrn especficamente para desacoplar la capa de recursos de los clientes en otra capa, como las capas de negocio o presentacin.

Catlogo de Patrones de Diseo J2EE. Y II: Capas de Negocio y de Integracin


Autor: Traductor: Juan Antonio Palos (Ozito) Sun

Service Activator o Contexto o Problema o Causas o Solucin Estructura Participantes y Responsabilidades Estrategias o Consecuencias o Cdigo de Ejemplo o Patrones Relacionados

Service Activator
Contexto
Los beans enterprise y otros servicios de negocio necesitan una forma de activarse asncronamente.

Problema
Cuando un cliente necesita acceder a un bean enteprise, primero busca el objeto home del bean. Luego el cliente le pide a ese objeto home que le proporcione una referencia remota al bean enterprise requerido. Entonces el cliente invoca a los mtodos de negocio sobre la referencia remota para acceder a los servicios del bean enterpise. Estas llamadas a mtodos, as como las bsquedas y las llamdas a mtodos remotos, son sncronos. El cliente tiene que esperar hasta que esos metodos retornan. Otro factor a considerar es el ciclo de vida de un bean enterprise. La especificacin EJB permite que el contenedor pasivice un bean enterprise a un almacenamiento intermedio. Como resultado, el contenedor EJB no tiene un mecanismo mediante el cual poder proporcionar un servicio estilo-proceso para mantener un bean enterprise constantemente activado y en estado listo. Como el cliente debe interactar con el bean enterprise utilizando su interface remoto, incluso si el bean est en estado activado en el contenedor, el cliente un necesita obtener su interface remoto mediante un proceso de bsqueda y todava acta con el bean de forma sncrona. Si una aplicacin necesita procesamiento sncrono para sus componentes de negocio del lado del servidor, entonces los beans enterprise son una opcin apropiada. Algunas aplicaciones cliente podran requerir este tipo de procesamiento porque los clientes no necesitan esperar o no tienen tiempo para esperar a que se complete el procesamiento. En caso donde la aplicacin necesita una forma de procesamiento asncrono, los beans enterpise no ofrecen esta capacidad en implementaciones anteriores a la especificacin EJB 2.0. La especificacin EJB 2.0 proporciona integracin introduciendo el bean dirigido-a-mensaje, que es un tipo especial de bean de sesin sin estado que ofrece capacidades de invocacin asncrona. Sin embargo, la nueva especificacin no ofrece invocacin asncrona para otros tipos de beans enterprise, como los beans con estado o de entidad. En general, un servicio de negocio como un bean de sesin o de entidad slo proporciona procesamiento sncrono y esto representa un reto para implemenetar procesamiento asncrono.

Causas

Los beans enterprise se exponen a sus clientes mediante sus interfaces remotos, que slo permiten acceso sncrono.

El contenedor maneja los beans enterprise, permitiendo interacciones slo mediante referencias remotas. El contenedor EJB no permite acceso directo a la implementacin del bean y sus mtodos. As, implementar el oyente de mensajes JMS no es factible en un bean enterprise, ya que esto viola la especificacin EJB al permitir el acceso directo a la implementacin del bean. Una aplicacin necesita proporcionar un marco de mensajera publicar/suscribir o punto-a-punto donde los clientes puedan publicar peticiones a beans enterprise para procesamiento asncrono. Los clientes necesitan capacidades de procesamiento asncrono en los beans entreprise y otros componentes de negocio que slo pueden ofrecer acceso sncrono, para que el cliente pueda enviar una peticin para su procesamiento sin esperar los resultados. Los clientes quieren utilizar interfaces de la capa media orientados a mesnajes (MOM) ofrecidos por el API Java Messaging Service (JMS). Estos interfaces no estn integrados en los productos servidores EJB que estn basados en especificaciones anteriores a la la EJB 2.0. Una aplicacin necesita proporcionar un servicio estilo "criado(daemon)" para que un bean enterprise pueda estar en modo callado hasta que un evento (o un mensaje) dispare su actividad. Los beans enterprise estn sujetos al control de su ciclo de vida por parte del contenedor, lo que incluye la pasivizacin debido a periodos de inactividad y control de recursos. El cliente tendr que invocar a un bean enteprise para activarlo de nuevo. La especificacin EJB 2.0 introdujo un bean dirigio-a-mensaje como un bean de sesin sin estado, pero no es posible invocar otros tipos diferentes de beans enteprise de forma asncrona.

Solucin
Utilizar un Service Activator para recibir peticiones y mensajes asncronos de los clientes. Cuando se recibe un mensaje, el Service Activator localiza e invoca a los mtodos de de los componentes de negocio necesarios para cumplir la peticin de forma asncrona. El ServiceActivator es un oyente JMS y un servicio de delegacin que requiere la implementacin de un oyente de mensajes JMS. Se puede implementar como un servicio independiente. Los clientes actan como generadores de mensajes, generando eventos basndose en su actividad. Cualquier cliente que necesite invocar asncronamente un servicio de negocio, como un bean enteprise, podra crear y enviar un mensaje al Service Activator. ste recibe el mensaje y lo analiza para interpretar la peticin del cliente. Una vez que se ha analizado y desempaquetado la peticin del cliente, el Service Activator identifica y localiza los componentes de servicio de negocio necesarios e invoca a sus mtodos de negocio para completar el procesamiento de la peticin del cliente de forma asncrona. Service Activator opcionalmente podra enviar un reconocimiento al cliente despus de que haya completado el procesamiento de la peticin. Tambin podra notificar al cliente o a otros servicios si ocurre un fallo durante el procesamiento de la peticin. El Service Activator podra utilizar los servicios de un Service Locator.

Estructura
La siguiente figura representa las relaciones entre clases para el patrn Service Activator:

Participantes y Responsabilidades
La siguiente figura muestra las interacciones entre los distintos participantes en el patrn Service Activator:

Client
El cliente solicita una facilidad de procesamiento asncrono de los objetos de negocio que participan en un flujo de trabajo. El cliente puede ser cualquier tipo de aplicacin que tenga la capacidad de crear y enviar mensajes JMS. El cliente tambin puede ser un componente EJB que necesite invocar los mtodos de negocio de otro componente EJB de forma asncrona. El cliente puede utilizar los servicios ofrecidos por el patrn Service Locator para buscar o crear componentes EJB, servicios JMS, u objetos JMS, segn necesite.

Request
Request

es el objeto message creado po el cliente y enviado al ServiceActivator mediante MOM. De acuerdo a la especificacin JMS, Request es un objeto que implementa el interface javax.jms.Message. El API JMS proporciona varios tipos de mesnajes, como TextMessage, ObjectMessage, etc.

ServiceActivator
ServiceActivator es la clase principal del patrn. Implementa el interface javax.jms.MessageListener, definido por la especificacin JMS. ServiceActivator implementa un mtodo onMessage() que se invoca cuando llega un nuevo mensaje. ServiceActivator analiza (desempaqueta) el mensaje (la peticin) para determinar qu debe hacer. El ServiceActivator podra utilizar los servicios de un patrn Service Locator para buscar o crear los componentes de servicio de negocio que necesita.

BusinessObject
es el objeto destino al que el cliente necesita acceder de forma asncrona. El objeto de negocio es un rol que pueden cumplir los beans de sesin o de entidad. Tambin es posible que el BusinessObject sea un servicio externo en vez de un bean de entidad.
BusinessObject

Estrategias

Entity Bean
Tanto los beans de sesin como los de entidad puede cumplir el rol de un BusinessObject. Cuando las aplicaciones J2EE implementan un patrn Session Faade para proporcionar acceso genrico a los beans de entidad y para encapsular el flujo de trabajo, el bean de sesin del Session Faade cumple el rol del BusinessObject. En aplicaciones sencillas con flujo de trabajo mnimo, un bean de entidad podra cumplir el rol del BusinessObject. Sin embargo, para flujos de trabajo complejos que implican varios beans de entidad y otros objetos de negocio, el ServiceActivator normalmente interacta con un Session Facade que encapsula dicho flujo de trabajo.

Session Bean
Cuando un bean de sesin cumple el rol del BusinessObject, los requerimientos del negocio determinan si el bean debera ser con o sin estado. Como el cliente del BusinessObject es un ServiceActivator que activa el BusinessObject cuando recibe un nuevo mensaje, el flujo de trabajo para procesar el mensaje puede definir si el bean debera tener estado o no. En muchos casos, un mensaje simplemente activa un slo mtodo en el BusinessObject que delega el procesamiento dentro del mensaje. En estos casos se puede utilizar un bean de sesin sin estado. Si el ServiceActivator necesita invocar varios mtodos en el BusinessObject o necesita trabajar con ms de un BusinessObject para cumplir los requerimientos de procesamiento, podra ser til considerar la utilizacin de un bean de sesin con estado para retener el estdo entre varias llamadas.

ServiceActivator Server
La estrategia ms correcta para implementar el oyente o ServiceActivator es una aplicacin JMS independiente que escuche y procese mensajes JMS. Una alternativa es implementar el ServiceActivator como servicio del servidor de aplicaciones. Esto hace ms fcil de manejar el ServiceActivator, porque utiliza las caractersticas del servidor de aplicaciones para monitorizar el estado del ServiceActivator y para arrancar, reiniciar y parar el ServiceActivator cuando sea necesario, manual o automticamente.

Enterprise Bean as Client

El Cliente puede ser cualquier cliente, incluyendo otro bean enterprise que requiera procesamiento asncrono. Cuando se integran aplicaciones legales en la plataforma J2EE, es lgico elegir aplicaciones Java como clientes para actar como generadores de mensajes basndose en la actividad del sistema legal. El ServiceActivator puede recibir mensajes y realizar cualquier invocacin a bean de enterprise necesaria para procesar la peticin desde sistemas legales.

Consecuencias

Integra JMS en implementaciones Pre-EJB 2.0 Anteriormente a la especificacin EJB 2.0 no haba integracin entre beans enterprise y componentes JMS. Este partrn proporciona una forma de integrar JMS en una aplicacin EJB y permite procesamiento asncrono. La especificacin EJB 2.0 define un nuevo tipo de bean de sesin, llamado bean dirigido-a-mensaje, para integrar JMS y componentes EJB. Este bean especial implementa el interface javax.jms.MessageListener y recibe mensajes asncronos. En este caso, el servidor de aplicaciones juega el rol del Service Activator. Este patrn hace posible ejecutar aplicaciones en implementaciones EJB 2.0 as como en implementaciones de EJB anteriores. Proporciona Procesamiento Asncrono para cualquier Bean Enterprise En la especificacin EJB 2.0, el bean dirigido-a-mensaje es un bean de sesin sin estado. Utilizando el patrn Service Activator, es posible proporcionar invocacin asncrona a todos los tipos de beans enterprise, incluyeno beans de sesin con o sin estado y beans de entidad. Como se explic anteriormente, ya que el Service Activator se implementa abiertamente, sin las limitaciones del bean dirigido-a-mensaje, el Service Activator puede realizar llamadas asncronas a cualquier tipo de servicio de negocio. As, este patrn presenta una forma de proporcionar procesamiento asncrono para clientes que no necesitan esperar los resultados o no quieren esperar a que se complete el procesamiento. El procesamiento se puede retrasar y realizarse ms tarde, permitiendo que el cliente complete el servicio en menos tiempo. Proceso Independiente Service Activator se puede ejecutar como un proceso independiente. Sin embargo, en una aplicacin crtica, necesitamos monitorizar el Service Activator para asegurarnos de su disponibilidad. Este control y manteminiento adicional puede aadir una pequea sobrecarga a la aplicacin.

Cdigo de Ejemplo
Consideremos una aplicacin de procesamiento de pedidos donde los clientes compran on-line y los otros procesos se realizan en segundo plano. En algunos casos, el cumplimiento del pedido podra externalizarse a un almacen de terceros. En dichos casos, el almacen on-line necesita invocar estos servicios de forma asncrona. Este es un ejemplo que demuestra la utilizacin de la mensajera punto-apunto (PTP) para conseguir el procesamiento asncrono. Sin embargo, la utilizacin de la mensajera publicar/suscribir sera similar, excepto en que se utilizara un Topic en lugar de una Queue. La eleccin del mtodo autilizado, PTP o publicar/suscribir, depedende de los requerimientos de la aplicacin, y se sale fuera del mbito de este patrn. En la siguiente figura podemos ver el diagrama de clases como los mtodos importantes de este ejemplo:

El siguiente fragmento de cdigo demuestra la implementacin de un Service Activator. Esta es la clase que se puede ejemplarizar en un servidor de aplicaciones o ejecutar como un servicio independiente, como se explic en las estrategias anteriores:

public class OrderServiceActivator implements javax.jms.MessageListener{ // Queue session and receiver: see JMS API for // details private QueueSession orderQueueSession; private QueueReceiver orderQueueReceiver; // Note: values should come from property files or // environment instead of hard coding. private String connFactoryName = "PendingOrdersQueueFactory"; private String queueName = "PendingOrders"; // use a service locator to locate administered // JMS components such as a Queue or a Queue // Connection factory private JMSServiceLocator serviceLocator; public OrderServiceActivator(String connFactoryName, String queueName) { super(); this.connFactoryName = connFactoryName; this.queueName = queueName; startListener(); } private void startListener() { try { serviceLocator = new JMSServiceLocator (connFactoryName); qConnFactory = serviceLocator.getQueueConnectionFactory(); qConn = qConnFactory.createQueueConnection(); // See JMS API for method usage and arguments orderQueueSession = qConn.createQueueSession (...); Queue ordersQueue = serviceLocator.getQueue(queueName); orderQueueReceiver = orderQueueSession.createReceiver(ordersQueue); orderQueueReceiver.setMessageListener(this); } catch (JMSException excp) { // handle error } } // The JMS API specifies the onMessage method in the // javax.jms.MessageListener interface. // This method is asynchronously invoked // when a message arrives on the Queue being // listened to by the ServiceActivator. // See JMS Specification and API for more details. public void onMessage(Message msg) { try { // parse Message msg. See JMS API for Message. ... // // // // // Invoke business method on an enterprise bean using the bean's business delegate. OrderProcessorDelegate is the business delegate for OrderProcessor Session bean. See Business Delegate pattern for details. OrderProcessorDelegate orderProcDeleg = new OrderProcessorDelegate();

// Use data values from the parsed message to // invoke business method on bean via delegate orderProcDeleg.fulfillOrder(...); // send any acknowledgement here... } catch (JMSException jmsexcp) { // Handle JMSExceptions, if any } catch (Exception excp) { // Handle any other exceptions } }

public void close() { try { // cleanup before closing orderQueueReceiver.setMessageListener (null); orderQueueSession.close(); } catch(Exception excp) { // Handle exception - Failure to close } } }

En el siguiente cdido est el ejemplo del Session Facade para despachar los pedidos a este servicio asncromo. El cliente Service Activator puede ser un bean de sesin que implementa el patrn Session Faade para proporcionar servicio de procesamiento de pedidos a una aplicacin de almacen on-line. Cuando se llama al mtodo createOrder(), despus de validar y de crear satisfactoriamente un nuevo pedido, se llama la mtodo sendOrder() para despachar el nuevo pedido al sevicio de envo:

// imports... public class OrderDispatcherFacade implements javax.ejb.SessionBean { ... // business method to create new Order public int createOrder(...) throws OrderException { // create new business order entity bean ... // successfully created Order. send Order to // asynchronous backend processing OrderSender orderSender = new OrderSender(); orderSender.sendOrder(order); // close the sender, if done... orderSender.close(); // other processing ... } }

El cdigo JMS se puede separar en una clase diferente para que pueda ser reutilizado por diferentes clientes. Podemos ver esta clase en el siguiente listado:

// imports... public class OrderSender { // Queue session and sender: see JMS API for details private QueueSession orderQueueSession; private QueueSender orderQueueSender; // These values could come from some property files private String connFactoryName = "PendingOrdersQueueFactory"; private String queueName = "PendingOrders"; // use a service locator to locate administered // JMS components such as a Queue or a Queue. // Connection factory private JMSServiceLocator serviceLocator; ... // method to initialize and create queue sender private void createSender() { try { // using ServiceLocator and getting Queue // Connection Factory is similar to the // Service Activator code. serviceLocator = new JMSServiceLocator (connFactoryName); qConnFactory = serviceLocator.getQueueConnectionFactory(); qConn = qConnFactory.createQueueConnection(); // See JMS API for method usage and arguments orderQueueSession = qConn.createQueueSession (...); Queue ordersQueue = serviceLocator.getQueue(queueName); orderQueueSender = orderQueueSession.createSender(ordersQueue);

catch(Exception excp) { // Handle exception - Failure to create sender } } // method to dispatch order to fulfillment service // for asynchronous processing public void sendOrder(Order newOrder) { // create a new Message to send Order object ObjectMessage objMessage = queueSession.createObjectMessage(order); // set object message properties and delivery // mode as required. // See JMS API for ObjectMessage // Set the Order into the object message objMessage.setObject(order); // send the message to the Queue orderQueueSender.send(objMessage); ... } catch (Exception e) { // Handle exceptions } ... } ... public void close() { try { // cleanup before closing orderQueueReceiver.setMessageListener (null); orderQueueSession.close(); } catch(Exception excp) { // Handle exception - Failure to close } } }

Patrones Relacionados

Session Facade El patrn Session Facade encapsula la complejidad del sistema y prorporciona acceso genrico a los objetos de negocio. Este patrn Service Activator podria acceder a un Session Faade como objeto de negocio principal para invocar mtodos de negocio de otros servicios de forma asncrona por cuenta del cliente. Business Delegate El patrn Service Activator podra utilizar un Business Delegate para acceder al Session Faade u otra implementacin de bean enterprise. Esto resulta en un cdigo ms sencillo para el Service Activator y en que el Business Delegate se pueda reutilizar entre diferentes capas. Service Locator El cliente puede utilizar el patrn Service Locator para buscar y crear objetos de servicios relacionados con JMS. El Service Activator puede utilizar el patrn Service Locator para buscar y crear componentes beans enterprise. Half-Sync/Half-Async [POSA2] El patrn Service Activator est relacionado con el patrn Half-Sync/Half-Async, que describe el desacoplamiento arquitectural de procesamientos sncronos y asncronos sugiriendo diferentes capas para sncronos y asncronso con una cola intermedia entre ellos.

S-ar putea să vă placă și