我需要从ActiveMQ队列中使用JMS消息并将其发布到Azure Service Bus主题。我在这个项目中使用了Spring Boot,并使用Apache qpid通过AMQP协议连接Service Bus。
我面临的问题是,在将消息发布到Service Bus Topic期间消耗来自ActiveMQ的消息后,如果由于任何原因发生异常,我将无法在ActiveMQ中保留消息。我希望ActiveMQ保留消息,直到我能够在Service Bus中发布消息。我尝试在侦听器容器工厂中使用确认作为Session.CLIENT_ACKNOWLEDGE,但在异常的某处,它返回成功,导致ActiveMQ丢弃消息。但是,ActiveMQ能够重试发送7次,但之后只丢弃消息。
以下是我的代码详细信息。 我必须使用2个配置类连接ActiveMQ和Service Bus,如下所示。
@Configuration
@EnableJms
public class RecevierConfig {
private final Logger logger = LoggerFactory.getLogger(RecevierConfig.class);
@Value("${activemq.host}")
private String activemqHost;
@Value("${activemq.protocol}")
private String activemqProtocol;
@Value("${activemq.port}")
private String activemqPort;
@Bean
public ActiveMQConnectionFactory activeMQConnectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory();
logger.info("Broker URL : "+activemqProtocol+"://"+activemqHost+":"+activemqPort);
activeMQConnectionFactory.setBrokerURL(activemqProtocol+"://"+activemqHost+":"+activemqPort);
return activeMQConnectionFactory;
}
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(activeMQConnectionFactory());
factory.setConcurrency("3-10");
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setErrorHandler(new DefaultErrorHandler());
return factory;
}
@Bean
public QueueReceiver receiver() {
return new QueueReceiver();
}
}
下面是为Service Bus连接创建ConnectionFactory和jmsTemplate以发布消息。
@Configuration
public class MessagingConfig {
@Value("${spring.application.name}")
private String clientId;
@Bean
@Primary
public ConnectionFactory jmsConnectionFactory(MessageStoreDetails details) throws UnsupportedEncodingException {
JmsConnectionFactory jmsConnectionFactory = new JmsConnectionFactory(details.getSBUrlString());
jmsConnectionFactory.setUsername(details.getUsername());
jmsConnectionFactory.setPassword(details.getPassword());
jmsConnectionFactory.setClientID(clientId);
// jmsConnectionFactory.setReceiveLocalOnly(true);
return new CachingConnectionFactory(jmsConnectionFactory);
}
@Bean
public JmsTemplate jmsTemplate(ConnectionFactory jmsConnectionFactory) {
JmsTemplate returnValue = new JmsTemplate();
returnValue.setConnectionFactory(jmsConnectionFactory);
return returnValue;
}
}
以下是QueueReceiver从ActiveMQ接收消息的代码
@Service
public class QueueReceiver {
private final Logger logger = LoggerFactory.getLogger(QueueReceiver.class);
@Autowired
private TopicPublisher topicPublisher;
@JmsListener(destination = "${activemq.queue}")
public void receiveMessage(Message message) {
try {
logger.info("*****Received message from ActiveMQ queue : " + message.getJMSMessageID());
topicPublisher.sendMessage(message);
message.acknowledge();
} catch (Exception e) {
//logger.error(e.toString());
throw new MessageProcessingException(e.toString());
}
}
}
下面是发布消息的类
@Service
public class TopicPublisher {
private final Logger logger = LoggerFactory.getLogger(TopicPublisher.class);
@Value("${servicebus.topic}")
private String topic;
@Autowired
private JmsTemplate jmsTemplate;
public void sendMessage(javax.jms.Message message) throws Exception {
logger.info("#### Sending message to Service Bus Topic : "+ topic +" Message ID: "+ message.getJMSMessageID());
jmsTemplate.convertAndSend(topic, message);
logger.info("**** Message Sent to Service Bus Topic : "+ topic +" Message ID: "+ message.getJMSMessageID());
}
}