I have a very simple Spring Boot 2.7.6 ActiveMQ Artemis app which listens for messages.
package broker.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.apache.activemq.broker.BrokerService;
import org.springframework.jms.annotation.JmsListener;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public BrokerService broker() throws Exception {
BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61616");
broker.setPersistent(false);
broker.start();
return broker;
}
@JmsListener(destination = "foo")
public void listen(String in) {
System.out.println(in);
}
}
Then I have another Spring Boot app which produces messages and sends them to the broker address.
package broker.producer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.support.destination.JndiDestinationResolver;
import org.springframework.stereotype.Service;
@Service
public class JmsProducer {
@Value("${spring.artemis.broker-url}")
private String brokerUrl;
@Value("${spring.jms.template.default-destination}")
private String defaultDestination;
Logger log = LoggerFactory.getLogger(JmsProducer.class);
@Bean
public ActiveMQConnectionFactory activeMQConnectionFactory() {
log.info("BrokerUrl: {}", brokerUrl);
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(brokerUrl);
return activeMQConnectionFactory;
}
@Bean
public JndiDestinationResolver jndiDestinationResolver() {
return new JndiDestinationResolver();
}
@Bean
public JmsTemplate jmsTemplate() {
JmsTemplate template = new JmsTemplate();
template.setConnectionFactory(activeMQConnectionFactory());
template.setPubSubDomain(false); // false for a Queue, true for a Topic
template.setDefaultDestinationName(defaultDestination);
return template;
}
public void send(String message) {
JmsTemplate jmsTemplate = jmsTemplate();
log.info("Sending message='{}'", message);
jmsTemplate.convertAndSend(message);
log.info("Sent message='{}'", message);
}
}
With this simple application.properties
for both apps.
spring.artemis.mode=EMBEDDED
spring.artemis.broker-url=tcp://localhost:61616
spring.artemis.user=admin
spring.artemis.password=secret
spring.artemis.embedded.enabled=true
spring.jms.template.default-destination=my-queue-1
Then I start each of the apps and try calling send
method and I keep getting this error from the producer app.
2024-01-15 15:50:28.462 ERROR 1012 --- [-netty-threads)] org.apache.activemq.artemis.core.client : AMQ214013: Failed to decode packet
java.lang.IllegalArgumentException: AMQ219032: Invalid type: 1
at org.apache.activemq.artemis.core.protocol.core.impl.PacketDecoder.decode(PacketDecoder.java:499) ~[artemis-core-client-2.19.1.jar:2.19.1]
Consumer app shows this error message:
2024-01-15 15:50:28.464 WARN 986 --- [0.1:57714@61616] o.a.a.b.TransportConnection.Transport : Transport Connection to: tcp://127.0.0.1:57714 failed: Unknown data type: 77
The problem is that your consumer app is starting an embedded instance of ActiveMQ Classic. See this method:
@Bean
public BrokerService broker() throws Exception {
BrokerService broker = new BrokerService();
broker.addConnector("tcp://localhost:61616");
broker.setPersistent(false);
broker.start();
return broker;
}
Then your producer app is using the ActiveMQ Artemis JMS client implementation (i.e. org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
) to connect and send a message. This client uses the "core" protocol which ActiveMQ Classic doesn't understand.
Your consumer app needs to start an embedded instance of ActiveMQ Artemis instead of ActiveMQ Classic. Spring itself should be doing this for you, but it may not be since you're starting your own already.