Implementar un ESB personalizable con Java

Considere una empresa en la que tiene aplicaciones heterogéneas, posiblemente entregadas por diferentes equipos, que necesitan interactuar entre sí pero tienen las siguientes limitaciones:

  • Cada aplicación no se crea necesariamente con la misma tecnología y es posible que no se comunique con las demás mediante su mecanismo de invocación nativo, por ejemplo, una aplicación J2EE y una aplicación .Net.
  • Preferiblemente, cada aplicación no debería transformar sus solicitudes al formato comprendido por la aplicación de destino. Además, la empresa tiene muchas aplicaciones que utilizan la aplicación de destino.
  • Los componentes del servicio deben utilizar un mecanismo de invocación o solicitud que les sea natural. Por ejemplo, una aplicación J2EE existente puede aceptar solicitudes solo a través de Java Message Service (JMS).
  • La empresa avanza hacia una arquitectura en la que una aplicación se ocupa únicamente de, uno, lo que sabe y, dos, lo que debe pasar como parámetros cuando quiere obtener los servicios de otra aplicación dentro de la empresa.

Otras restricciones pueden requerir que tenga una infraestructura que permita que aplicaciones heterogéneas se integren sin problemas sin alterar su diseño. Un bus de servicio empresarial (ESB) es una forma de realizar dicha arquitectura de integración empresarial.

Aunque cada empresa probablemente creará su ESB de una manera única, es importante tener en cuenta la flexibilidad al considerar la definición de un ESB. No hay un enfoque fijo para construir uno. La idea es tener una capa de conectividad que optimice las interacciones entre los consumidores de servicios y los proveedores de servicios, una que pueda responder a contextos orientados a eventos, mensajes o servicios.

Este artículo analiza un enfoque para crear un ESB extensible basado en Java que admita los requisitos funcionales de ESB más comunes.

Requisitos comunes de ESB

Los requisitos comunes de un ESB también son sus características más utilizadas:

  1. Enrutamiento: el ESB debe proporcionar un mecanismo de enrutamiento eficiente y flexible.
  2. Transformación: un componente de servicio no debería necesitar conocer el formato de solicitud del servicio de destino que podría invocar. Según el solicitante y el objetivo, el ESB debería poder aplicar la transformación adecuada a la solicitud para que el objetivo pueda comprenderla.
  3. Transporte multiprotocolo: Una implementación de ESB que habla solo JMS o solo servicios web no tiene mucho valor. Debería ser lo suficientemente extensible para admitir múltiples protocolos de mensajes según las necesidades de la empresa.
  4. Seguridad: si es necesario, el ESB debe hacer cumplir la autenticación y la autorización para acceder a los diferentes componentes del servicio.

La Figura 1 muestra los principales componentes arquitectónicos de un ESB. Tiene tres amplios compartimentos:

  1. Receptor: un ESB expone diferentes interfaces para permitir que las aplicaciones cliente envíen mensajes al ESB. Por ejemplo, un servlet podría recibir las solicitudes HTTP para el ESB. Al mismo tiempo, podría tener un MDB (bean controlado por mensajes) escuchando en un destino JMS donde las aplicaciones cliente pueden enviar mensajes.
  2. Núcleo: esta es la parte principal de la implementación del ESB. Maneja el enrutamiento y la transformación, y aplica seguridad. Por lo general, se compone de un MDB que recibe las solicitudes entrantes y luego, según el contexto del mensaje, aplica la transformación, el enrutamiento y la seguridad adecuados. Los detalles sobre el enrutamiento, el transporte, la transformación y la información de seguridad se pueden especificar en un documento XML (que se explica en breve).
  3. Despachador: Todos los manipuladores de transporte de salida se incluyen en esta parte del ESB. Puede conectar cualquier controlador de transporte arbitrario (correo electrónico, fax, FTP, etc.) en el ESB.

Todas estas partes del ESB están unidas por un documento XML que enumera todas las rutas en las que opera el ESB. Los diferentes controladores de transporte, transformadores y políticas de reintento y su conexión a diferentes rutas están todos conectados a través de este documento XML.

ESBConfiguration.xml

