En esta entrada vamos a ver como configurar (de forma rápida), como configurar colas con Spring y un gestor de colas, como es el caso de Apache ActiveMQ, para enviar y recibir mensajes. Para ello, podéis descargar:
- La versión 5.7.0 de ActiveMQ
- Tomcat 7
Os creáis un proyecto Maven con la siguiente configuración:
En el pom.xml, la dependencia a Spring y al core de ActiveMQ:
<?xml version="1.0"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <artifactId>spring-activemq-sample</artifactId> <modelVersion>4.0.0</modelVersion> <packaging>war</packaging> <groupId>papidal</groupId> <version>1.0</version> <properties> <releaseCandidate>1</releaseCandidate> <spring.version>3.1.1.RELEASE</spring.version> <java.version>1.5</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <maven.javadoc.reporting.version>2.7</maven.javadoc.reporting.version> <commons.logging.version>1.1.1</commons.logging.version> <log4j.version>1.2.16</log4j.version> <context.path>spring-activemq-sample</context.path> </properties> <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <configuration> <warName>${context.path}</warName> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>activemq-core</artifactId> <version>5.7.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>3.1.0.RELEASE</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-asm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> </dependency> </dependencies> </project>
Un contexto, context.xml, en el que estarán vuestras colas de entrada y salida, así como la conexión al gestor de colas:
<?xml version="1.0" encoding="UTF-8"?> <Context> <!-- Conexión ActiveMQ --> <Resource name="jms/mqConnectionFactory" auth="Container" type="org.apache.activemq.ActiveMQConnectionFactory" description="JMS Connection Factory" factory="org.apache.activemq.jndi.JNDIReferenceFactory" brokerURL="tcp://localhost:61616" /> <!-- Cola 1 --> <Resource name="jms/testQueueOne" auth="Container" type="org.apache.activemq.command.ActiveMQQueue" factory="org.apache.activemq.jndi.JNDIReferenceFactory" physicalName="TestQueueOne"/> <!-- Cola 2 --> <Resource name="jms/testQueueTwo" auth="Container" type="org.apache.activemq.command.ActiveMQQueue" factory="org.apache.activemq.jndi.JNDIReferenceFactory" physicalName="TestQueueTwo"/> </Context>
El resto de configuración, en spring-config.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> <!-- Recursos jndi --> <jee:jndi-lookup id="mqConnectionFactory" jndi-name="java:comp/env/jms/mqConnectionFactory" /> <jee:jndi-lookup id="testQueueOne" jndi-name="java:comp/env/jms/testQueueOne" /> <jee:jndi-lookup id="testQueueTwo" jndi-name="java:comp/env/jms/testQueueTwo" /> <!-- Clase que recibe los mensajes --> <bean id="testMessageListener" class="papidal.TestMessageListener"> <property name="testMessageSender" ref ="testMessageSender" /> </bean> <bean id="poiMessageListenerContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="connectionFactory" ref ="mqConnectionFactory" /> <property name="destination" ref ="testQueueOne"/> <property name="messageListener" ref ="testMessageListener"/> <property name="concurrentConsumers" value="2" /> </bean> <!-- Clase que envía los mensajes --> <bean id="testMessageSender" class="papidal.TestMessageSender"> <property name="jmsTemplate" ref="jmsTemplate"/> <property name="testQueue" ref="testQueueTwo"/> </bean> <bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate"> <property name="connectionFactory" ref="mqConnectionFactory" /> </bean> </beans>
En el web.xml, indicáis dónde tenemos la configuración de spring:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <!-- Fichero de configuración de spring --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/config/spring-config.xml </param-value> </context-param> <!-- Cargamos el contexto de Spring --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> </web-app>
La clase que escucha en la cola 1, los mensaje que llegan:
package papidal; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.TextMessage; import org.apache.log4j.Logger; public class TestMessageListener implements MessageListener { private TestMessageSender messageSender_i; private static final Logger logger_c = Logger.getLogger(TestMessageListener.class); //Escucha los mensajes public void onMessage(Message message) { logger_c.info("Recibo mensaje de la cola [" + message +"]"); if (message instanceof TextMessage) { try { String msgText = ((TextMessage) message).getText(); logger_c.debug("Mensaje recibido: " + msgText); messageSender_i.sendMessage(msgText); } catch (JMSException jmsEx_p) { String errMsg = "Error obteniendo el mensaje"; logger_c.error(errMsg, jmsEx_p); } } else { String errMsg = "El mensaje no es del tipo TextMessage"; logger_c.error(errMsg); throw new RuntimeException(errMsg); } } public void setTestMessageSender(TestMessageSender messageSender_p) { this.messageSender_i = messageSender_p; } }
La clase que usamos para enviar los mensajes recibidos hacia la cola 2:
package papidal; import javax.jms.JMSException; import javax.jms.Queue; import org.apache.log4j.Logger; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service; // Enviamos mensajes a una cola @Service public class TestMessageSender { private JmsTemplate jmsTemplate_i; private Queue testQueue_i; private static final Logger logger_c = Logger .getLogger(TestMessageSender.class); // Envio del mensaje public void sendMessage(String message_p) throws JMSException { logger_c.debug("Ponemos el mensaje en la cola[" + testQueue_i.toString() + "] Mensaje[" + message_p + "]"); jmsTemplate_i.convertAndSend(testQueue_i, message_p); } public void setJmsTemplate(JmsTemplate tmpl) { this.jmsTemplate_i = tmpl; } public void setTestQueue(Queue queue) { this.testQueue_i = queue; } }
"D:\apache-activemq-5.7.0\bin\activemq.bat"
Para administrar:
Simplemente con levantar el servidor ya veremos la cola 1 (en mi caso, un Tomcat 7) con 2 consumidores.
Le damos a "send To", metemos cualquier cosa (típicamente un xml) y vemos que por la
consola de Tomcat hemos recibido el mensaje correctamente, que hemos enviado
por la cola 1 y que lo hemos a su vez enviado a la cola 2.
En el ActiveMQ podemos
verlo también (fijaros en la columna de encolados y desencolados. Como la cola
para enviar mensajes es la dos, y nosotros escuchamos sólo la 1, la cola 2 no
tiene consumidores activos ya que sólo la usamos para enviar mensajes. Si algún
modulo quiere escucharla, no hay problema).
Acordaros de darle a F5 para
refrescar la pantalla ;)
A partir de aquí, se pueden definir canales, jugar con el xpath para aceptar o descartar mensajes en función del identificador del envoltorio, usar jaxb para hacer marshall/unmarshall, definir el encoding del parseo de xml a clases Java y viceversa, ...
Hola,
ResponderEliminarBuen ejemplo. Un consejo, cambia los estilos de la página porque no se entiende bien el código y hay que hacer demasiado esfuerzo para leerlo, eso afecta la cantidad de usuarios que acceda a tu página.
Saludo