Buenas, hoy veremos un ejemplo completo de como interacturar desde WSO2 con una cola ActiveMQ. Mostraremos como configurar el Micro Integrator, MI, escribir y leer de la cola y consultar cuantos registros tiene.
Para el ejemplo utilizaremos las siguientes versiones:
- Micro Integrator 4.0.0
- Active MQ 5.8.14.
1. Docker Compose
Por un lado debemos incluir las librerías y dependencias de ActiveMQ en el docker compose base que tenemos:
- activemq-broker, activemq-client y activemq-openwire-legacy 5.14.0
- geronimo-j2ee-management_1_1_spec-1.0.1 y geronimo-jms_1.1_spec-1.1.1
- hawtbu-1.11
activemq:
image: rmohr/activemq:5.14.5
mem_limit: 1G
hostname: activemq
container_name: activemq
ports:
- 8161:8161 #UI
- 61616:61616 #JMS
networks:
wso2-net:
ipv4_address: 172.16.238.20Unexpected error during sending message out org.apache.axis2.AxisFault: The system cannot infer the transport information from the jms:/.....
[[transport.jms.sender]] name = "myQueueSender" parameter.initial_naming_factory = "org.apache.activemq.jndi.ActiveMQInitialContextFactory" parameter.provider_url = "tcp://activemq:61616" parameter.connection_factory_name = "QueueConnectionFactory" parameter.connection_factory_type = "queue" parameter.cache_level = "producer"
[[transport.jms.listener]] name = "myQueueConnectionFactory" parameter.initial_naming_factory = "org.apache.activemq.jndi.ActiveMQInitialContextFactory" parameter.provider_url = "failover:tcp://activemq:61616" parameter.connection_factory_name = "QueueConnectionFactory" parameter.connection_factory_type = "queue" parameter.cache_level = "consumer" [[transport.jms.listener]] name = "default" parameter.initial_naming_factory = "org.apache.activemq.jndi.ActiveMQInitialContextFactory" parameter.provider_url = "failover:tcp://activemq:61616" parameter.connection_factory_name = "QueueConnectionFactory" parameter.connection_factory_type = "queue"
Ahora procederemos a crear el primer recurso de una API, con el cual enviaremos información al activeMQ. Pero previamente transformaremos el mensaje, simplemente por añadir una pequeña lógica al ejemplo.
<resource methods="POST" uri-template="/activeMQ/"> <inSequence> <payloadFactory media-type="xml"> <format> <m:getQuote xmlns:m="http://services.samples"> <m:request> <m:book> <m:isbn>$1</m:isbn> <m:release>$2</m:release> </m:book> </m:request> </m:getQuote> </format> <args> <arg expression="$.isbn" evaluator="json"/> <arg expression="$.year" evaluator="json"/> </args> </payloadFactory> <property name="OUT_ONLY" value="true"/> <call> <endpoint> <address uri="jms:/myqueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory
&java.naming.provider.url=failover:(tcp://activemq:61616) &java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory &transport.jms.DestinationType=queue&redeliveryPolicy.redeliveryDelay=30000&maximumRedeliveries=10" /> </endpoint> </call> <respond /> </inSequence> <outSequence/> <faultSequence/> </resource>
En este código hay dos apartados interesantes:
- La configuración de la propiedad OUT_ONLY que nos permite indicarle al MI que no se quede a la espera de una respuesta por parte del ActiveMQ.
- La configuración de la invocación al ActiveMQ, donde aparte de los valores básicos para la configuración, podemos incluir la política de reintentos a través de las propiedades de redelivery o aumentar la resiliencia con la configuración de failover, donde podemos incluir varios nodos de ActiveMQ.
<address uri="jms:/myqueue?transport.jms.ConnectionFactory=myCustomSender" />
<resource methods="GET" uri-template="/activeMQ/{broker}/{queue}/count"> <inSequence> <property name="Authorization" expression="fn:concat('Basic ', base64Encode('admin:admin'))" scope="transport"/> <send> <endpoint xmlns="http://ws.apache.org/ns/synapse" name="mock_v1_activemqCount_httpEp"> <http method="GET" uri-template="http://activemq:8161/api/jolokia/read/org.apache.activemq:type=Broker,brokerName={uri.var.broker},destinationType=Queue,destinationName={uri.var.queue}/QueueSize" /> </endpoint> </send> </inSequence> <outSequence> <property name="ContentType" scope="axis2" type="STRING" value="application/json"/> <property name="messageType" scope="axis2" type="STRING" value="application/json"/> <switch source="json-eval($.status)"> <case regex="200"> <payloadFactory media-type="json"> <format> { "count": $1 } </format> <args> <arg evaluator="json" expression="json-eval($.value)"/> </args> </payloadFactory> </case> <default> <property name="HTTP_SC" value="500" scope="axis2" /> <payloadFactory media-type="json"> <format>{ "msg": "Unexpected error"}</format> <args /> </payloadFactory> </default> </switch> <respond/> </outSequence> <faultSequence/> </resource>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="activemqExample_v1_consumer_pr" transports="jms" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence> <log level="full"> <property name="MSG" value="Receiving messages from Queue" /> </log> <property action="set" name="OUT_ONLY" value="true"/> <drop /> </inSequence> <faultSequence /> </target> <parameter name="redeliveryPolicy.maximumRedeliveries">1</parameter> <parameter name="transport.jms.DestinationType">queue</parameter> <parameter name="transport.jms.SessionTransacted">true</parameter> <parameter name="transport.jms.Destination">myqueue</parameter> <parameter name="redeliveryPolicy.redeliveryDelay">2000</parameter> <parameter name="transport.jms.CacheLevel">consumer</parameter> <description /> </proxy>
curl --request POST 'https://localhost:8253/mock/activeMQ' \
--header 'Content-Type: application/json' \
--data-raw '{
"author":"Alfred Bester",
"name":"the stars my destination",
"isbn":"1-85798-814-0",
"year": 1956
}'