ActiveMQ - spring integrated jms

Keywords: Spring Apache xml Session

Preface

This article will realize the integration of spring and activemq, mainly demonstrating how to realize the point-to-point and publish-subscribe communication model, and how to send persistent messages and achieve persistent subscription. For an introduction to persistent messages and persistent subscriptions, please refer to:< ActiveMQ - Persistent Messages and Subscriptions for Persistent Themes>.

Drivers get on the bus

Recall that to receive and send messages, you need the following components: connection factory, destination, producer, consumer and message. Yes, spring integration activemq also requires these components.

Connecting factories
spring has established its own connection management class to better manage connections. The original JMS connection factory is included in the connection management class in a combined way. The operation of creating connections is performed by the original JMS connection factory. spring's connection management class has two main implementations: SingleConnectionFactory and ChaingConnectionFactory.

Single Connection Factory: All requests to create connections return the same connection, and the returned connection cannot be close d.

Caching Connection Factory: It inherits the features of Single Connection Factory and adds caching capabilities that can cache Session, Message Producer and Message Consumer.

&lt;!--Configure Connection Factory--&gt;
&lt;bean id="connectionFactory"
      class="org.springframework.jms.connection.CachingConnectionFactory"&gt;
    &lt;property name="sessionCacheSize" value="10"/&gt;
    &lt;property name="targetConnectionFactory"&gt;
        &lt;bean class="org.apache.activemq.ActiveMQConnectionFactory"&gt;
            &lt;!-- MQ address --&gt;
            &lt;!--
                 &lt;property name="userName" value="admin"/&gt;
                 &lt;property name="password" value="123456"/&gt;
                 &lt;property name="brokerURL" value="tcp://192.168.88.18:61616"/&gt;
             --&gt;
            &lt;property name="brokerURL" value="tcp://127.0.0.1:61616"/&gt;
            &lt;!-- Whether to send asynchronously --&gt;
            &lt;property name="useAsyncSend" value="true"/&gt;
        &lt;/bean&gt;
    &lt;/property&gt;
&lt;/bean&gt;

Destination destination

Configure the destination, where you configure a queue and a topic, and give them a name, which is retrieved from the configuration file.

    &lt;!--Configuration queue--&gt;
    &lt;bean id="activeMQQueue" class="org.apache.activemq.command.ActiveMQQueue"&gt;
        &lt;constructor-arg value="${queue.name}"/&gt;
    &lt;/bean&gt;

    &lt;!--Configuration theme--&gt;
    &lt;bean id="activeMQTopic" class="org.apache.activemq.command.ActiveMQTopic"&gt;
        &lt;constructor-arg value="${topic.name}"/&gt;
    &lt;/bean&gt;

Message producer
spring defines templates for message producers, which configure the destination of the message delivered by the producer and the persistence of the message.

    &lt;!-- **************Configuring message producers************* --&gt;
    &lt;!--Point-to-point model--&gt;
    &lt;bean id="queueJmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
        &lt;constructor-arg ref="connectionFactory"/&gt;
        &lt;!--Message persistence--&gt;
        &lt;property name="deliveryPersistent" value="true"/&gt;
        &lt;property name="defaultDestination" ref="activeMQQueue"/&gt;
        &lt;property name="pubSubDomain" value="false"/&gt;
    &lt;/bean&gt;

    &lt;!--Release/Subscription model--&gt;
    &lt;bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
        &lt;constructor-arg ref="connectionFactory"/&gt;
        &lt;!--Message persistence--&gt;
        &lt;property name="deliveryPersistent" value="true"/&gt;
        &lt;!--Destination--&gt;
        &lt;property name="defaultDestination" ref="activeMQTopic"/&gt;
        &lt;!--Subscription model --&gt;
        &lt;property name="pubSubDomain" value="true"/&gt;
    &lt;/bean&gt;

News consumers
Previously, to use persistent subscribers, an ID must be assigned to the connection and a name must be assigned to the subscriber. The combination of client_id and subcriber name must determine the only subscriber. In order to use persistent subscriptions, an additional connection factory is created and an ID is assigned to the connection.

&lt;!--Configure Connection Factory--&gt;
    &lt;bean id="consumerConnectionFactory"
          class="org.springframework.jms.connection.CachingConnectionFactory"&gt;
        &lt;property name="sessionCacheSize" value="10"/&gt;
        &lt;property name="targetConnectionFactory"&gt;
            &lt;bean class="org.apache.activemq.ActiveMQConnectionFactory"&gt;
                &lt;!-- MQ address --&gt;
                &lt;!--
                     &lt;property name="userName" value="admin"/&gt;
                     &lt;property name="password" value="123456"/&gt;
                     &lt;property name="brokerURL" value="tcp://192.168.88.18:61616"/&gt;
                 --&gt;
                &lt;property name="brokerURL" value="tcp://127.0.0.1:61616"/&gt;
                &lt;property name="useAsyncSend" value="true"/&gt;
                &lt;!-- to connection distribution ID --&gt;
                &lt;property name="clientID" value="client_id"/&gt;
            &lt;/bean&gt;
        &lt;/property&gt;
    &lt;/bean&gt;

