Catálogo de Patrones de Diseño J2EE. I.- Capa de Presentación

El sistema controla el flujo de ejecuci�n y accede a los datos de negocio, desde los que crea el contenido de la presentaci�n.

Nota:
El patr�n Service to Worker, igual que el patr�n Dispatcher View, describe una combinaci�n com�n de otros patrones del cat�logo. Estos dos macro-patrones describen las combinaci�n de un controlador y un dispatcher con vistas y helpers. Aunque describen esta estructura com�n, cada uno enfatiza un uso diferentes de los patrones.

.�Problema

El problema es una combinaci�n de los problemas resueltos por los patrones Front Controller y View Helper de la capa de presentaci�n. No hay un componente centralizado para manejar el control de acceso, la recuperaci�n de contenido, o el manejo de la vista, y hay c�digo de control duplicado esparcido por varias vistas. Adem�s, la l�gica de negocio y la de formateo de la presentaci�n est�n mezcladas en esas vistas, haciendo que el sistema sea menos flexible, menos reutilizables y generalmente menos resistente a los cambios.

Mezclar l�gica de negocio con el procesamiento de la vista tambi�n reduce la modularidad y proporciona una pobre separaci�n de roles entre los equipos de producci�n Web y de desarrollo de software.

.�Causas

  • Los chequeos de autentificaci�n y autorizaci�n se completan en cada petici�n.
  • El c�digo scriptlet dentro de las vistas se deber�a minimizar.
  • La l�gica de negocio se deber�a encapsular en componentes distintos a la vista.
  • El control de flujo es relativamente complejo y se basa en valores del contenido din�mico.
  • La l�gica de control de la vista es relativamente sofisticada, con varias vistas que potencialmente se mapean a la misma petici�n.

.�Soluci�n

Combinar un controlador y un dispacher con vistas y helper (ver Front Controller y View Helper) para manejar peticiones de clientes y preparar una presentaci�n din�mica como respuesta. Los controladores delegan la recuperaci�n 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 navegaci�n y puede encapsularse dentro de un controlador o de un componente separado.

Service to Worker describe la combinaci�n de los patrones Front Controller y View Helper con un componente dispatcher.

Aunque este patr�n 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 m�s responsabilidades.

Aunque los patrones Service to Worker y Dispatcher View representan una combinaci�n de otros patrones del cat�logo, el primero garantiza con su nombre una comunicaci�n eficiente entre los desarrolladores. Mientras que el segundo sugiere una recuperaci�n de contenido relegada al momento de procesamiento de la vista.

En el patr�n Dispatcher View, el dispatcher normalmente juega un rol moderado en el control de la vista. En el patr�n Service to Worker, el dispatcher juega un rol algo m�s 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 informaci�n encapsulada en la petici�n es suficiente para determinar la vista a la que despachar la petici�n. 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 env�a una petici�n directamente al controlador con un par�metro de consulta que describe una acci�n a realizar:

http://some.server.com/servlet/Controller?action=login

Aqu� la responsabilidad del dispatcher es traducir el nombre l�gico login en el nombre del recurso de una vista apropiada, como login.jsp, y reenviar a esa vista. Para conseguir esta traducci�n, el dispatcher podr�a acceder a recursos como un fichero de configuraci�n XML que especifica las vistas apropiadas a mostrar.

Por otro lado, en el patr�n Service to Worker, el dispatcher podr�a 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 patr�n Service to Worker.

.�Participantes y Responsabilidades

La siguiente figura muestra el diagrama de secuencia que representa al patr�n 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 m�s up front (m�s cercano) al controlador y al dispatcher, mientras que Dispatcher View describe arquitecturas donde se ha movido m�s comportamiento al momento del procesamiento de la vista. As�, los patrones sugieren una continuidad, donde el comportamiento se ha encapsulado m�s cerca de la vista o se ha movido hac�a atr�s en el flujo de proceso.

.�Controller

El controlador normalmente es el punto de contacto inicial para manejar una petici�n. Funciona con un dispatcher para completar el control de la vista y la navegaci�n. El controlador maneja la autentificaci�n, la autorizaci�n, la recuperaci�n de contenido, la validaci�n y otros aspectos del manejo de la petici�n. Delega en los helpers para completar partes de este trabajo.

.�Dispatcher

Un dispatcher es el responsable del control de la vista y la navegaci�n, controlando la elecci�n 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 coordinaci�n con el controlador. El dispatcher puede proporcionar reenv�o est�tico a la vista o podr�a proporcionar un mecanismo de reenv�o din�mico m�s sofisticado.

El dispatcher utiliza el objeto RequestDispatcher (soportado en la especificaci�n Servlet), pero tambi�n encapsula alguna informaci�n de procesamiento adicional. Cuantas m�s responsabilidades encapsule este componente, m�s se acercar� al ideal del patr�n Service to Worker. Y al controlario, cuando el diapatcher juega un papel m�s limitado, m�s se acercar� al ideal del patr�n Dispatcher View.

.�View

Una Vista representa una presentaci�n de informaci�n al cliente. La informaci�n utilizada en esta presentaci�n se recupera de un modelo. Los helpers soportan vistas encapsulando y adaptando un modelo para utilizarlo en una presentaci�n.

.�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 obtenci�n de los datos requeridos por la vista y almacen�ndolos en el modelo intermedio, en cuyo caso el helper es conocido como un value bean. Adem�s, los helpers podr�an 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 formate�ndolos como contenido Web.

