Catálogo de Patrones de Diseño J2EE. Y II: Capas de Negocio y de Integración

Un sistema multi-capa distribuido requiere invocación remota de métodos para enviar y recibir datos entre las capas. Los clientes están expuestos a la complejidad de tratar con componentes distribuidos.

. Problema

Los componentes de la capa de presentación interactúan directamente con servicios de negocio. Esta interacción directa expone los detalles de la implementación del API del servicio de negocio a la capa de presentación. Como resultado, los componentes de la capa de presentación son vulnerables a los cambios en la implementación de los servicios de negocio: cuando cambia la implementación del servicio de negocio, la implementación del codigo expuesto en la capa de presentación también debe cambiar.

Además, podría haber una reducción de rendimiento en la red porque los componentes de la capa de presentación que utilizan el API de servicio de negocio hacen damasiadas invocaciones sobre la red. Esto sucede cuando los componentes de la capa de presentación 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 tecnología Enterprise JavaBeans (EJB).

. Causas

  • Los clientes de la capa de presentación 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 podrían cambiar según evolucionan los requerimientos del negocio.
  • Es deseable miniminar el acoplamiento entre los clientes de la capa de presentación y los servicios de negocio, y así ocultar los detalles de la implementación del servicio.
  • Los clientes podrían necesitar implementar mecanismos de caché para la información del servicio de negocio.
  • Es deseable reducir el tráfico de red entre el cliente y los servicios de negocio.

. Solución

Utilizamos un Business Delegate para reducir el acoplamiento entre los clientes de la capa de presentación y los servicios de negocio. El Business Delegate oculta los detalles de la implementación del servicio de negocio, como los detalles de búsqueda y acceso de la arquitectura EJB.

El Business Delegate actúa como una abstracción de negocio del lado del cliente; proporciona una abstracción para, y por lo tanto oculta, la implementación de los servicios del negocio. Utilizando Business Delegate se reduce el acoplamiento entre los clientes de la capa de presentación y los servicios de negocio del sistema. Dependiendo de la estrategia de implementación, Business Delegate podría aislar a los clientes de la posible volatilidad en la implementación del API de los servicios de negocio. Potencialmente, esto reduce el número de cambios que se deben hacer en el código de cliente de la capa de presentación cuando cambie el API del servicio de negocio o su implementación subyacente.

Sin embargo, los métodos de interface en el Business Delegate aún podría requerir modificaciones si cambia el API del servicio de negocio. Si bien es cierto, que los cambios se harán con más probabilidad en el servicio de negocio que en el Business Delegate.

Con frecuencia, los desarrolladores son excépticos cuando un objetivo de diseño como la abstracción de la capa de negocio provoca un trabajo adicional como pago por futuras ganancias. Sin embargo, utilizando este patrón o esta estrategia resulta sólo en una pequeña 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 búsqueda y nombrado. El Business Delegate también maneja las excepciones de los servicios de negocio, como excepciones java.rmi.Remote, excepciones Java Messages Service (JMS), etc. El Business Delegate podría interceptar dichas excepciones a nivel de servicio y generar en su lugar excepciones a nivel de aplicación. Las excepciones de nivel de aplicacion son fáciles de manejar por los clientes, y pueden ser amigables para el usuario. El Business Delegate también podría realizar de forma transparene cualquier operación de reintento o de recuperación 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 razón competitiva para utilizar el patrón.

Otro beneficio es que el delegado podría 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 implementación de código de búsqueda del servicio de negocio. El Lookup Service podría 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 relación uno-a-uno entre los dos. Esta relación existe porque la lógica que podría haber sido encapsulada en un Business Delegate en relación a su interacción con varios servicios de negocio (creando una relación uno-a-uno) normalmente se construye de vuelta en un Session Facade.

Finalmente, se debería tener en cuenta que este patrón se podría utilizar para reducir el acoplamiento entre otra capas, no simplemente entre las capas de presentación y de negocio.

. Estructura

La siguiente figura muestra el diagrama de clases que representa al patrón 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 típicas para este patrón:

El BusinessDelegate utiliza un LookupService para localizar el servicio de negocio. El servicio de negocio se utiliza para invocar a los métodos de negocio por cuenta del cliente. El método Get_ID muestra que el BusinessDelegate puede obtener una versión String del handle (como un objeto EJBHandle) para el servicio de negocio y devolverlo al cliente como un String. El cliente puede utilizar la versión String del handle más tarde para reconectar con el servicio de negocio que estaba utilizando cuando obtuvo el handle. Esta técnica evitará nuevas búsquedas, ya que el handle es capáz de reconectar con su ejemplar del servicio de negocio. Se debería observar que los objetos handle los implementa el contenedor y podrían no ser portables entre contenedores de diferentes vendedores.