With connections, consumers also need to specify message receivers to listen for and process messages.

public class MyQueueMessageListener implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            TextMessage textMessage = (TextMessage) message;
            System.out.println("MyQueueMessageListener Received the message:" + textMessage.getText());
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

Sprjms provides a MessageListener Container interface to manage connections, consumers, destinations, and message receipts. spring provides two implementation classes, SimpleMessageListenerContainer and DefaultMessageListenerContainer.

SimpleMessageListener Container, which creates a session and Consumer consumer from the beginning, registers the listener using the standard JMS MessageConsumer.setMessageListener() method to let the JMS provider call the callback function of the listener. It does not dynamically adapt to runtime needs and participate in external transaction management. In terms of compatibility, it is very close to the independent JMS specification, but generally incompatible with the JMS limitations of Java EE.

Compared with SimpleMessageListener Container, DefaultMessageListener Container dynamically adapts to runtime needs and can participate in external transaction management. It balances low requirements for JMS providers, advanced functions such as transaction participation and compatibility with Java EE environments. In general, DefaultMessageListener Container is used.

      &lt;bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
        &lt;property name="connectionFactory" ref="consumerConnectionFactory"/&gt;
        &lt;!--Destination name, consistent with the previous destination configuration--&gt;
        &lt;property name="destinationName" value="${queue.name}"/&gt;
        &lt;!--Automatic confirmation--&gt;
        &lt;property name="sessionAcknowledgeMode" value="1"/&gt;
        &lt;!--Point-to-point model--&gt;
        &lt;property name="pubSubDomain" value="false"/&gt;
        &lt;!--MessageListener--&gt;
        &lt;property name="messageListener" ref="myQueueMessageListener"/&gt;
    &lt;/bean&gt;
    &lt;bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
        &lt;property name="connectionFactory" ref="consumerConnectionFactory"/&gt;
        &lt;!--Destination name, consistent with the previous destination configuration--&gt;
        &lt;property name="destinationName" value="${topic.name}"/&gt;
        &lt;!--Automatic confirmation--&gt;
        &lt;property name="sessionAcknowledgeMode" value="1"/&gt;
        &lt;!--Subscription model--&gt;
        &lt;property name="pubSubDomain" value="true"/&gt;
        &lt;!--Persistent Subscription Name--&gt;
        &lt;property name="durableSubscriptionName" value="durable_sub_name"/&gt;
        &lt;!--durable subscription--&gt;
        &lt;property name="subscriptionDurable" value="true"/&gt;
        &lt;!--MessageListener--&gt;
        &lt;property name="messageListener" ref="myQueueMessageListener"/&gt;
    &lt;/bean&gt;

