2.1 getting started with ActiveMQ (introduction, JMS, installation, use)

Keywords: Session Spring Java Apache

Article directory

What is ActiveMQ

ActiveMQ is the most popular and powerful open source message produced by Apache.

ActiveMQ is a JMS Provider implementation that fully supports the JMS 1.1 and J2EE 1.4 specifications. Although it has been a long time since the JMS specification was introduced, JMS still plays a special role in today's J2EE applications.

What is JMS?

Java Message Service (JMS) application program interface is a Java platform API for message oriented middleware (MOM), which is used to send messages between two applications or distributed systems for asynchronous communication. Java message service is a platform independent API.

Object model of JMS

ConnectionFactory Connection factory
Connection Connect
Session Conversation
Destination objective
MessageProducer Producer
MessageConsumer Consumer
Message news
Broker Instance of message middleware (ActiveMQ)

Message model of JMS

Point to point (P2P) / point to point

Publish / subscribe / topic (publish / subscribe)

Message structure of JMS

Message header

Message attribute

The message property can be understood as the additional message header of the message, and the property name can be customized

Property value types: boolean, byte, int, long, float, double, String

Message body

Features of ActiveMQ

  • Support for multiple programming languages
  • Support multiple transport protocols
  • There are many ways to persist

ActiveMQ installation

Demo environment: Centos7, jdk8, activemq5.15.8
Download address: http://activemq.apache.org/activemq-5158-release.html
Or cd /tmp, then wget -c http://mirrors.shu.edu.cn/apache/activemq/5.15.8/apache-activemq-5.15.8-bin.tar.gz. If wget is not installed, you can first yum install wget.
Unzip: tar -zxvf apache-activemq-5.15.8-bin.tar.gz -C /var
Modify the directory name mv /var/apache-activemq-5.15.8/ /var/activemq/

Start:. / bin/activemq start
Stop:. / bin/activemq stop

The previous command is used to run ActiveMQ, but the best way is to start ActiveMQ as a service. Using the system service will ensure that ActiveMQ can start when the system starts.

Make system service

1. Create a systemd service file: vi /usr/lib/systemd/system/activemq.service

2. Put in content

[Unit]
Description=ActiveMQ service
After=network.target

[Service]
Type=forking
ExecStart=/var/activemq/bin/activemq start
ExecStop=/var/activemq/bin/activemq stop
User=root
Group=root
Restart=always
RestartSec=9
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=activemq


[Install]
WantedBy=multi-user.target

3. Find the directory where the Java command is located, where is Java, and fill the copy path into JAVA_HOME in the next step.

4. Set Java home in the activemq configuration file / var/activemq/bin/env

# Location of the java installation
# Specify the location of your java installation using JAVA_HOME, or specify the
# path to the "java" binary using JAVACMD
# (set JAVACMD to "auto" for automatic detection)
JAVA_HOME="/usr/local/java/jdk1.8.0_181"
JAVACMD="auto"

5. Manage the start and stop of activemq through systemctl

  • Start activemq service: systemctl start activemq
  • View service status: systemctl status activemq
  • Create software link: ln -s /usr/lib/systemd/system/activemq.service /etc/systemd/system/multi-user.target.wants/activemq.service
  • System CTL enable ActiveMQ
  • Check whether it is enabled: systemctl list unit files | grep ActiveMQ

6. Firewall configuration, Web management port is 8161 by default, communication port is 61616 by default

  • Add and restart firewall
firewall-cmd --zone=public --add-port=8161/tcp --permanent
firewall-cmd --zone=public --add-port=61616/tcp --permanent
systemctl restart firewalld.service
  • Or close the firewall directly: systemctl stop firewalld.service
  • If you are an alicloud server, you need to open the firewall port in the console.

Web management platform using ActiveMQ

ActiveMQ has its own management platform, which can be accessed by visiting http: / / service IP:8181/admin in the browser.

ActiveMQ's management page turns on identity verification by default

Account number: admin

Password: admin

Web management configuration

ActiveMQ's Web management platform is based on jetty, so you can see jetty's configuration file in / var/activemq/conf directory.

Modify the default port of the web management platform in / var/activemq/conf/jetty.xml.


Using ActiveMQ in Java

