Spring boot integrates the Topic of activeMQ. If you don't understand it, you have to understand it

Keywords: Java Session Spring Apache

Preface

Today, we share with you springboot's integration of activeMq's topic (Theme) - Publish / subscribe mode, similar to the WeChat public number. We can receive messages when we are concerned about the public. Topic needs consumers to subscribe before they can receive messages. If there is no consumer subscription, the message generated by the producers is the waste message (publish / subscribe mode, the producer produces a message, which can be consumed by multiple consumers. Consumption). This instance supports websocket, message resend and persistence
Version information: SpringBoot2.1.5 ActiveMQ 5.15.10

Consumer Engineering

Consumer engineering catalog

pom file

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency> 

yml file configuration

server
port: 8085
spring:
activemq:
broker-url: tcp://localhost:61616
user: admin
password: admin
jms:
pub-sub-domain: true
#Own theme name
myTopic: boot_actviemq_topic

Configuration class

package com.example.topic_customer.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

import javax.jms.ConnectionFactory;
import javax.jms.Topic;

/**
 * @Date 2019/11/13  10:22
 * @Desc Consumer configuration class
 */
@Configuration
public class BeanConfig {
    @Value("${myTopic}")
    private String myTopic;

    /**
     * websocket To configure
     *
     * @return
     */
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }

    @Bean
    public Topic topic() {
        return new ActiveMQTopic(myTopic);
    }

    public RedeliveryPolicy redeliveryPolicy() {
        RedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
        //Whether to increase the waiting time after each attempt to resend fails
        redeliveryPolicy.setUseExponentialBackOff(true);
        //The number of retransmissions, which is 6 by default, is set to 10 here, and - 1 means unlimited times
        redeliveryPolicy.setMaximumRedeliveries(-1);
        //Retransmission interval, default 1 ms, set to 10000 MS
        redeliveryPolicy.setInitialRedeliveryDelay(10000);
        //Indicates that there is no delay and only when useexponential backoff (true) is true
        //Wait 10000 ms after the first failure before resending and 10000 * 2 ms after the second failure
        //Double 10000 * 2 * 2 for the third time, and so on
        redeliveryPolicy.setBackOffMultiplier(2);
        //Avoid message collision
        redeliveryPolicy.setUseCollisionAvoidance(true);
        //Setting the maximum delay time of resend 360000 MS means there is no delay, only when useexponential backoff (true) is true
        redeliveryPolicy.setMaximumRedeliveryDelay(360000);
        return redeliveryPolicy;
    }

    public ConnectionFactory connectionFactory() {
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        //Set resend properties
        connectionFactory.setRedeliveryPolicy(redeliveryPolicy());
        return connectionFactory;
    }

    /**
     * JMS Listener container factory for queues
     */
    @Bean(name = "jmsTopicListener")
    public DefaultJmsListenerContainerFactory jmsTopicListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setPubSubDomain(true);
        factory.setSessionTransacted(true);
        factory.setAutoStartup(true);
        //Open persistent subscription
        factory.setSubscriptionDurable(true);
        //Reconnection interval
        factory.setRecoveryInterval(1000L);
        factory.setClientId("topic_provider:zb1");
        return factory;
    }
} 

There are two main ways to set up consumer persistence:

  1. //Open persistent subscription factory.setSubscriptionDurable(true);
    2.factory.setClientId("topic [provider: zb1"); / / this can be set at will

. topicalcustomer class

package com.example.topic_customer.customer;

import lombok.Data;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

import javax.jms.JMSException;
import javax.jms.TextMessage;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.server.ServerEndpoint;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @Date 2019/11/13  13:31
 * @Desc
 */
@Component
@ServerEndpoint("/websocket")
@Data
public class TopicCustomer {
    /**
     * Each client will have a corresponding session, and the server can send relevant messages
     */
    private javax.websocket.Session session;

    /**
     * J.U.C The thread safe class under the package is mainly used to store the corresponding webSocket connection of each client
     */
    private static CopyOnWriteArraySet<TopicCustomer> copyOnWriteArraySet = new CopyOnWriteArraySet<>();

    @OnOpen
    public void onOpen(javax.websocket.Session session) {
        this.session = session;
        copyOnWriteArraySet.add(this);
    }

    @OnClose
    public void onClose() {
        copyOnWriteArraySet.remove(this);
    }

    @OnMessage
    public void onMessage(String message) {
    }

    @OnError
    public void onError(javax.websocket.Session session, Throwable error) {
        error.printStackTrace();
    }

