Search code examples
jmsspring-integrationspring-integration-dslactivemq-artemis

Sending message with Spring Integration to ActiveMQ Artemis topic


Goal

I would like to send a message to a topic which I will process later with a client applications. For this purpose I use Spring Boot and Spring Integration Java DSL with its JMS module. As a message broker I use a native ActiveMQ Artemis.


Here is my setup

DemoApplication.java

@SpringBootApplication
public class DemoApplication {

    private static final Logger logger = LoggerFactory.getLogger(DemoApplication.class);

    public interface StarGate {
        void sendHello(String helloText);
    }

    @Autowired
    private ConnectionFactory connectionFactory;

    @Bean
    public IntegrationFlow mainFlow() {
        return IntegrationFlows
                .from(StarGate.class)
                .handle(Jms.outboundAdapter(connectionFactory)
                        .configureJmsTemplate(jmsTemplateSpec -> jmsTemplateSpec
                                .deliveryPersistent(true)
                                .pubSubDomain(true)
                                .sessionTransacted(true)
                                .sessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE)
                                .explicitQosEnabled(true)
                        )
                        .destination(new ActiveMQTopic("wormhole")))
                .get();
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
        StarGate stargate = context.getBean(StarGate.class);
        stargate.sendHello("Jaffa, kree!");
        logger.info("Hello message sent.");
    }

}

application.properties

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

spring.jms.pub-sub-domain=true
spring.jms.template.delivery-mode=persistent
spring.jms.template.qos-enabled=true
spring.jms.listener.acknowledge-mode=client

logging.level.org.springframework=INFO

build.gradle (the important parts)

springBootVersion = '2.0.2.RELEASE'
dependencies {
    compile('org.springframework.boot:spring-boot-starter-artemis')
    compile('org.springframework.boot:spring-boot-starter-integration')
    compile('org.springframework.integration:spring-integration-jms')
    testCompile('org.springframework.boot:spring-boot-starter-test')
}

As an ActiveMQ Artemis server I use the vromero/artemis (2.6.0) docker image with default configuration.


The Problem

On the producer side the message appears to be successfully sent but on the message broker side the message is missing. The address is created but the queue is missing.

ActiveMq Artemic Console Addresses ActiveMq Artemic Console Queues

The name of the topic will be dynamic in the future, so I'm not allowed to create the topic manually in broker.xml. I rely on the automatic-queue-creation feature of Artemis.

Why message sending is not working in this case?


Nerd note: I'm aware that Star Gates are basically connected via wormholes in a point-to-point manner but for the sake of the question let's ignore this fact.


Solution

  • When a message is sent to a topic and auto-creation is enabled for both addresses and queues only the address will be created and not a queue. If a queue were created automatically and the message was put into the queue that would violate the semantics of a topic. A subscription queue on a topic address is only created in response to a subscriber. Therefore, you need a subscriber on the topic before you send the message otherwise the message will be dropped (in accordance with topic semantics).