Eu tenho um aplicativo Spring Boot 2.7.6 ActiveMQ Artemis muito simples que escuta mensagens.
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);
}
}
Então eu tenho outro aplicativo Spring Boot que produz mensagens e as envia para o endereço do corretor.
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);
}
}
Com isso simples application.properties
para ambos os aplicativos.
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
Então eu inicio cada um dos aplicativos e tento chamar send
o método e continuo recebendo esse erro do aplicativo produtor.
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]
O aplicativo consumidor mostra esta mensagem de erro:
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
O problema é que seu aplicativo consumidor está iniciando uma instância incorporada do ActiveMQ Classic. Veja este método:
Em seguida, seu aplicativo produtor está usando a implementação do cliente ActiveMQ Artemis JMS (ou seja,
org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
) para se conectar e enviar uma mensagem. Este cliente usa o protocolo "principal" que o ActiveMQ Classic não entende.Seu aplicativo consumidor precisa iniciar uma instância incorporada do ActiveMQ Artemis em vez do ActiveMQ Classic. O próprio Spring deveria estar fazendo isso por você, mas pode não estar, já que você já está começando o seu próprio.