ActiveMQ es un proveedor de colas de versiones que tiene buena fama, así es que estamos confiando en éste más que en HornetQ que es el que viene embebido en JBoss 6.

Sin embargo, la documentación no me es muy transparente… por ej. puede seguir este Getting Started >> y levantar la versión 5.6 en http://localhost:8161/admin pero resutla que hay otro getting started para la versión 5 >> que dice que hay que compilarla con maven… no cacho.

También traté de poner una dependencia en el pom.xml de mi proyecto de prueba como dice aquí >>

<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>5.6.0</version>
</dependency>

pero entre que me da un error de compilación (por colisión de la clase javax.el.ElResolver) y que no veo que al iniciar JBoss haya nada en el log que diga ActiveMQ. Me parece que agregar la dependencia es si vas a extender el core de ActiveMQ y no para usarlo, por lo mismo, como usa Jetty, me estaría dando el conflicto de clases…

Entonces no queda otra que ver cómo deployar ActiveMQ como recurso dentro de JBoss… para ActiveMQ incluye un JCA llamado Resource Adapter, sin embargo, para descargar el RAR los links dan 404 y los ‘Nightly Snapshot’ llegan hasta la versión 4 del 2006… ¿estará medio abandonado el proyecto?

Rebuscándosela un poco, dentro del directorio apache-acitivemq-5.6.0/lib viene un activemq-rar.txt que dice

ActiveMQ RAR is no longer included in the distribution.Please download it separately from: http://repo1.maven.org/maven2/org/apache/activemq/activemq-rar/

y efectivamente desde ahí podemos descargar la última versión. Ahora, ya que es un repositorio de maven, ¿no podrá ser agregado como dependencia también? Efectivamente, lo podemos encontrar en la Maven Central >> y la dependencia que agregamos es

<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-rar</artifactId>
<version>5.6.0</version>
<type>rar</type>
</dependency>

Bueno, se borró todo lo que había escrito. Pero en resumen estaba viendo la posibilidad de usar esta dependencia para empaquetar el rar dentro del proyecto, para lo cual habría que transformar el war en ear.

En todo caso, primero estaba viendo cómo configurarlo. Para eso estaba siguiendo estas instrucciones >>

Primero, en server/all/deploy creamos un directorio con el mismo nombre de… se borró por tercera vez!

Creamos server/all/deploy/activemq-rar-5.x.x.rar, dentro metemos el rar y lo descomprimimos con

jar xvf activemq-rar-5.x.x.rar

y editamos dos archivos: por una parte, el META-INF/rar.xml

    • Se cambia el ServerUrl para que maneje los mensajes por métodos dentro de la VM en vez de por sockets TCP (no es obligatorio, pero es mucho más eficiente si es embedded)
      <config-property>
          <description>
            The URL to the ActiveMQ server that you want this connection to connect to.  If using
            an embedded broker, this value should be 'vm://localhost'.
          </description>
          <config-property-name>ServerUrl</config-property-name>
          <config-property-type>java.lang.String</config-property-type>
         <!-- <config-property-value>tcp://localhost:61616</config-property-value> comentar esta línea -->
       <config-property-value>vm://localhost</config-property-value><!-- descomentar esta línea -->
        </config-property>
      
    • Se cambia el BrokerXmlConfig para que tome sus configuraciones del xml que editaremos a continuación
      <config-property>
          <description>
            Sets the XML configuration file used to configure the embedded ActiveMQ broker via
            Spring if using embedded mode.
      
            BrokerXmlConfig is the filename which is assumed to be on the classpath unless
            a URL is specified. So a value of foo/bar.xml would be assumed to be on the
            classpath whereas file:dir/file.xml would use the file system.
            Any valid URL string is supported.
          </description>
          <config-property-name>BrokerXmlConfig</config-property-name>
          <config-property-type>java.lang.String</config-property-type>
          <!-- hay que rellenar con ésto -->
          <config-property-value>xbean:broker-config.xml</config-property-value>
        </config-property>
      

Lo otro es editar el broker-config.xml. Para hacerla corta digamos que el original viene así (en v.5.3)

<beans xmlns="http://activemq.apache.org/schema/core">
<bean xmlns=""/>
<!--  shutdown hook is disabled as RAR classloader may be gone at shutdown -->
<broker useJmx="true" useShutdownHook="false">

<managementContext>
<!-- use appserver provided context instead of creating one,
for jboss use: -Djboss.platform.mbeanserver -->
<managementContext createConnector="false"/>
</managementContext>

<persistenceAdapter>
<journaledJDBC journalLogFiles="5" dataDirectory="../data"/>
</persistenceAdapter>