Maven uses ActiveMQ

Add dependency

<dependencies>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>activemq-all</artifactId>
            <version>5.15.8</version>
        </dependency>

        <dependency>
            <groupId>org.eclipse.paho</groupId>
            <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
            <version>1.2.0</version>
        </dependency>
    </dependencies>
/**
 * Simple producer
 */
public class Producer {
    public static void main(String[] args) {
        new ProducerThread("tcp://123.57.246.250:61616", "queue1").start();
    }

    static class ProducerThread extends Thread {
        String brokerUrl;
        String destinationUrl;

        public ProducerThread(String brokerUrl, String destinationUrl) {
            this.brokerUrl = brokerUrl;
            this.destinationUrl = destinationUrl;
        }

        @Override
        public void run() {
            ActiveMQConnectionFactory connectionFactory;
            Connection conn;
            Session session;

            try {
                // 1. Create connection factory
                connectionFactory = new ActiveMQConnectionFactory(brokerUrl);
                // 2. Create connection object md
                conn = connectionFactory.createConnection();
                conn.start();
                // 3. Create session
              	//First parameter: whether to start transaction. true: transaction is enabled, the second parameter is ignored.
								//Second parameter: only when the first parameter is false can it make sense. Response mode of the message. 1. Automatic response 2. Manual response. Automatic response means that the client will delete the message after receiving it. Receiving the message does not mean that it is used correctly. If we want to ensure that the message is consumed correctly, we need to manually.
                session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
                // 4. Create a point-to-point destination
                 Destination destination = session.createQueue(destinationUrl);
                // 5. Create producer message
                MessageProducer producer = session.createProducer(destination);
                // Set the producer's mode with two options: persistent / non persistent
                producer.setDeliveryMode(DeliveryMode.PERSISTENT);
                // 6. Create a text message
                String text = "Hello world!";
                TextMessage message = session.createTextMessage(text);
                for (int i = 0; i < 1; i++) {
                    // 7. Send message
                    producer.send(message);
                }
                // 8. Close connection
                session.close();
                conn.close();
            } catch (JMSException e) {
                e.printStackTrace();
            }
        }
    }
}
/**
 * Simple consumer
 */
// http://activemq.apache.org/consumer-features.html
public class Consumer {
    public static void main(String[] args) {
        new ConsumerThread("tcp://123.57.246.250:61616", "queue1").start();
        new ConsumerThread("tcp://123.57.246.250:61616", "queue1").start();
    }
}

class ConsumerThread extends Thread {

    String brokerUrl;
    String destinationUrl;

    public ConsumerThread(String brokerUrl, String destinationUrl) {
        this.brokerUrl = brokerUrl;
        this.destinationUrl = destinationUrl;
    }

    @Override
    public void run() {
        ActiveMQConnectionFactory connectionFactory;
        Connection conn;
        Session session;
        MessageConsumer consumer;

        try {
            // brokerURL http://activemq.apache.org/connection-configuration-uri.html
            // 1. Create connection factory
            connectionFactory = new ActiveMQConnectionFactory(this.brokerUrl);
            // 2. Create connection object
            conn = connectionFactory.createConnection();
            conn.start(); // Be sure to start
            // 3. Create session (one or more sessions can be created)
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            // 4. Create a point-to-point receive target, queue point to point
            Destination destination = session.createQueue(destinationUrl);

            // 5. Create consumer message http://activemq.apache.org/destination-options.html
            consumer = session.createConsumer(destination);

            // 6. Receive message (wait for no message)
            Message message = consumer.receive();
            if (message instanceof TextMessage) {
                System.out.println("Text message received:" + ((TextMessage) message).getText());
            } else {
                System.out.println(message);
            }

            consumer.close();
            session.close();
            conn.close();
        } catch (JMSException e) {
            e.printStackTrace();
        }
    }
}

Output: text message received: Hello world!

springboot uses ActiveMQ

  1. pom file import dependency
	<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <!--Direct use spring-boot-starter-activemq-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-activemq</artifactId>
        </dependency>
        <!-- MQTT -->
        <dependency>
            <groupId>org.springframework.integration</groupId>
            <artifactId>spring-integration-mqtt</artifactId>
        </dependency>
    </dependencies>
  1. Write configuration application.properties
