Apache ActiveMQ Artemis is a combined feature-set of ActiveMQ/HornetQ/Apollo. It provides a non blocking architecture for an outstanding performance. So in the tutorial, JavaSampleApproach will guide how to
create JMS producer/consumer by SpringBoot Artemis applications.
Related posts:
– Spring JMS with ActiveMQ – JMS Consumer and JMS Producer | Spring Boot
– Spring Apache Kafka Application with SpringBoot Auto-Configuration
– Spring RabbitMQ Producer/Consumer applications with SpringBoot
I. Technologies
– Java 8
– Maven 3.6.1
– Spring Tool Suite: Version 3.8.4.RELEASE
– Spring Boot: 1.5.4.RELEASE
– Apache Artemis 2.1.0
II. SpringBoot Artemis
1. SpringBoot Auto-configure
When having artemis-jms-client
Artemis on the classpath, Spring Boot can auto-configure a ConnectionFactory.
We use spring.artemis.*
to control Artemis configuration:
1 2 3 4 5 |
spring.artemis.mode=native spring.artemis.host=localhost spring.artemis.port=61616 spring.artemis.user=jsa spring.artemis.password=12345 |
spring.artemis.mode
has 2 mode: {NATIVE, EMBEDDED}:
– NATIVE: Connect to a broker using the native Artemis protocol.
– EMBEDDED: Embed the broker in the application.
2. Sending/Receiving messages
For sending message, we use: JmsTemplate jmsTemplate
1 2 3 4 5 6 7 8 9 10 11 12 |
@Component public class ArtemisProducer { @Autowired JmsTemplate jmsTemplate; @Value("${jms.queue.destination}") String destinationQueue; public void send(String msg){ jmsTemplate.convertAndSend(destinationQueue, msg); } } |
For recieved messages, we use: @JmsListener
:
1 2 3 4 5 6 7 8 |
@Component public class ArtemisConsumer { @JmsListener(destination = "${jms.queue.destination}") public void receive(String msg){ System.out.println("Recieved Message: " + msg); } } |
3. SpringBoot Artemis applications
In the tutorial, we create 2 SpringBoot Artemis projects for producer/consumer:
III. Practice
We create 2 SpringBoot projects {SpringBootArtemisProducer, SpringBootArtemisConsumer}:
Step to do:
– Create SpringBoot projects
– Implement Artemis Producer/Consumer
– Deploy Artemis
– Run and check results
1. Create SpringBoot projects
Using SpringToolSuite, we create 2 SpringBoot projects: {SpringBootArtemisProducer, SpringBootArtemisConsumer}.
For SpringBootArtemisProducer, add dependencies:
1 2 3 4 5 6 7 8 9 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-artemis</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> |
For SpringBootArtemisConsumer, add dependencies:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>artemis-jms-client</artifactId> <version>2.1.0</version> </dependency> |
Why we don’t use artemis-jms-client 2.1.0
for SpringBootArtemisProducer?
-> At the time we do the tutorial, artemis-jms-client 2.1.0
has a bug for jmsTemplate.convertAndSend
with exception:
1 2 3 4 5 6 |
java.lang.NoSuchMethodError: org.apache.activemq.artemis.api.core.client.ClientMessage.setUserID(Ljava/lang/Object;)Lorg/apache/activemq/artemis/api/core/Message; at org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer.doSendx(ActiveMQMessageProducer.java:469) ~[artemis-jms-client-2.1.0.jar:2.1.0] at org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer.send(ActiveMQMessageProducer.java:191) ~[artemis-jms-client-2.1.0.jar:2.1.0] at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:626) ~[spring-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE] at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:597) ~[spring-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE] at org.springframework.jms.core.JmsTemplate$4.doInJms(JmsTemplate.java:574) ~[spring-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE] |
Why we don’t use spring-boot-starter-artemis - version 1.5.6
(that includes artemis-jms-client 1.5.5
) for Artemis consumer @JmsListener
?
-> Because we got an bug:
1 |
Setup of JMS message listener invoker failed for destination 'JSA-QUEUE' - trying to recover. Cause: AMQ119019: Queue already exists JSA-QUEUE |
Note:
1 2 3 4 5 |
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-artemis</artifactId> <version>1.5.6.RELEASE</version> </dependency> |
EQUAL TO:
1 2 3 4 5 6 7 8 9 10 |
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-jms</artifactId> <version>4.3.10.RELEASE</version> </dependency> <dependency> <groupId>org.apache.activemq</groupId> <artifactId>artemis-jms-client</artifactId> <version>1.5.5</version> </dependency> |
2. Implement Artemis Producer/Consumer
For above projects, open application.properties files, add Artemis configuration:
1 2 3 4 5 6 |
spring.artemis.mode=native spring.artemis.host=localhost spring.artemis.port=61616 spring.artemis.user=jsa spring.artemis.password=12345 jms.queue.destination=JSA-QUEUE |
2.1 Implement Artemis Producer
Using JmsTemplate
to implement ArtemisProducer
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package com.javasampleapproach.artemis.jms; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Component; @Component public class ArtemisProducer { @Autowired JmsTemplate jmsTemplate; @Value("${jms.queue.destination}") String destinationQueue; public void send(String msg){ jmsTemplate.convertAndSend(destinationQueue, msg); } } |
– Create a simple RestApi for sending messages:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
package com.javasampleapproach.artemis.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.javasampleapproach.artemis.jms.ArtemisProducer; @RestController public class RestApiController { @Autowired ArtemisProducer producer; @RequestMapping(value="/produce") public String produce(@RequestParam("msg")String msg){ producer.send(msg); return "Done"; } } |
2.2 Implement Artemis Consumer
Using @JmsListener
to implement ArtemisConsumer:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
package com.javasampleapproach.artemis.jms; import org.springframework.jms.annotation.JmsListener; import org.springframework.stereotype.Component; @Component public class ArtemisConsumer { @JmsListener(destination = "${jms.queue.destination}") public void receive(String msg){ System.out.println("Recieved Message: " + msg); } } |
3. Deploy Artemis
Go to Artemis download page. Download Artemis 2.1.0:
Extract apache-artemis-2.1.0-bin.zip, we have:
Create an Artemis broker jsa-springboot-broker by commandline:
C:\apache-artemis-2.1.0\bin>artemis create "C:\dev\jsa-springboot-broker"
:
Run the Artemis broker by commnandline: "C:\dev\jsa-springboot-broker\bin\artemis" run
4. Run and check results
Build and Run above SpringBoot projects with commandlines: {mvn clean install
, mvn spring-boot:run
}
– Make a sending request: http://localhost:8080/produce?msg=JSA - SpringBoot Artemis, Hello World!
. Results:
-> Use jconsole.exe, monitor message added in Artemis queue:
-> Artemis Consumer’s Logs:
1 |
Recieved Message: JSA - SpringBoot Artemis, Hello World! |
hello.., great tutorial. Can you do complete end to end series on spring boot, spring data, angular with microservices
It will be really helpful
Can you please guide how can we integrate springboot application with artemis cluster.
Hello Bhushan,
In application.properies file, just modify the Artemis Connection configuration as below:
Regards,
JSA
Thanks JavaSampleApproach for your replay, I am using static discovery server, so there is no groupAddress or groupPort.
I have created project with native setting, my consumer class is receiving messages if i send from server but from producer its not receiving messages.