Patrones de Diseño (Capa Presentacion)

download Patrones de Diseño (Capa Presentacion)

If you can't read please download the document

Transcript of Patrones de Diseño (Capa Presentacion)

Patrones de Diseo J2EEIntroduccin a los PatronesQu 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 PatronesUn 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 PatrnSe 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 EstrategiasCuando 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 J2EE Capa de Presentacin Decorating Filter Un objeto que est entre el cliente y los componentes Web. Este procesa las / Intercepting peticiones y las respuestas.

Filter Un objeto que acepta todos los requerimientos de un cliente y los direcciona a manejadores apropiados. El patrn Front Controller podra dividir la Front Controller/ funcionalidad en 2 diferentes objetos: el Front Controller y el Dispatcher. En Front ese caso, El Front Controller acepta todos los requerimientos de un cliente y Component realiza la autenticacin, y el Dispatcher direcciona los requerimientos a manejadores apropiados. View Helper Un objeto helper que encapsula la lgica de acceso a datos en beneficio de los componentes de la presentacin. Por ejemplo, los JavaBeans pueden ser usados como patrn View Helper para las pginas JSP.

Un objeto vista que est compuesto de otros objetos vista. Por ejemplo, una Composite view pgina JSP que incluye otras pginas JSP y HTML usando la directiva include o el action include es un patrn Composite View. Service To Worker Es como el patrn de diseo MVC con el Controlador actuando como Front Controller pero con una cosa importante: aqu el Dispatcher (el cual es parte del Front Controller) usa View Helpers a gran escala y ayuda en el manejo de la vista.

Es como el patrn de diseo MVC con el controlador actuando como Front Controller pero con un asunto importante: aqu el Dispatcher (el cual es parte Dispatcher View del Front Controller) no usa View Helpers y realiza muy poco trabajo en el manejo de la vista. El manejo de la vista es manejado por los mismos componentes de la Vista.

Capa de Negocio Business Delegate Un objeto que reside en la capa de presentacin y en beneficio de los otros componentes de la capa de presentacin llama a mtodos remotos de los objetos de la capa de negocios.

Value Object/ Data Transfer Un objeto serializable para la transferencia de datos sobre la red. Object/ Replicate Object Session Faade/ Session Entity Faade/ Distributed Faade El uso de un bean de sesion como una fachada (facade) para encapsular la complejidad de las interacciones entre los objetos de negocio y participantes en un flujo de trabajo. El Session Faade maneja los objetos de negocio y proporciona un servicio de acceso uniforme a los clientes.

Aggregate Entity Un bean entidad que es construido o es agregado a otros beans de entidad. Value Object Assembler Un objeto que reside en la capa de negocios y crea Value Objets cuando es requerido.

Value List Es un objeto que maneja la ejecucin de consultas SQL, cach y Handler/ Pageprocesamiento del resultado. Usualmente implementado como beans de by-Page Iterator/ sesin. Paged List Consiste en utilizar un objeto Service Locutor para abstraer toda la utilizacin JNDI y para ocultar las complejidades de la creacin del contexto inicial, de bsqueda de objetos home EJB y recreacin de objetos EJB. Varios clientes pueden reutilizar el objeto Service Locutor para reducir la complejidad del cdigo, proporcionando un punto de control.

Service Locator

Capa de Integracin Data Access Object Service Activator Consiste en utilizar un objeto de acceso a datos 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.

Se utiliza para recibir peticiones y mensajes asncronos de los clientes. Cuando se recibe un mensaje, el Service Activator localiza e invoca a los Service Activator mtodos de los componentes de negocio necesarios para cumplir la peticin de forma asncrona.

Plantilla de PatrnLos 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. Estrategias: Describe diferentes formas en las que se podra implementar el patrn.

o

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.

Intercepting FilterContexto

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 o o

Logging y autentificacin. Depuracin y transformacin de la salida para un cliente especfico Descomprensin y conversin del esquema de codificacin de la entrada.

SolucinCrear 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.

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

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

Ejemplo:

MainServlet.java package intercepting_filter; import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*;