La lista XML ESBConfiguration.xml, que aparece a continuación, nos da una idea sobre el funcionamiento de un ESB. Los principales elementos de interés en ESBConfiguration.xmlson los siguientes:

  1. Beans: Este elemento contiene cero o más Beanelementos.
  2. Bean: Este elemento básicamente define la forma en que creamos y configuramos una Beanclase. Tiene los siguientes atributos:
    • name: Nombre exclusivo que se puede utilizar para hacer referencia a este bean.
    • className: Nombre completo de la clase de bean.
    Cada bean puede tener cero o más Propertyelementos como hijos. Cada Propertyelemento tiene un atributo nameque lo identifica y un elemento secundario de tipo Valueque contiene el valor de la propiedad. Estas propiedades son en realidad los miembros de la clase de estilo JavaBeans que pueden configurar la clase de bean.
  3. RetryPolicies: Este elemento contiene cero o más elementos secundarios RetryPolicy.
  4. RetryPolicy: Este elemento define la política de reintento para una ruta determinada. Tiene un atributo nameque se puede usar para referirse a él. Tiene dos elementos secundarios llamados MaxRetriesy RetryInterval.
  5. Route: El EsbConfigurationelemento raíz puede contener cero o más elementos secundarios de este tipo. Básicamente representa una ruta para la ESB. Tiene los siguientes atributos:
    • name: Nombre único que se puede utilizar para hacer referencia a esta ruta.
    • retryPolicyRef: Referencia a la política de reintento. Debe coincidir con el atributo RetryPolicydel elemento name.
    • transformerRef: Referencia a un bean que representa al transformador. Debe coincidir con el atributo Beandel elemento name.
    El Routeelemento puede tener uno o más elementos secundarios de tipo TransportHandlerRef. Este hijo básicamente apunta a un bean que representa un manejador de transporte apropiado que debe usarse para esta ruta, y el nombre del método público de ese bean que debe invocarse para enviar el mensaje. Opcionalmente, el Routeelemento puede tener un DeadLetterDestinationhijo que apunta a otra ruta que representa un destino de letra muerta.

A EsbConfiguration.xmlcontinuación, aparece un documento XML de muestra :

                              qcf-1   myCreditQueue     //www.tax.com/calc      file:///C:/temp/esb/transform/xsl/credit.xsl     file:///C:/temp/esb/transform/custom/configManager.properties      qcf-1   Redelivery.Queue     qcf-1   System.DL.Queue     qcf-1   System.Error.Queue     qcf-1   Redelivery.Request.Topic       10 100   10 500    

Comportamiento ESB

El ESBConfiguration.xmldocumento dicta el comportamiento de nuestro ESB. El EsbRouterMDB carga este XML desde una ubicación especificada en su descriptor de implementación. La información que contiene se organiza luego en una estructura de datos que se muestra en la Figura 2 a continuación.

El EsbRouterutiliza esta información (vía EsbConfigManager) para descifrar la ruta apropiada, la transformación, si la hay, que se aplicará, la verificación de autorización de seguridad, etc. El punto importante a tener en cuenta es la forma en que se ha utilizado la técnica de Inyección de Dependencias, junto con la herencia. para desacoplar varias funciones (como el transporte de mensajes multiprotocolo y la transformación de mensajes) del ESB, lo que permite que sea altamente extensible y personalizable.

Como muestra el diagrama de clases, hay dos interfaces importantes en el diseño de ESB: TransformHandlery TransportHandler. Le permiten escribir una implementación de transporte y transformación específica para mensajes enrutados. Estas clases de implementación se pueden conectar con las rutas a través de Beanelementos en EsbConfiguration. Por ejemplo, en el EsbConfiguration.xmldocumento de muestra , la siguiente definición de bean especifica el manejador de transporte:

   myQCF   myCreditQueue   

A continuación, se puede hacer referencia a este manejador de transporte en un Routenodo insertando un TransportHandlerhijo de esta manera:

Nota
El enfoque descrito en este artículo utiliza interfaces Java para definir los controladores de transporte y transformación. Por lo tanto, cualquier nuevo controlador tendría que implementar la interfaz requerida, lo que podría parecer intrusivo. Puede modificar fácilmente EsbConfigManagerpara usar Dependency Injection para llamar a cualquier método arbitrario de una clase de implementación, eliminando así la necesidad de implementar una interfaz. Pero como EsbRoutersiempre pasa una javax.jms.Messageinstancia, la clase de implementación de su controlador debe usar el tipo de javax.jms.Messagetodos modos.