    @JmsListener(destination = "${myTopic}", containerFactory = "jmsTopicListener")
    public void receive(TextMessage textMessage, javax.jms.Session session) throws JMSException {
        //Traverse client
        for (TopicCustomer webSocket : copyOnWriteArraySet) {
            try {
                //Server active push
                webSocket.session.getBasicRemote().sendText(textMessage.getText());
                System.out.println("-- Receive topic Persistent message -- " + textMessage.getText());
            } catch (Exception e) {
                System.out.println("-----Test retransmission-----");
                session.rollback();// You cannot omit to use the retransmission information
            }
        }
    }
}

Startup class

package com.example.topic_customer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class TopicCustomerApplication {

    public static void main(String[] args) {
        SpringApplication.run(TopicCustomerApplication.class, args);
    }
} 

Screenshot of mq after the consumer starts successfully:

Producer Engineering

Manufacturer's engineering catalog


yml profile

server:
  port: 8084
spring:
  activemq:
    broker-url: tcp://localhost:61616
    user: admin
    password: admin
  jms:
    pub-sub-domain: true

myTopic: boot_actviemq_topic

Configuration class

package com.example.topicprovider.config;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.RedeliveryPolicy;
import org.apache.activemq.command.ActiveMQTopic;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
import org.springframework.stereotype.Component;

import javax.jms.ConnectionFactory;
import javax.jms.Topic;

/**
 * @Date 2019/11/13  10:22
 * @Desc Producer profile
 */
@Component
public class BeanConfig {
    @Value("${myTopic}")
    private String myTopic;

    public RedeliveryPolicy redeliveryPolicy(){
        RedeliveryPolicy redeliveryPolicy=   new RedeliveryPolicy();
        //Whether to increase the waiting time after each attempt to resend fails
        redeliveryPolicy.setUseExponentialBackOff(true);
        //The number of retransmissions, which is 6 by default, is set to 10 here, and - 1 means unlimited times
        redeliveryPolicy.setMaximumRedeliveries(-1);
        //Retransmission interval, default 1 ms, set to 10000 MS
        redeliveryPolicy.setInitialRedeliveryDelay(10000);
        //Indicates that there is no delay and only when useexponential backoff (true) is true
        //Wait 10000 ms after the first failure before resending and 10000 * 2 ms after the second failure
        //Double 10000 * 2 * 2 for the third time, and so on
        redeliveryPolicy.setBackOffMultiplier(2);
        //Avoid message collision
        redeliveryPolicy.setUseCollisionAvoidance(true);
        //Setting the maximum delay time of resend 360000 MS means there is no delay, only when useexponential backoff (true) is true
        redeliveryPolicy.setMaximumRedeliveryDelay(360000);
        return redeliveryPolicy;
    }

    @Bean
    public Topic topic() {
        return new ActiveMQTopic(myTopic);
    }

    public ConnectionFactory connectionFactory(){
        ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
        //Set resend properties
        connectionFactory.setRedeliveryPolicy(redeliveryPolicy());
        return connectionFactory;
    }

    /**
     * JMS Listener container factory for queues
     */
    @Bean(name = "jmsTopicListener")
    public DefaultJmsListenerContainerFactory jmsTopicListenerContainerFactory() {
        DefaultJmsListenerContainerFactory factory =
                new DefaultJmsListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory());
        factory.setPubSubDomain(true);
        factory.setSessionTransacted(true);
        factory.setAutoStartup(true);
        //Open persistent subscription
        factory.setSubscriptionDurable(true);
        //Reconnection interval
        factory.setRecoveryInterval(1000L);
        return factory;
    }
}

TopicProvider class

package com.example.topicprovider.topic_provider;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.jms.Topic;
import java.util.UUID;

/**
 * @Date 2019/11/13  10:25
 * @Desc
 */
@Component
public class TopicProvider {
    @Autowired
    private Topic topic;
    @Autowired
    private JmsTemplate jmsTemplate;

    @Scheduled(fixedDelay = 10000)
    private void produceMsg() {
        jmsTemplate.convertAndSend(topic, "Subject producers" + UUID.randomUUID().toString().substring(1, 7));
        System.out.println( jmsTemplate.getDeliveryMode());
        System.out.println("Theme producer 1");
    }
}

Startup class

package com.example.topicprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class TopicProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(TopicProviderApplication.class, args);
    }
}

Results after successful startup:

Last

Like, you can pay attention to my public address: java little melon brother sharing platform. Thank you for your support!

Posted by mashnote on Thu, 21 Nov 2019 13:02:43 -0800