<transportConnectors>
<transportConnector uri="tcp://localhost:61616"/ >
</transportConnectors>
</broker>
</beans>

y tiene que quedar así

<beans xmlns="http://activemq.apache.org/schema/core">
<!-- para inyectar directorios de jboss  -->
<bean xmlns="" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"/>
<!--  shutdown hook is disabled as RAR classloader may be gone at shutdown -->
<broker useJmx="true" useShutdownHook="false" brokerName="rober.broker1"> <!-- se agrega el nombre -->

<managementContext>
<!-- use appserver provided context instead of creating one,
for jboss use: -Djboss.platform.mbeanserver -->
<managementContext createConnector="false"/>
</managementContext>

<persistenceAdapter> <!--se usa el PlaceHolderConfigurer -->
<journaledJDBC journalLogFiles="5" dataDirectory="${jboss.server.data.dir}/activemq"/>
</persistenceAdapter>

<transportConnectors> <!--se repite el brokerName y se agrega discoveryUrl -->
<transportConnector uri="tcp://localhost:61616"/  brokerName="rober.broker1" discoveryUri="multicast://default">
</transportConnectors>

<!--se agrega este tag -->
<networkConnectors>
<networkConnector uri="multicast://default" />
</networkConnectors>

</broker>
</beans>

El asunto es que todo esto funciona para la versión 5.3… pero si lo hacemos en la versión 5.6 se cae con

Deployment "vfs:///home/roberto/JAVA/jboss-6.1.0.Final/server/all/deploy/activemq-rar-5.6.0.rar" is in error due to the following reason(s): java.lang.IllegalArgumentException: Null type

Si seguimos el stacktrace >> se vé que es un error de la librería scala-library-2.9.1.jar, que está en esta versión pero no en las anteriores.

De hecho al parecer es un error de la integración de Scala con JBoss >>, aparentemente porque una clase de JBoss está mal implementada par reflexión >>.

Éste es un error que sólo se produce en la última versión (5.6) y de hecho si intentamos este mismo procedimiento con la anterior (5.5) funciona bien. Hay en efecto una diferencia grande entre estas dos versiones (la última pesa 24Mb y la anterior 8Mb) lo que me mueve a preguntar de qué se trata todo esto.

UPDATE

Con este jaleo de la versión 5.6 no había terminado de configurar JBoss para que inicie las colas de ActiveMQ. Para ésto hay que poner un xml DTD (de configuración de un Data Source) para el JCA. Éste también va en /server/all/deploy y se llama activemq-jms-ds.xml. Tiene la siguiente estructura >>:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE connection-factories
PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN"
"http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd">
<connection-factories>
<tx-connection-factory>
<jndi-name>activemq/QueueConnectionFactory</jndi-name>
<xa-transaction/>
<track-connection-by-tx/>
<rar-name>activemq-rar-5.5.1.rar</rar-name>
<connection-definition>javax.jms.QueueConnectionFactory</connection-definition>
<ServerUrl>vm://localhost</ServerUrl>
<!--
<UserName>sa</UserName>
<Password></Password>
-->
<min-pool-size>1</min-pool-size>
<max-pool-size>200</max-pool-size>
<blocking-timeout-millis>30000</blocking-timeout-millis>
<idle-timeout-minutes>3</idle-timeout-minutes>
</tx-connection-factory>
<tx-connection-factory>
<jndi-name>activemq/TopicConnectionFactory</jndi-name>
<xa-transaction/>
<track-connection-by-tx/>
<rar-name>activemq-rar-5.5.1.rar</rar-name>
<connection-definition>javax.jms.TopicConnectionFactory</connection-definition>
<ServerUrl>vm://localhost</ServerUrl>
<!--
<UserName>sa</UserName>
<Password></Password>
-->
<min-pool-size>1</min-pool-size>
<max-pool-size>200</max-pool-size>
<blocking-timeout-millis>30000</blocking-timeout-millis>
<idle-timeout-minutes>3</idle-timeout-minutes>
</tx-connection-factory>

<mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.queue:name=outboundQueue">
<attribute name="JNDIName">activemq/queue/outbound</attribute>
<depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='activemq-rar-5.5.1.rar'</depends>
<attribute name="Type">javax.jms.Queue</attribute>
<attribute name="Properties">PhysicalName=queue.outbound</attribute>
</mbean>
<mbean code="org.jboss.resource.deployment.AdminObject" name="activemq.topic:name=inboundTopic">
<attribute name="JNDIName">activemq/topic/inbound</attribute>
<depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='activemq-rar-5.5.1.rar'</depends>
<attribute name="Type">javax.jms.Topic</attribute>
<attribute name="Properties">PhysicalName=topic.inbound</attribute>
</mbean>
</connection-factories>