public class MainServlet extends HttpServlet { private static final String CONTENT_TYPE = "text/html"; //Initialize global variables public void init() throws ServletException { } //Process the HTTP Get request public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(CONTENT_TYPE); PrintWriter out = response.getWriter(); out.println(""); out.println("MainServlet"); out.println(""); out.println("The servlet has received a GET. This is the reply."); out.println(""); out.println(""); out.close(); } //Clean up resources public void destroy() { } }

ScanFilter.java package intercepting_filter; import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*;

public class ScanFilter extends HttpServlet implements Filter { private FilterConfig filterConfig;

public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } //Process the request/response pair public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) { try { String contentType = request.getContentType(); System.out.println("El tipo de contenido es :"); System.out.println(contentType); //if (contentType.startsWith("multipart/form-data")) { // // Por ejemplo, un procesamiento del fichero o escaneo para //comprobar si tiene virus antes de subirlo a sevidor} //} filterChain.doFilter(request, response); } catch (ServletException sx) { filterConfig.getServletContext().log(sx.getMessage()); } catch (IOException iox) { filterConfig.getServletContext().log(iox.getMessage()); } } //Clean up resources public void destroy() { } } ServletFilter.java package intercepting_filter; import import import import javax.servlet.*; javax.servlet.http.*; java.io.*; java.util.*;

public class ServletFilter extends HttpServlet implements Filter { private FilterConfig filterConfig; //Handle the passed-in FilterConfig public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } //Process the request/response pair public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) { try { System.out.println("Paso por el filtro SevletFilter"); filterChain.doFilter(request, response); } catch (ServletException sx) { filterConfig.getServletContext().log(sx.getMessage()); } catch (IOException iox) { filterConfig.getServletContext().log(iox.getMessage()); } } //Clean up resources public void destroy() { } } mainservlet.html

MainServlet press Submit to invoke servlet MainServlet web.xml mainservlet intercepting_filter.MainServlet mainservlet /mainservlet servletfilter intercepting_filter.ServletFilter servletfilter /* scanfilter intercepting_filter.ScanFilter scanfilter /*

Front ControllerContextoEl 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.

ProblemaEl 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.

SolucinUsar 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.

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

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

EjemploFrontController.java package fcexample.controller; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import fcexample.model.*; public class FrontController extends HttpServlet { public public public public static static static static final final final final String String String String USERNAME_PARAM = "username"; PASSWORD_PARAM = "password"; USERBEAN_ATTR = "userbean"; CONTROLLER_PREFIX = "/pages";

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { process(request, response); } protected void process(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String nextPage = request.getPathInfo(); System.out.println(nextPage);

HttpSession session = request.getSession(true); UserBean userBean = (UserBean) session.getAttribute(USERBEAN_ATTR); if (userBean == null || !userBean.isLoggedIn()) { String username = request.getParameter(USERNAME_PARAM); String password = request.getParameter(PASSWORD_PARAM); if (userBean == null) { userBean = UserBeanFactory.newInstance(); session.setAttribute(USERBEAN_ATTR, userBean); } userBean.setUsername(username); userBean.setPassword(password); boolean result = userBean.doLogin(); if (!result) { nextPage = "/login.jsp"; } } System.out.println("La next page es:"+ nextPage); RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextPage); dispatcher.forward(request, response); } } ListController.java package fcexample.controller; import javax.servlet.*; import javax.servlet.http.*; import java.io.IOException; import fcexample.model.*; public class ListController extends HttpServlet { public public public public static static static static final final final final String String String String FIRST_PARAM = "nombre"; LAST_PARAM = "apellidos"; EMAIL_PARAM = "email"; MAILINGBEAN_ATTR = "mailingbean";

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String nombre = request.getParameter(FIRST_PARAM); String apellidos = request.getParameter(LAST_PARAM); String email = request.getParameter(EMAIL_PARAM); MailingBean mb = MailingBeanFactory.newInstance(); mb.setNombre(nombre); mb.setApellidos(apellidos); mb.setEmail(email); request.setAttribute(MAILINGBEAN_ATTR, mb); boolean result = mb.doSubscribe();

String nextPage = "/success.jsp"; if (!result) nextPage = "/failure.jsp"; RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(nextPage); dispatcher.forward(request, response); } } MailingBean.java package fcexample.model; public interface MailingBean { public String getNombre(); public void setNombre(String first); public String getApellidos(); public void setApellidos(String last); public String getEmail(); public void setEmail(String email); public boolean doSubscribe(); public String getErrorString(); } MailingBeanFactory.java package fcexample.model; public class MailingBeanFactory { public static MailingBean newInstance() { return new MailingBeanImpl(); } } MailingBeanImpl.java package fcexample.model; public class MailingBeanImpl implements MailingBean { private private private private String String String String nombre; apellidos; email; errorString;

public MailingBeanImpl() { }

public boolean doSubscribe() { if (getEmail().indexOf('@') == -1) { setErrorString("Email Incorrecto"); return false; } else { setErrorString(null);

return true; } } public String getErrorString() { return errorString; } public String getNombre() { return nombre; } public void setNombre(String nombre) { this.nombre = nombre; } public String getApellidos() { return apellidos; } public void setApellidos(String apellidos) { this.apellidos = apellidos; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public void setErrorString(String errorString) { this.errorString = errorString; } } UserBean.java package fcexample.model; public interface UserBean { public String getUsername(); public void setUsername(String username); public String getPassword(); public void setPassword(String password); public boolean doLogin(); public boolean isLoggedIn(); } UserBeanFactory.java package fcexample.model; public class UserBeanFactory { public static UserBean newInstance() {

return new UserBeanImpl(); } } UserBeanImpl.java package fcexample.model; public class UserBeanImpl implements UserBean { private String username; private String password; private boolean loggedIn; public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.password; } public void setPassword(String password) { this.password = password; } public boolean doLogin() { if (password == null || password.length() < 3) { setLoggedIn(false); } else { setLoggedIn(true); } return isLoggedIn(); } private void setLoggedIn(boolean loggedIn) { this.loggedIn = loggedIn; } public boolean isLoggedIn() { return loggedIn; } } Failure.jsp Resultados de la suscripcion

Querido ,

Se siente, la direccin no ha podido ser aadida a la lista.

El problema fue: .

Login.jsp Login

Username:
Password:
Succes.jsp Resultados de la suscripcion

Querido ,

Felicidades, la direccin ha sido aadida a la lista Suscripcin.html Subscribe! Nombre:
Apellidos:
Email:
Web.xml FrontController fcexample.controller.FrontController ListController fcexample.controller.ListController

FrontController /pages/* ListController /servlets/ListController 30 pages/subscribe.html

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

ProblemaLos 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.

CausasLos 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. 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. Una vista comnmente se utiliza para responder a una peticin de negocios particular.

o

o

SolucinUna 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.

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

Participantes y ResponsabilidadesLa 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:

Ejemplo

FormatingModel.java package beans; import java.io.Serializable; public class FormattingModel implements Serializable { private String dateValue; private String currencyValue; public FormattingModel () {} /* accesores */ public void setDateValue (String _date) {

this.dateValue = _date; } public String getDateValue () { return this.dateValue; } public void setCurrencyValue (String _currency) { this.currencyValue = _currency; } public String getCurrencyValue () { return this.currencyValue; } } MenuModel.java package beans; import java.io.Serializable; import java.util.Hashtable; import java.util.Enumeration; public class MenuModel implements Serializable { Hashtable links = new Hashtable(); String list = ""; public MenuModel() { /* Inicializamos el modelo con valores de ejemplo */ links.put("Fold-away Keyboard", "/Controller?action=display&item=101"); links.put("Standard Leather Case", "/Controller? action=display&item=102"); links.put("Deluxe 3-Pocket Case", "/Controller? action=display&item=103"); links.put("Travel Cable", "/Controller?action=display&item=104"); links.put("Stylus Pack", "/Controller?action=display&item=105"); links.put("8MB Backup Module", "/Controller?action=display&item=106"); } /* accesores */ public void setList (String _list) { this.list = _list; } public String getList () { StringBuffer csvList = new StringBuffer(); /* Transformamos la hashtable en una lista separada por comas */ Enumeration enu = links.keys(); while (enu.hasMoreElements()) { String linkName = (String) enu.nextElement(); String linkURL = (String) links.get(linkName); csvList.append(linkName).append(",").append(linkURL).append("\n"); } return csvList.toString(); } } FormatTag.java package tags; import import import import import import javax.servlet.jsp.JspWriter; javax.servlet.jsp.JspTagException; javax.servlet.jsp.tagext.BodyTagSupport; javax.servlet.jsp.tagext.BodyContent; java.io.IOException; java.util.Locale;

import import import import import

java.util.Calendar; java.text.DateFormat; java.text.SimpleDateFormat; java.text.NumberFormat; java.text.DecimalFormat;

public class FormatTag extends BodyTagSupport { /* Objeto local para la internationalizacion del contenido */ private Locale locale; /* Atributos de la etiqueta */ protected String format; /* Constantes estticas */ private final static String DATE_LONG = "date"; private final static String NUMERIC_DECIMAL = "decimal"; private final static String NUMERIC_ROUNDED = "rounded"; private final static String NUMERIC_CURRENCY = "currency"; public FormatTag() { locale = Locale.getDefault(); } public void setLocale(Locale locale) { this.locale = locale; } /* Procesamos el cuerpo de la etiqueta */ public int doAfterBody() throws JspTagException { try { BodyContent body = getBodyContent(); JspWriter out = body.getEnclosingWriter(); /* Obtenemos el valor de entrada*/ String textValue = body.getString().trim(); /* Valor de salida formateado */ out.println(formatValue(textValue)); } catch (IOException e) { throw new JspTagException(e.toString()); } return SKIP_BODY; } /* Procesamod el fin de la etiqueta */ public int doEndTag() throws JspTagException { return EVAL_PAGE; } private String formatValue (String _input) { String formattedValue = ""; try { if(format.equals(DATE_LONG)) { Calendar cal = Calendar.getInstance(); cal.setTime(DateFormat.getDateInstance( DateFormat.SHORT).parse(_input)); SimpleDateFormat df = new SimpleDateFormat("EEE, MMM d, yyyy"); formattedValue = df.format(cal.getTime()); } else if(format.equals(NUMERIC_DECIMAL)) { DecimalFormat dcf = (DecimalFormat) NumberFormat.getInstance(locale); dcf.setMinimumFractionDigits(2); dcf.setMaximumFractionDigits(2); formattedValue = dcf.format(dcf.parse(_input)); } else if(format.equals(NUMERIC_ROUNDED)) { DecimalFormat dcf = (DecimalFormat) NumberFormat.getInstance(locale); dcf.setMinimumFractionDigits(0); dcf.setMaximumFractionDigits(0); formattedValue = dcf.format(dcf.parse(_input)); } else if(format.equals(NUMERIC_CURRENCY)) { float num = Float.parseFloat(_input); DecimalFormat dcf = (DecimalFormat) NumberFormat.getCurrencyInstance(); formattedValue = dcf.format(num);

} } catch (Exception e) { System.out.println(e.toString()); } return formattedValue; } /* accesores */ public String getFormat () { return this.format; } public void setFormat (String _format) { this.format = _format; } } MenuTag.java package tags; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.tagext.BodyTagSupport; import javax.servlet.jsp.tagext.BodyContent; import java.io.BufferedReader; import java.io.IOException; import java.util.StringTokenizer; public class MenuTag extends BodyTagSupport { /* Atributos de la etiqueta */ protected String links; public int doAfterBody() throws JspTagException { try { BodyContent body = getBodyContent(); JspWriter out = body.getEnclosingWriter(); /* Parseamos los registros y los convertimos a una lista de links */ BufferedReader contentReader = new BufferedReader(body.getReader()); String record = ""; while ((record = contentReader.readLine()) != null) { StringTokenizer st = new StringTokenizer(record, ","); while (st.hasMoreTokens()) { String linkName = st.nextToken(); if(!linkName.trim().equals("")){ String linkURL = st.nextToken(); out.println(""); out.println(linkName + ""); out.println("

"); } } } } catch (IOException e) { throw new JspTagException(e.toString()); } return SKIP_BODY; } public int doEndTag() throws JspTagException { return EVAL_PAGE; } /* accesores */ public String getLinks () { return this.links; } public void setLinks (String _links)

{ this.links = _links; } } formatHelper.jsp Ejemplo de Formateo del texto Varios formatos de moneda y fecha

Formato Valor original Valor formateado Fecha Decimal (NN.NN) ${myBean.currencyValue} ${myBean.currencyValue} Entero (N,NNN) ${myBean.currencyValue} ${myBean.currencyValue} Moneda (N,NNN.NN) ${myBean.currencyValue} ${myBean.currencyValue}

menuHelper.jsp Accesorios de un producto Accesorios para el producto: Deluxe PDA

${myBean.list} Helpers.tld 1.0 helpers /helpers FormatTag tags.FormatTag JSP format yes true MenuTag tags.MenuTag jsp