El diagrama de secuencia de la siguiente figura muestra la obtención de un BusinessService (como un bean de sesión o de entidad) utilizando este handle.

. BusinessDelegate

El rol de BusinessDelegate es proporcionar control y protección para el servicio de negocio. BusinessDelegate puede exponer dos tipos de constructores al cliente. Un tipo de petición ejemplariza el BusinessDelegate sin una ID, mientras que el otro lo inicializa con un ID, donde ID es una versión 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 (más adelante veremos el patrón 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 implementación del BusinessService de nombrado y búsqueda. Además, el cliente de la capa de presentación 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 implementación de la búsqueda 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 métodos subyacentes del API de servicios de negocio. En esta estrategia, un Business Delegate proporciona la función de proxy para pasar los métodos del cliente al bean de sesión que encapsula. Adicionalmente el Business Delegate podría hacer un caché con los datos necesarios, incluyendo las referencias remotas de los objetos home o remote del bean de sesión para mejorar el rendimiento reduciendo el número de búsquedas. El Business Delegate también podría convertir dichas referencias en identificadores de versión (IDs) y viceversa, utilizando los servicios de un Service Locator.

El ejemplo de implementación de esta estrategia se explica en la sección Código de Ejemplo de esta página.

. 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 podrían utilizar XML como el lenguaje de integración. 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 presentación y de negocio ocultando todos los detalles de implementación de la capa de negocio. Es fácil manejar los cambios porque están centralizados en un sólo lugar, el Business Delegate.
  • Traduce las Excepciones del Servicio de Negocio
    El Business Delegate es el responsable de traducir cualquier excepción de red o relacionada con la infraestructura en excepciones de negocio, aislando a los clientes del conocimiento de las especifidades de la implementación.
  • Implementa Recuperación de Fallos y Sincronización de Threads
    Cuando el Business Delegate encuentra un fallo en el servicio de negocio, puede implementar características de recuperación automática sin exponer el problema al cliente. Si la recuperación tiene éxito, el cliente no necesita saber nada sobre el fallo. Si el intento de recuperación no tiene éxito, entonces el Business Delegate necesita informar al cliente del fallo. Además, los métodos del Business Delegate podrían 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, podría proporcionar una variante del interface proporcionado por los beans enterprise subyacentes.
  • Impacto en el Rendimiento
    El Business Delegate podría proporcionar servicio de caché (y un mejor rendimiento) a la capa de presentación para las peticiones de servicios comunes.
  • Presenta una Capa Adicional
    El Business Delegate podría verse como la adicción de una capa innecesaria entre el cliente y el servicio, y con eso incrementar la complejidad y disminuir la flexibilidad. Algunos desarrolladores podrían sentir esto coomo un esfuerzo extra para desarrollar Business Delegates con implementaciones que utilizan la estrategia Delegate Proxy.
  • Oculta los elementos Remotos
    Aunque la localización transparente es uno de los beneficios de este patrón, podría surgir un problema diferente debido a que el desarrolador está tratanto con un servicio remoto como si fuera un servicio local. Esto podría suceder si el desarrollador del cliente no entiende que el Business Delegate es cliente-proxy a un servicio remoto. Normalmente, unas llamadas a métodos en el Business Delegate resultan en unas llamadas a métodos remotos bajo la envoltura. Ignorando esto, el desarrollador podría tender a realiaar varias llamadas a métodos para realizar una sola tarea, lo que incrementará el tráfico en la red.

. Código de Ejemplo: Implementar el Patrón Business Delegate

Consideremos una Aplicación de Servicios Profesional (PSA), donde un cliente de la capa Web necesita acceder a un bean de sesión que implementa el patrón Session Facade. Se puede aplicar el patrón Business Delegate para diseñar un clase Delegate como ResourceDelegate, que ecapsula la complejidad de tratar con el bean de sesión ResourceSession. En el siguientre fragmento de código podemos ver la implementación 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 código 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 patrón Service Locator se podría utilizar para crear el servicio de búsqueda del Business Delegate, ocultando los detalles de implementación de cualquier servicio de búsqueda y código de acceso.
  • Proxy [GoF]
    Un Business Delegate podría actuar como un proxy, proporcionando suplentes para los objetos en la capa de negocio.
  • Adapter [GoF]
    Un Business Delegate podría utilizar el patrón 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.

COMPARTE ESTE ARTÍCULO

ENVIAR A UN AMIGO
COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN GOOGLE +
ARTÍCULO ANTERIOR

¡SÉ EL PRIMERO EN COMENTAR!
Conéctate o Regístrate para dejar tu comentario.