All configuration files are given below:

  • spring-context.xml

    &lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"&gt;
    &lt;bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"&gt;
        &lt;property name="location"&gt;
            &lt;value&gt;classpath:activemq.properties&lt;/value&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
    &lt;/beans&gt;
  • spring-activemq-producer.xml

    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
    &lt;beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.2.xsd"&gt;
    
    &lt;!--Configure Connection Factory--&gt;
    &lt;bean id="producerConnectionFactory"
          class="org.springframework.jms.connection.CachingConnectionFactory"&gt;
        &lt;property name="sessionCacheSize" value="10"/&gt;
        &lt;property name="targetConnectionFactory"&gt;
            &lt;bean class="org.apache.activemq.ActiveMQConnectionFactory"&gt;
                &lt;!-- MQ address --&gt;
                &lt;!--
                     &lt;property name="userName" value="admin"/&gt;
                     &lt;property name="password" value="123456"/&gt;
                     &lt;property name="brokerURL" value="tcp://192.168.88.18:61616"/&gt;
                 --&gt;
                &lt;property name="brokerURL" value="tcp://127.0.0.1:61616"/&gt;
                &lt;!-- Whether to send asynchronously --&gt;
                &lt;property name="useAsyncSend" value="true"/&gt;
            &lt;/bean&gt;
        &lt;/property&gt;
    &lt;/bean&gt;
    
    &lt;!-- **************Configuring message producers************* --&gt;
    &lt;!--Point-to-point model--&gt;
    &lt;bean id="queueJmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
        &lt;constructor-arg ref="producerConnectionFactory"/&gt;
        &lt;!--Message persistence--&gt;
        &lt;property name="deliveryPersistent" value="true"/&gt;
        &lt;property name="defaultDestination" ref="activeMQQueue"/&gt;
        &lt;property name="pubSubDomain" value="false"/&gt;
    &lt;/bean&gt;
    
    &lt;!--Release/Subscription model--&gt;
    &lt;bean id="topicJmsTemplate" class="org.springframework.jms.core.JmsTemplate"&gt;
        &lt;constructor-arg ref="producerConnectionFactory"/&gt;
        &lt;!--Message persistence--&gt;
        &lt;property name="deliveryPersistent" value="true"/&gt;
        &lt;!--Destination--&gt;
        &lt;property name="defaultDestination" ref="activeMQTopic"/&gt;
        &lt;!--Subscription model --&gt;
        &lt;property name="pubSubDomain" value="true"/&gt;
    &lt;/bean&gt;
    
    &lt;!--Configuration queue--&gt;
    &lt;bean id="activeMQQueue" class="org.apache.activemq.command.ActiveMQQueue"&gt;
        &lt;constructor-arg value="${queue.name}"/&gt;
    &lt;/bean&gt;
    
    &lt;!--Configuration theme--&gt;
    &lt;bean id="activeMQTopic" class="org.apache.activemq.command.ActiveMQTopic"&gt;
        &lt;constructor-arg value="${topic.name}"/&gt;
    &lt;/bean&gt;
    &lt;/beans&gt;
  • spring-activemq-consumer.xml
    &lt;!--Configure Connection Factory--&gt;
    &lt;bean id="consumerConnectionFactory"
          class="org.springframework.jms.connection.CachingConnectionFactory"&gt;
        &lt;property name="sessionCacheSize" value="10"/&gt;
        &lt;property name="targetConnectionFactory"&gt;
            &lt;bean class="org.apache.activemq.ActiveMQConnectionFactory"&gt;
                &lt;!-- MQ address --&gt;
                &lt;!--
                     &lt;property name="userName" value="admin"/&gt;
                     &lt;property name="password" value="123456"/&gt;
                     &lt;property name="brokerURL" value="tcp://192.168.88.18:61616"/&gt;
                 --&gt;
                &lt;property name="brokerURL" value="tcp://127.0.0.1:61616"/&gt;
                &lt;!-- Whether to send asynchronously --&gt;
                &lt;property name="useAsyncSend" value="true"/&gt;
                &lt;property name="clientID" value="client_id"/&gt;
            &lt;/bean&gt;
        &lt;/property&gt;
    &lt;/bean&gt;

    &lt;!--*******Here are some of the relevant consumer configurations bean*******--&gt;

    &lt;!--messages receiving bean--&gt;
    &lt;bean id="myQueueMessageListener"
          class="com.github.thinwonton.activemq.MyQueueMessageListener"/&gt;
    &lt;bean id="myTopicMessageListener"
          class="com.github.thinwonton.activemq.MyTopicMessageListener"/&gt;

    &lt;bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
        &lt;property name="connectionFactory" ref="consumerConnectionFactory"/&gt;
        &lt;!--Destination name, consistent with the previous destination configuration--&gt;
        &lt;property name="destinationName" value="${queue.name}"/&gt;
        &lt;!--Automatic confirmation--&gt;
        &lt;property name="sessionAcknowledgeMode" value="1"/&gt;
        &lt;!--Point-to-point model--&gt;
        &lt;property name="pubSubDomain" value="false"/&gt;
        &lt;!--MessageListener--&gt;
        &lt;property name="messageListener" ref="myQueueMessageListener"/&gt;
    &lt;/bean&gt;
    &lt;bean class="org.springframework.jms.listener.DefaultMessageListenerContainer"&gt;
        &lt;property name="connectionFactory" ref="consumerConnectionFactory"/&gt;
        &lt;!--Destination name, consistent with the previous destination configuration--&gt;
        &lt;property name="destinationName" value="${topic.name}"/&gt;
        &lt;!--Automatic confirmation--&gt;
        &lt;property name="sessionAcknowledgeMode" value="1"/&gt;
        &lt;!--Subscription model--&gt;
        &lt;property name="pubSubDomain" value="true"/&gt;
        &lt;!--Persistent Subscription Name--&gt;
        &lt;property name="durableSubscriptionName" value="durable_sub_name"/&gt;
        &lt;!--durable subscription--&gt;
        &lt;property name="subscriptionDurable" value="true"/&gt;
        &lt;!--MessageListener--&gt;
        &lt;property name="messageListener" ref="myQueueMessageListener"/&gt;
    &lt;/bean&gt;

&lt;/beans&gt;

Posted by dazz_club on Thu, 04 Jul 2019 14:31:59 -0700