Search code examples
javaspring-bootspring-jmsactivemq-artemis

How to create Session Factory when sending async messages via ActiveMQ Artemis in Spring Boot?


I'm trying to send simple message to a topic from sender Spring Boot app to a receiver Spring Boot app. But I keep getting two exceptions.

First exception occurs in receiver Spring Boot app:

javax.jms.JMSException: Failed to create session factory
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:882) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:299) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:294) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:410) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:350) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.getConnection(SingleConnectionFactory.java:328) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:243) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.support.JmsAccessor.createConnection(JmsAccessor.java:196) ~[spring-jms-5.3.18.jar:5.3.18]

A few seconds later the following exception occurs in sender app:

org.apache.activemq.artemis.api.core.ActiveMQConnectionTimedOutException: AMQ219013: Timed out waiting to receive cluster topology. Group:null
    at org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl.createSessionFactory(ServerLocatorImpl.java:748) ~[artemis-core-client-2.19.1.jar:2.19.1]
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnectionInternal(ActiveMQConnectionFactory.java:880) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:299) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory.createConnection(ActiveMQConnectionFactory.java:294) ~[artemis-jms-client-2.19.1.jar:2.19.1]
    at org.springframework.jms.connection.SingleConnectionFactory.doCreateConnection(SingleConnectionFactory.java:410) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.initConnection(SingleConnectionFactory.java:350) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.getConnection(SingleConnectionFactory.java:328) ~[spring-jms-5.3.18.jar:5.3.18]
    at org.springframework.jms.connection.SingleConnectionFactory.createConnection(SingleConnectionFactory.java:243) ~[spring-jms-5.3.18.jar:5.3.18]

I'm following a Udemy course on Spring Boot microservices, where chapters 13 and 14 are dedicated to JMS messaging so, I have pretty much the same config except version of Spring Boot, mine is 2.6.6 and instructor's is 2.1.x or something like that. I have to keep 2.6.6 because some other stuff in my project.

I did manage to start Active MQ server via Docker, like so:

C:\Users\Miljan>docker run -it --rm  -p 8161:8161 -p 61616:61616 vromero/activemq-artemis

Before running an image, I had to download image, I can see server is running:

enter image description here

Also, I can login into console (username: artemis; password: simetraehcapa;):

enter image description here

Other configuration in sender app:

@EnableAsync
@EnableScheduling
@Configuration
public class AsyncConfig {

    public static final String EXECUTOR = "SchedulerExecutor";

    @Bean(name = EXECUTOR)
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(2);
        executor.setQueueCapacity(50);
        executor.setThreadNamePrefix(EXECUTOR + "-");
        executor.initialize();
        return executor;
    }
}

and

@Configuration
public class JmsConfig {

    public static final String QUEUE = "queue";

    @Bean // Serialize message content to json using TextMessage
    public MessageConverter jacksonJmsMessageConverter(ObjectMapper objectMapper) {
        MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
        converter.setTargetType(MessageType.TEXT);
        converter.setTypeIdPropertyName("_type");
        converter.setObjectMapper(objectMapper);
        return converter;
    }
}

and

spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=8161
spring.artemis.user=artemis
spring.artemis.password=simetraehcapa

And finally, how I actually send a message is via simple GET request (http://localhost:8080/send):

@GetMapping("/send")
public void sendMessage(){
    Student s = new Student("MIKE");
    this.jmsTemplate.convertAndSend(JmsConfig.QUEUE, s);
}

And listener class:

@Component
@EnableJms
public class Listener {

    @Autowired
    private JmsTemplate jmsTemplate;

    @JmsListener(destination = "queue")
    public void listen(Student student){
        System.out.println(student);
    }
}

So my questions are:

  1. How to configure Session Factory?
  2. Do I miss some other config which I'm not aware of?

Solution

  • I believe the problem is this line in your configuration:

    spring.artemis.port=8161
    

    This pointing to the HTTP port used by the embedded web server in ActiveMQ Artemis. This isn't suitable for JMS clients. You should be using:

    spring.artemis.port=61616