spring.activemq.broker-url=tcp://123.57.246.250:61616
spring.activemq.user=admin
spring.activemq.password=admin
  1. Producer code
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplate;

    @PostConstruct
    public void init() {
        jmsTemplate.convertAndSend("queue1", "Hello Spring 4");
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}
  1. Consumer code
@SpringBootApplication
@EnableJms
public class Consumer {

    @JmsListener(destination = "queue1")
    public void receive(String message) {
        System.out.println("Message received:" + message);
    }

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

Manually configure multiple ActiveMQ

  1. A JmsConfiguration class needs to be added
@Configuration
@EnableJms
public class JmsConfiguration {

    /**
     * Connection factory
     * Configure multiple ActiveMQ to copy one method, change the method name and some parameters.
     * @param brokerUrl
     * @param userName
     * @param password
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory1(@Value("${spring.activemq.broker-url}") String brokerUrl, @Value("${spring.activemq.user}") String userName, @Value("${spring.activemq.password}") String password) {
        return new ActiveMQConnectionFactory(userName, password, brokerUrl);
    }

    /**
     * Connection factory
     *
     * @param brokerUrl
     * @param userName
     * @param password
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory2(@Value("${spring.activemq.broker-url}") String brokerUrl, @Value("${spring.activemq.user}") String userName, @Value("${spring.activemq.password}") String password) {
        return new ActiveMQConnectionFactory(userName, password, brokerUrl);
    }

    /**
     * Listening container in queue mode
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactoryQueue(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        return bean;
    }

    /**
     * topic Monitor
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsListenerContainerFactory<?> jmsListenerContainerFactoryTopic(ConnectionFactory connectionFactory) {
        DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory();
        bean.setConnectionFactory(connectionFactory);
        bean.setPubSubDomain(true);
        return bean;
    }

    /**
     * Queue template
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsTemplate jmsTemplateQueue(ConnectionFactory connectionFactory) {
        return new JmsTemplate(connectionFactory);
    }

    /**
     * Publish subscription template
     *
     * @param connectionFactory
     * @return
     */
    @Bean
    public JmsTemplate jmsTemplatePublish(ConnectionFactory connectionFactory) {
        JmsTemplate jmsTemplate = new JmsTemplate(connectionFactory);
        jmsTemplate.setPubSubDomain(true);
        return jmsTemplate;
    }

}
  1. Producer code demonstration
@SpringBootApplication
public class Producer {

    @Autowired
    private JmsTemplate jmsTemplatePublish;

    @Autowired
    private JmsTemplate jmsTemplateQueue;

    @PostConstruct
    public void send() {
        // Queue mode send
        jmsTemplatePublish.convertAndSend("topic1", "Hello Spring topic 1");

        // Publish and subscribe mode send
        jmsTemplateQueue.send("queue1", new MessageCreator() {
            @Override
            public Message createMessage(Session session) throws JMSException {
                MapMessage message = session.createMapMessage();
                message.setString("msg", "Hello Spring xxxx");
                return message;
            }
        });
    }

    public static void main(String[] args) {
        SpringApplication.run(Producer.class, args);
    }
}
  1. Consumer code demonstration
@SpringBootApplication
public class Consumer {

    @JmsListener(destination = "queue1", containerFactory = "jmsListenerContainerFactoryQueue")
    public void receiveQueue(Message message) throws JMSException {
        if (message instanceof TextMessage) {
            System.out.println("Text message received:" + ((TextMessage) message).getText());
        } else if (message instanceof ActiveMQMapMessage) {
            System.out.println("Received Map News:" + ((ActiveMQMapMessage) message).getContentMap());
        } else {
            System.out.println(message);
        }
    }

    @JmsListener(destination = "topic1", containerFactory = "jmsListenerContainerFactoryTopic")
    public void receiveTopic(String message) {
        System.out.println("Received subscription message:" + message);
    }

    public static void main(String[] args) {
        SpringApplication.run(Consumer.class, args);
    }
}
34 original articles published, 15 praised, 7387 visited
Private letter follow

Posted by shainh on Wed, 11 Mar 2020 04:22:26 -0700