Como vemos, en tx-connection-factory liga un Queue y un Topic a sus nombres JNDI.  Si no me equivoco éstas son las salidas y las que están en mbean son las entradas… nop, los mbean son AdminObjects… pa qué sirven… moya…

Ahora sí, al deployarlo podemos ver en el log de JBoss

...
INFO  [RARDeployment] Required license terms exist, view vfs:/home/roberto/JAVA/jboss-6.1.0.Final/server/all/deploy/activemq-rar-5.5.1.rar/META-INF/ra.xml
...
INFO  [XBeanBrokerFactory$1] Refreshing org.apache.activemq.xbean.XBeanBrokerFactory$1@4ca41180: startup date [Wed Aug 08 11:34:52 CLT 2012]; root of context hierarchy
...
WARN  [ActiveMQResourceAdapter] Could not start up embeded ActiveMQ Broker 'xbean:broker-config.xml': Line 19 in XML document from class path resource [broker-config.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'beans'.
...
INFO  [RARDeployment] Required license terms exist, view vfs:/home/roberto/JAVA/jboss-6.1.0.Final/server/all/deploy/activemq-rar-5.5.1.rar/activemq-rar-5.5.1.rar/META-INF/ra.xml
...
INFO  [AdminObject] Bound admin object 'org.apache.activemq.command.ActiveMQQueue' at 'activemq/queue/outbound'
INFO  [AdminObject] Bound admin object 'org.apache.activemq.command.ActiveMQTopic' at 'activemq/topic/inbound'
INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=activemq/QueueConnectionFactory' to JNDI name 'java:activemq/QueueConnectionFactory'
INFO  [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=ConnectionFactoryBinding,name=activemq/TopicConnectionFactory' to JNDI name 'java:activemq/TopicConnectionFactory'

Nótese el WARN que probablemente se deba a que el xml del ejemplo es para una versión anterior >>

Aún así no aparece listado como recurso JMS en la consola de administración de JBoss… ¿será que hay algo mal? Vamos a probarlo, porque no veo que esté partiendo el broker… Nop, como dice en el otro artículo >>, ya lo pude probar dentro de la VM.

Ahora la duda que tengo es, como lo quiero para hablar con C++ >> no me sirve que funcione dentro de la VM, sino que escuche por TCP.

TCP

Para que ActiveMQ funcione vía TCP en vez de dentro de la VM, vamos a hacer caso omiso del comentario en ra.xml, y vamos a dejar el ServerUrl como estaba

<config-property>
<config-property-name>ServerUrl</config-property-name>
<config-property-type>java.lang.String</config-property-type>
<config-property-value>tcp://localhost:61616</config-property-value>
<!--<config-property-value>vm://localhost</config-property-value>-->
</config-property>

Igualmente, en el activemq-ds.xml, vamos a dejar esta propiedad por red

 <tx-connection-factory>
 <jndi-name>activemq/QueueConnectionFactory</jndi-name>
 <xa-transaction/>
 <track-connection-by-tx/>
 <rar-name>activemq-rar-5.5.1.rar</rar-name>
 <connection-definition>javax.jms.QueueConnectionFactory</connection-definition>
 <ServerUrl>tcp://localhost:61616/</ServerUrl> <!-- en vez de vm://localhost -->
 <min-pool-size>1</min-pool-size>
 <max-pool-size>200</max-pool-size>
 <blocking-timeout-millis>30000</blocking-timeout-millis>
 <idle-timeout-minutes>3</idle-timeout-minutes>
 </tx-connection-factory>
 

En teoría no debiera ser más que eso… el problema es que al momento de usar la ConnectionFactory inyectada, escupe

ERROR [org.apache.activemq.ra.ActiveMQEndpointWorker] 
Failed to connect to broker [tcp://localhost:61616]: 
Could not connect to broker URL: tcp://localhost:61616. 
Reason: java.net.ConnectException: Connection refused: 
...

Entonces estoy cachando que no es que le esté diciendo que escuche en ese puerto, ¿sino que debe conectarse a otro ActiveMQ que está escuchando en esa dirección?? Efectivamente, si instalamos un ActiveMQ stand-alone como al principio, vuelve a andar.

¿O sea que el JCA actúa sólo como el enlace al JNDI? ¿No estarán sobrando muchas librerías si es que tiene la capacidad de correr sólo? Investigar más.

Este sitio utiliza cookies.    Leer más