I am trying to write a test to make sure my Spring Boot application is able to receive messages from an address after migrating from ActiveMQ "Classic" to ActiveMQ Artemis. As this is a migration from ActiveMQ "Classic" some topic/queue names remain as VirtualTopic... What I am trying to achieve is a publish/subscribe scenario where a message sent on VirtualTopic.audit.events would be received by VirtualTopic.audit.events::junit or any other queue with that address. This is what I mean by "consumer queue." Also some of our older clients (e.g. on WebLogic) still use the OpenWire protocol to connect to our broker.
I am using a jmsMessagingTemplate to send and receive messages, and I have have enabled pubSubdomain in my ConnectionFactory.
From what I can deduce in the logs, I am able to send the message on the topic, but jmsMessagingTemplate.receive(...) on a FQDN of a listening queue on that address never returns (unless spring.jms.template.receive-timeout is set).
Here is my code, and the relevant configuration:
StatusEventSpec
def 'notify a success status event'() {
when:
Message message = buildMessage(false)
service.notify(message.headers, message.headers.getId(), StatusType.AUDIT_STORE_SUCCESS)
sleep(1000)
then:
Message<String> notifyMessage = jmsMessagingTemplate.receive(config.statusEventDestination + "::junit")
notifyMessage != null
StatusEvent event = jsonService.fromString((String) notifyMessage.payload, StatusEvent.class)
event.id == message.headers.getId().toString()
event.statusDate != null
event.status == StatusType.AUDIT_STORE_SUCCESS
event.event == StatusEvent.CCNCSI_EVENT_STATUS
event.error == null
}
application.yml
ccncsi.common.statusEventDestination=VirtualTopic.audit.events
spring.jms.template.receive-timeout=10s
spring.jms.pub-sub-domain=true
I already tried the following:
- use
spring.artemis.embedded.topics=VirtualTopic.audit.events,VirtualTopic.audit.events::junit(test hangs) spring.artemis.embedded.topics=VirtualTopic.audit.eventsandspring.artemis.embedded.queues=VirtualTopic.audit.events::junitI get error message:
AMQ221080: Deploying address VirtualTopic.audit.events supporting [MULTICAST]
2023-07-05 15:43:06.837 WARN 14508 --- [ main] org.apache.activemq.artemis.core.server : AMQ222274: Failed to deploy address VirtualTopic.audit.events: AMQ229209: Can't remove routing type ANYCAST, queues exists for address: VirtualTopic.audit.events. Please delete queues before removing this routing type.
- I also tried to define a DynamicDestinationResolver bean (test hangs)
@Bean
public DynamicDestinationResolver dynamicDestinationResolver() {
return new DynamicDestinationResolver() {
@Override
public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException {
if(destinationName.contains("VirtualTopic.")) {
pubSubDomain = true;
}
return super.resolveDestinationName(session, destinationName, pubSubDomain);
}
};
}
- I also tried using
QueueConfigurationandtopicConfigurationbeans with no success
@Bean
public TopicConfiguration topicConfiguration() {
TopicConfigurationImpl topicConfiguration = new TopicConfigurationImpl();
topicConfiguration.setName(statusEventDestination);
return topicConfiguration;
}
@Bean
public QueueConfiguration queueConfiguration() {
QueueConfiguration queueConfiguration = new QueueConfiguration("junit");
queueConfiguration.setAddress(statusEventDestination);
return queueConfiguration;
}
I suspect that the listening queue on VirtualTopic.audit.events is created after (when jmsMessagingTemplate.receive(..) is called) the message is sent on the embedded broker.
What am I missing?
I finally got this sorted but I think there is a problem with the Artemis embedded server. I had to resort to create my addresses and queues manually to get the right configuration and add them to the EmbeddedServer configuration to get what I wanted instead of using
spring.artemis.embedded.queuesandspring.artemis.embedded.topicsproperties or automatic configuration.If I use either, I get the following behaviour:
My understanding is that the queue
junitis created after the message is sent toVirtualTopic.audit.events, sojmsMessagingTemplate.receive("VirtualTopics.audit.events::junit")never receives it.I worked around that by using a manual configuration of the server and setting addresses and queues before the test starts:
I also had to stop and start the server between each test,
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)did not work either.As a result I get the following logs:
and my test passes
I don't know if there is a way to do this using only the
application.yamlfile