Una vista podr�a trabajar con cualquier n�mero de helpers, que normalmente est�n implementados por componentes JavaBeans (JSP 1.0+) o componentes de etiquetas personalidas (JSP 1.1+). Adem�s, un helper podr�a 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 protecci�n para el servicio de negocio (puedes ver el patr�n "Business Delegate" m�s adelante).

.�Estrategias

.�Servlet Front

Ver la estrategia "Servlet Front" en el patr�n Front Controller.

.�JSP Front

Ver la estrategia "JSP Front" en el patr�n Front Controller.

.�JSP page View

Ver la estrategia "JSP page View" en el patr�n View Helper.

.�Servlet View

Ver la estrategia "Servlet View" en el patr�n View Helper.

.�JavaBean Helper

Ver la estrategia "JavaBean Helper" en el patr�n View Helper.

.�Custom Tag Helper

Ver la estrategia "Custom Tag Helper" en el patr�n View Helper.

.�Dispatcher in Controller

Ver la estrategia "Dispatcher in Controller" en el patr�n Front Controller.

Como hemos visto, los patrones Service to Worker y Dispatcher View sugieren una continuidad, donde el comportamiento se ha encapsulado m�s cerca de la vista o se ha movido hac�a atr�s 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 m�nima.

.�Transformer Helper

Ver la estrategia "Transformer Helper" en el patr�n View Helper.

.�Consecuencias

  • Centraliza el Control y Mejora la Modularidad y la Reutilizaci�n
    Este patr�n sugiere proporcionar un lugar central para manejar los servicios del sistema y la l�gica de negocio entre varias peticiones. El contolador maneja el procesamiento de la l�gica de negocio y el manejo de peticiones. Hay que tener en cuenta, que como control centralizado, es posible introducir un s�lo unto de fallo.

    El patr�n tambi�n promueve el particionamiento de la aplicaci�n y aconseja la reutilizaci�n. El c�digo com�n 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 reutilizaci�n significa menos duplicaci�n de c�digo, que normalmente significa en entorno m�s libre de bugs.

  • Mejora el Particionamiento de la Aplicaci�n
    La utilizaci�n de helpers resulta en una separaci�n clara entre la vista y el procesamiento de negocio en una aplicaci�n. Los helpers, en la forma de JavaBeans (JSP 1.0+) o etiquetas personalizadas (JSP 1.1+), proporcionan un lugar donde construir la l�gica de negocio fuera de la p�gina JSP. Si la l�gica de negocio se deja dentro de la p�gina JSP, los grandes proyectos resultan embrollados.
  • Mejora la Separaci�n de Roles
    Al separar la l�gica de formateo de la l�gica de negocio de la aplicaci�n tambi�n se reducen las dependencias de los mismos recursos entre individuos que cumplen diferentes roles. Sin esta separaci�n, por ejemplo, un desarrollador de sofware poseer�a c�digo que est� embebido dentro de marcas HTML, mientras que un miembro del equipo de producci�n Web necesitar�a modificar la distribuci�n de una p�gina y dise�ar componentes que est�n mezclados con l�gica de negocio. Como ning�n individuo que cumple estos roles est� familiarizado con las implementaciones espec�ficas del trabajo del otro individuo, se puede llegar a un punto de confusi�n en que las modificaciones accidentales introduzcan errores el sistema.

.�C�digo de Ejemplo

Los siguientes fragmentos de c�digos muestran una implementaci�n del patr�n Service to Worker, utilizando un servlet controlador, un helper command, un componente dispatcher y una vista. La implementaci�n incluye las estrategias Servlet Front, Command and Controller, JSP View y JavaBean Helper. Tambi�n se utiliza una vista compuesta muy b�sica, 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 factor�a, que devuelve un Command de tipo gen�rico, como veremos m�s 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 gen�rico, que es un ejemplo del patr�n 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 deber�a 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 invocaci�n del servicio de negocio mediante el delegado tiene que ver con un objeto Account Transfer, que el adaptador almacena en un atributo de la petici�n para utilizarlo en la vista. El siguiente ejemplo muestra accountdetails.jsp, la p�gina JSP que despachar� la petici�n. El objeto Transfer Object se importa mediante la etiqueta est�ndar <jsp:useBean> y se accede a sus propiedades utilizando la etiqueta est�ndar <jsp:getProperty>. La vista tambi�n utiliza una estrategia Composite muy simple, haciendo la inclusi�n de la subvista trace.jsp durante la traducci�n, est� subvista es la responsable de guardar informaci�n de la presentaci�n s�lo para prop�sitos 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 patr�n Service to Worker es el resultado de combinar el patr�n View Helper con un dispatcher, en coordinaci�n con el patr�n Front Controller.
  • Dispatcher View
    El patr�n Dispatcher View es otro nombre para la combinaci�n del patr�n Front Controller con un dispatcher, y el patr�n View Helper. Los patrones Service to Worker y Dispatcher View son id�nticos con respecto a los componentes implicados, pero son diferentes en la divisi�n de labores entre esos componentes. El patr�n Dispatcher View siguiere relegar la recuperaci�n de contenido al momento en que se procesa la vista. Adem�s, el dispatcher juega un rol m�s limitado en el control de la vista, ya que la elecci�n de le vista normalmente ya est� incluida en la petici�n.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
SIGUIENTE ARTÍCULO