ActiveMQ como JMS provider en Websphere Application Server

ActiveMQ como JMS provider en Websphere Application Server

Introducción

 

En esta publicación vamos a ver paso a paso como configurar Websphere Application Server (comúnmente conocido como WAS) para el manejo de queues y finalmente integrarlo con otro JMS provider de mensajería, para este ejemplo utilizaremos ActiveMQ.

Veremos cómo implementar y configurar un Mssasge Driven Bean en WAS para consumir mensajes guardados en las queues.

Entorno de trabajo:

    • Websphere Application Server 8.5.5
    • ActiveMQ 5.15.4
    • Java 8 u65


    Esta guía fue armada utilizando en conjunto las siguientes 3 instrucciones:

    • https://access.redhat.com/sites/default/files/video/thumbnails/WAS-AMQ-RAR-Instructions.pdf
    • http://www.craigstjean.com/2016/02/WebSphere-8-5-MQ-Spring-and-Message-Driven-Beans/
    • https://ibm.co/2wiEcWv

    Descargas

     

     

    Objetivo

    Lograr integrar ActiveMQ como JMS provider de Websphere Application Server.

     

    Diagrama Arquitectura

    Contamos con una app web, la cual envía mediante un HTTP Request un mensaje capturado por un JavaServlet basico y este envía el mensaje a una queue. El mensaje encolado de esta manera es consumido por un Message Listener y encolada a otra queue de mensajes (Response Quque). Nuestro sevlet, realizara un poll a la queue para obtener los mensajes enviados por el MDB para ser mostrado en nuestra app web.

    Websphere JMS Provider

    En este punto vamos a ver cómo crear una app web utilizando como JMS Provider la que viene por defecto en el Websphere Application Server.

    Para ello vamos a tener un war con una pequeña aplicación web y un jar que contiene nuestro MDB.

    En esta seccion vamos a ver los siguientes puntos:

    • Configuración de Websphere
    • Creando una app web

    Basándonos en el diagrama de arquitectura ya propuesto, para este punto, al estar trabajando exclusivamente en el Websphere Application Server, nuestro diagrama de arquitectura sera el siguiente:

    Configuración Websphere

    Websphere cuenta con una consola administrativa, la cual por defecto se encuentra en la siguiente url: https://localhost:9043/ibm/console/logon.jsp.

    En esta sección vamos a configurar un Bus en el websphere y asignarle una queue. A la queue creada de esta manera, vamos asignarle un jndi name y al bus le vamos asignar una connection factory para utilizarla desde nuestra aplicación.

    Buses
    Un bus de integración de servicios es un grupo de uno o varios servidores de aplicaciones o clústeres de servidores en una célula de WebSphere Application Server que colaboran para proporcionar servicios de mensajería asíncrona.

    A continuación se puede ver una serie de pasos a seguir para la creación de un Bus:

      1. Ingresar a la consola administrativa de Websphere
      2. Service integration > Buses

     

      1. Seleccionamos New…
      2. Ingresamos el nombre del bus que deseamos crear, para este ejemplo le ingresamos el nombre “Bus”, dejamos sin seleccionar la opción “Bus security” y finalizamos confirmando la creación del bus.
      3. “Next” y salvamos los cambios. Deberiamos ver en la seccion nuestro bus de esta manera
      4. Ingresamos al bus creado y dentro del mismo ingresamos a la opcion “Destinations” en la sección “Destination resources”.

     

    Destinations

    Las Destinations son las Queues o Topics en donde vamos a guardar y consumir nuestros mensajes.

    Para este ejemplo nos crearemos 2 Queues, una bajo el nombre de REQ.HELLO, la cual contiene los mensajes enviados desde nuestra aplicación y RESP.HELLO, en donde se guardan los mensajes consumidos por nuestro MDB y luego son recibidos por nuestra app.

    Creación de Bus REQ.HELLO:

    1. Ingresar a la consola administrativa de Websphere
    2. Service integration > Buses > Seleccionamos nuestro bus creado y NEW …
    3. Seleccionamos el tipo de Bus que queremos crear, para este ejemplo seleccionamos Queue. Next…
    4. Ingresamos el identificador, el cual es el nombre de nuestra Queue. Next…
    5. Seleccionamos el Bus member, en este punto es donde seleccionamos el Nodo del websphere en donde vamos a crear nuestro queue. Next.. y confirmamos nuestra queue

    Para la creación del Bus RESP.HELLO, seguir los mismos pasos pero cambiando el nombre del identificador en el punto 4.

    Queue

    Finalizada la creación de los buses y sus queues, debemos ahora configurar el JMS queue para cada queue del bus que vamos a usar en nuestra aplicación.

    No hay que confundir las Queue creadas en el bus con las Queues creadas en este punto. Las queues creadas en los buses son las Destinations, mientras que las Queue creadas en este punto son colas, pero que funcionan como JMS.

    Es en este punto en donde creamos el JNDI name de nuestras Queues de un bus especifico. Para nuestro ejemplo, debemos crearnos dos JMS queue, una para los mensajes enviados (REQ.HELLO) y otra para los mensajes recibidos (RESP.HELLO).

    Pasos a seguir (REQ.HELLO):

    1. Ingresar a la consola administrativa de Websphere
    2. Resources > JMS > Queues
    3. Seleccionamos NEW…
    4. En la sección de “Select JMS resource provider”, seleccionamos nuestro messaging provider, en este caso es el Default messaging provider
    5. Completamos la configuración ingresando los siguientes datos:
    • Name: Request_HelloQueue
    • JNDI name: jms/Request_HelloQueue
    • Bus name: bus
    • Queue name: REQ.HELLO

    El resto de la configuración lo dejamos con los valores por defecto.

    Pasos a seguir (RESP.HELLO):

    1. Repetir los pasos para la creación del JMS de la queue REQ.HELLO 1,2,3 y 4.
    2. Completamos la configuración ingresando los siguientes datos :
    • Name: Response_HelloQueue
    • JNDI name: jms/Response_HelloQueue
    • Bus name: bus
    • Queue name: RESP.HELLO

    Finalizada las configuraciones de Queues, debemos ver algo muy similar en la imagen a continuación en en la sección de Queues:

    Crear una Active Specifcation

    Para que nuestro MDB funcione, necesitamos configurar un JMS activation specificacion, la cual permite la conexión entre nuestro servidor de aplicaciones y la aplicación, de esta manera cualquier clase que implemente un MessageListener va a poder escuchar cualquier mensaje que se guarde en una Queue o Topic.

    Pasos a seguir:

    1. Ingresar a la consola administrativa de Websphere
    2. Resources > JMS > Activation specification
    3. Seleccionar el scope, por lo general se utiliza el nodo del servidor en donde vamos a deployar nuestra aplicación o donde se va a encontrar nuestro MDB y queues.
    4. NEW…
    5. Seleccionamos el JMS Default messaging provider, el cual es el mismo que utilizamos en nuestra Queue ya configurada.
    6. Ingresamos el nombre Activation_Hello y el jndi jms/Activation_Hello por el cual lo vamos a referenciar
    7. En la sección de Destinations, seleccionamos el tipo de destino al cual vamos a hacer referencia, en este caso seleccionamos Queue e ingresamos en Destination lookup, el jndi name jms/Request_HelloQueue que ya ingresamos en el paso anterior de la Queue, en donde se van a guardar los mensajes enviados por el usuario. Finalmente deberíamos tener la siguiente configuración:
    8. Ok y Salvar.

     

    Connection factories

    Desde la consola administrativa del Websphere Application Server podemos crear conexiones a los JMS providers que deseemos, ya sea para queues o topics. El propio WAS contiene por defecto un provider de mensajería, el cual vamos a utilizar para crear las conexiones a las queues o topics contenidos dentro del servidor.

    Para configurar el messaging provider por defecto debemos seguir los siguientes pasos:

    1. Ingresar a la consola administrativa de Websphere
    2. Resources > JMS > Connection factories
    3. Seleccionamos built-in-jms-connectionfactory, la cual corresponde a la connection factory por defecto que viene en el WAS. Dentro de built-in-jms-connectionfactory, podemos encontrar varias properties, entre ellas el JNDI name de la connection factory como también el bus al cual vamos a conectarnos. El Bus es un grupo interconectado de servidores y clusters que ya vienen embebidos dentro del servidor.
    4. Seleccionar el bus al que se desea crear una conexión. Este bus sera el creado con las Destination REQ.HELLO y RESP.HELLO.
    5. Ok y Salvar

     

    Creando una app web

    Las aplicación creadas en Java EE y que vayan a ser deployadas en un WAS, deben contar con un archivo de configuración bajo el nombre ibm-web-bnd.xml. Este archivo contiene los recursos que vamos a necesitar y sus referencias (jndi name).

    Al ser un aplicación web, vamos a contar un web.xml, para este ejemplo, vamos a contar con el siguiente xml:

    • message-destination-ref: Para cualquier aplicación que use MDB, debemos especificarle mediante este archivo el jndi name de las destinations y su nombre que luego vamos a inyectar como dependencia en nuestro código.
    • resource-ref: cualquier aplicación que use una connection factory a la cual debamos conectarnos para enviar un mensaje, se debe agregar a este archivo como un recurso.

     

    Servlet

    En este ejemplo vamos a utilizar un servlet básico para obtener el mensaje enviado por post y enviarlo a nuestra queue (REQ.QUEUE), como también vamos a obtener los mensajes que lleguen a la queue RESP.QUEUE.

    En nuestro servlet, vamos a inyectar por jndi nuestra connection factory y las Queues en donde vamos a enviar y consumir nuestros mensajes.

     

    MDB

    A continuación vamos a implementar un MessageListener, el cual va a estar escuchando cualquier mensaje enviado a la cola REQ.HELLO.

    Todo mensaje que llegue a la cola REQ.HELLO, va a ser consumido por nuestro MDB. El mensaje obtenido de esta manera por nuestro listener, va a ser enviado a otra cola de respuesta (RESP.HELLO).

    Para este ejemplo, nuestro MDB se encuentra en un jar independiente al war.

    Al igual que en la implementación del servlet, vamos a tener otro archivo de configuración ibm-ejb-jar-bnd.xml de la siguiente manera:

    • message-driven name: Nombre de la clase que implementa MessageListener
    • jca-adapter: Definimos la referencia al recurso del MDB al cual va a estar escuchando
    • resource-ref: Recursos a inyectar como dependencias del MDB

     

    Finalmente la implementación de nuestra MDB se vería de esta manera:

     

    ActiveMQ JMS provider

    En el punto anterior vimos como utilizar el JMS provider embebido dentro del WAS. A continuación veremos como integrar el WAS utilizando otro JNDI provider distinto al que ya contiene por defecto. Para el siguiente ejemplo, estaremos configurando Apache ActiveMQ, el cual es un broker de mensajería.

    Desarrollaremos una aplicacion web, que pueda enviar un mensaje y se guarde en una cola ubicada en el broker de mensajería. También tendremos un MDB, el cual estará encargado de escuchar la cola en nuestro broker. Al igual que la app creada en el punto anterior, ante cualquier mensaje enviado, el MDB lo consumirá de forma automática y lo guardara en otra cola de respuesta utilizada para mostrar los mensajes enviados desde nuestras web. Esta ultima cola se encuentra también en el broker de mensajería.

    En la imagen a continuación, vamos a ver el diagrama de arquitectura utilizado como base para la configuración y desarrollo de nuestra app:

    Desde la consola administrativa del websphere podemos configurar ActiveMQ como JMS provider, para ello debemos deployar el Resource Adapter del ActiveMQ en el Websphere.

    Configuración Websphere

    A grandes rasgos, en los siguientes puntos de esta sección vamos a realizar las siguientes tareas.

    • Deployar ActiveMQ resource adapter
    • Resource adapter: Crear una Active Specifcation
    • Resource adapter: Crear una Connection Factory
    • Queue connection factories
    • Creando una app web

     

    Deploy ActiveMQ Resource Adapter

    El ActiveMQ resource adater no viene en la instalación por defecto del ActiveMQ, para ello debemos descargarlo. Para este ejemplo vamos a descargar el .rar correspondiente a la versión 5.15.4.

    Podemos descargarlo de esta url: http://search.maven.org/#search|ga|1|a%3A»activemq-rar»

    Una vez que tengamos el rar, procedemos a instalarlo en el webpshere de la siguiente manera:

    1. Ingresar en la consola de websphere
    2. Resources > Resource Adapters > Resource Adaptares
    3. Seleccionamos el Scope del adaptador que vamos a instalar y seleccionamos Instalar RAR
    4. En Path, ubicamos y seleccionamos el archivo descargado y Next.
    5. En configuración, dejamos por defecto los valores cargados. Ok y salvamos la configuración.

    Finalizada la instalación debemos visualizar nuestro adaptor en la sección Resource Adapters de esta manera:

    Resource adapter: Crear una Active Specifcation

     

    1. Ingresamos a nuestro ActiveMQ Resource Adapter recien instalada en la sección de Resource Adapter y en la sección Additional Properties, seleccionamos la opcion J2C activation specifications.
    2. Seleccionamos New.. y completamos con estos valores:Name: AMQActivationSpecJNDI Name: AMQActivationSpecMessage listener type: javax.jms.MessageListener supported by org.apache.activemq.ra.ActiveMQActivationSpec
    3. Ok y Salvar.

     

    Resource adapter: Crear un Administered Object

     

    1. Ingresamos a nuestro ActiveMQ Resource Adapter recien instalada en la sección de Resource Adapter y en la sección Additional Properties, seleccionamos la opcion J2C activation specifications.
    2. New y completamos las properties con los siguietnes valores:Name: myQueueJNDI Name: dynamicQueues/myQueueAdministered object class: org.apache.activemq.command.ActiveMQQueueimplements javax.jms.queue
      En este punto, creamos la Queue (myQueue) que se va a crear en el ActiveMQ cuando se envie el mensaje con su JNDI para acceder de forma remota (dynamicQueues/myQueue).
    3. Ok y salvar.
    4. En la seccion de Additional Properties, ingresamos a J2C administered objects custom properties
    5. Seleccionamos la property PhysicalName e ingresamos su valor con el mismo nombre de la Queue ingresado en el punto 2.
    6. Ok y salvar

     

    Resource adapter: Crear una Connection Factory

     

    1. Ingresamos a nuestro ActiveMQ Resource Adapter recién instalada en la sección de Resource Adapter y en la seccion Additional Properties, seleccionamos la opcion J2C connection factories.
    2. New y completamos los siguientes valores:Name: AMQCFJNDI name: jms/AMQCFConnection factory interface: javax.jms.ConnectionFactory
    3. Ok y salvar

     

    Queue connection factories:

    Finalazada la configuración del Resource Adapter, debemos configurar una connection factory para que desde nuestro servlet se pueda enviar un mensaje y que este se pueda encolar en una Queue, para ello debemos realizar los siguientes pasos:

    1. En la consola de webpshere, ir a Resources > JMS > JMS Connection factories y seleccionar New
    2. Completamos los datos con los siguientes valores:
    • Name: ActiveMQ
    • External initial context factory: org.apache.activemq.jndi.ActiveMQInitialContextFactory
    • External provider URL: tcp://host:port correspondiente a nuestro broker de mensajeria
    • Class path: En este campo, ingresaremos el path completo hasta los siguientes archivos:
      • activemq-client-5.15.4.jar – link de descarga: https://mvnrepository.com/artifact/org.apache.activemq/activemq-client/5.15.0
      • hawtbuf-1.11.jar – link de descarga: https://mvnrepository.com/artifact/org.fusesource.hawtbuf/hawtbuf/1.11
      • slf4j-api-1.7.25.jar – link de descarga: https://mvnrepository.com/artifact/org.slf4j/slf4j-api/1.7.25
      • En la imagen a continuación podemos ver un ejemplo de la configuración de General properties

    En la imagen a continuación podemos ver un ejemplo de la configuración de General properties

     

    Importante: nuestra aplicacion NO debe contener ninguna libreria que agreguemos en el claspath.

    Finalmente salvamos los cambios.

    Habiendo configurado un nuevo JMS provider, debemos crear una connection factory para establecer la conexion con la misma, para ello realizamos lo siguiente:

    1. Resources > JMS > Queue connection factories y seleccionamos New.
    2. Seleccionamos nuestro JMS resource provider llamado ActiveMQ (creado en el paso anterior) y OK
    3. Completamos la configuracion con los siguientes valores:
    • Name: myQCF
    • JNDI name: jms/myQueueConnectionFactory
    • External JNDI name: QueueConnectionFactory

    Finalmente Ok y salvamos

    Por ultimo, debemos crearnos una Queue, cuyo jndi sea accedida en el mismo scope del servidor.

    1. Resources > JMS > Queue y seleccionamos NEW.
    2. Seleccionamos nuestro ActiveMQ como JMS resource provider y OK.
    3. Completamos con los siguientes valores la configuracion:
    • Name: myQueue
    • JNDI name: queue/myQueue
    • External JNDi name: dynamicQueues/myQueue

    Ok y salvamos.

    Creando una app web

    La aplicación que vamos a crear en este punto va a ser similar a la creada previamente en el punto Websphere JMS Connection Factory, con la diferencia que los archivos que contienen los bindings de los resources van a estar apuntando a la configuracion realizada, como también la inyección de elementos correspondientes a esta sección.

    Vamos a tener los mismos archivos de configuración que ya vimos, pero con la diferencia que vamos a estar referenciando a la connection factory creada en el resource adapter del ActiveMQ, nuestros archivos web.xml y ibm-web-bnd.xml de nuestra app web van a tener el siguiente formato:

    web.xml

    Podemos observar lo siguiente:

    El resource corresponde a la conection factory cuyo JMS provider es el del ActiveMQ, con esto logramos establecer la conexion al broker de mensajeria para guardar nuestros mensajes en una queue.

    Los message-destinations-ref corresponde a los recursos que vamos a necesitar para nuestra aplicación. Definimos sus nombres, tipos y su JNDI de las queues que vamos a utilizar para guardar y obtener nuestros mensajes.

    ibm-web-bnd.xml

    En este fichero xml, podemos ver 3 referencias a 3 recursos.

    • jms/Response_HelloQueue que del borker de mensajer que va a ser nuestra cola remota donde vamos a volcar los mensajes que vana ser consumidos por el MDB que posteriormente vamos a mostrar en nuestra jsp.
    • queue/myQueue queue del broker de mensajeria
    • jms/myQueueConnectionFactory connection factory necesaria para efectuar la sesión y conexion con el broker de mensajería.

    Nuestro Servlet quedara de esta manera:

    HelloServlet.java

    Podemos notar la inyeccion de dependencias en el servlet por los jndi configurados en el web.xml y ib-web.bnd.xml

    Finalmente, nuestro MDB se ubicara en un jar aparte que tendra la siguiente configuracion:

    ibm-ejb-jar-bnd.xml

    • jca-adater destination-binding-name: corresponde al jndi name remota de la cola del broker de mensajería.
    • resource-ref: jndi name de nuestro ActiveMQ JMS Resource Adapter installado, va a ser inyetado a nuestra MDB para usar como connection factory
    • mesage-destination-ref: jndi name de la cola local utilizada para guardar los mensajes consumidos por el MDB.

    HelloMDB.java

     

    Deploy app en Websphere

    Los deploys en WAS son bastante lineales y similares para un jar, war o ear. Dependiendo de los recursos que hayamos definidos es que puede cambiar algunos pasos.

    En los pasos siguientes vemos como ejemplo el deploy de un war en el webspehere:

    1. Ingresar a la consola administrativa de Websphere
    2. Applications > Aplication Type > Websphere enterprise applications
    3. Install
    4. Buscamos nuestro war que deseamos deployar y Next
    5. Seleccionamos la opción Fast Path, NEXT y damos comienzo a la configuración de la instalación de nuestro war
    6. Step 1: En el campo Directory to install application ingresamos el nombre que deseemos. Esto creara en el file system (en donde hayamos instalado nuestro servidor), una carpeta en la que se ubicara nuestro war. Por lo general, la ruta de instalación tiene el siguiente formato: /IBM/WebSphere/AppServer/profiles/AppSrv01/[NODO]/[Nombre de nuestra carpeta ingresada]. Para este ejemplo ingresaremos el nombre ejemplo-mdb-web_war
    7. Step 2: Seleccionamos nuestro modulo y NEXT
    8. Step 3: ingresamos en el campo Context Root el siguiente valor: /ejemplo-mdb-web, de esta manera, para nuestro modulo vamos a definir el web.xml y la URI en como vamos a acceder, por ejemplo: si definimos nuestro context root como /hola y el mapeo de nuestro servlet es login, la URI conformada de esta manera tendría el siguiente formato: host:port/login/hola.
    9. Step 4: Es opcional, podemos o no seleccionar la opción metadata-complete attribute. Esto permite (o no) que cada vez que le acceda al modulo, se busque las anotaciones en la metadata.
    10. Step 5: Muestra un resumen final de la configuración de nuestro war previo a ser deployado. Si se desea se puede volver a los pasos anteriores para modificar algún valor. Seleccionamos Finish y Comienza la instalacion del war.
    11. Instalado el war, se muestra una pantalla de información, indicando si la misma fue correcto o si existió un error y cual fue su razón. En caso que sea exitoso el deploy, podemos deberíamos de ver la siguiente pantalla:
    12. REVIEW (opcional) para ver los cambios previos a salvar
    13. SAVE
    14. Finalizada la instalación, vemos nuestro war instalado pero no levantado (indicado por una cruz en rojo), para ello debemos seleccionar la app y seleccionar Start.
    15. ingresar host:port/ejemplo-mdb-web/ para utilizar la aplicación

     

    Comentarios

    Websphere Application Server, es un servidor con una gran cantidad de herramientas útiles que lo hacen un servidor potente, pero con una gran curva de aprendizaje.

    Como experiencia personal, en este caso en particular para configurar un JMS provider externo, llevo un esfuerzo adicional en investigación y fusión de varios documentos, ya que no se encontraba centralizada la información necesaria para realizar una configuración exitosa.

     

    Referencias

     

    • https://ibm.co/2wiEcWv
    • https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/urun_app_msgdestref.html
    • https://stackoverflow.com/questions/29099231/activemq-5-11-with-websphere-application-server-8-5
    • https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.iseries.doc/ae/cmb_aslp.html
    • https://www.ibm.com/support/knowledgecenter/SSEQTP_8.5.5/com.ibm.websphere.base.iseries.doc/ae/rmig_stabfeat.html
    • https://access.redhat.com/sites/default/files/video/thumbnails/WAS-AMQ-RAR-Instructions.pdf
    • http://www.craigstjean.com/2016/02/WebSphere-8-5-MQ-Spring-and-Message-Driven-Beans/