Spock测试与Artemis嵌入式服务器:如何在地址上配置消费队列?
解决方案
1. 配置Artemis兼容VirtualTopic路由规则
ActiveMQ Artemis需显式配置地址规则以兼容Classic的VirtualTopic行为,在application.yml中添加嵌入式代理核心配置:
spring: artemis: embedded: config: core: address-settings: # 匹配所有VirtualTopic前缀的地址 'VirtualTopic.*': default-routing-type: MULTICAST routing-types: [MULTICAST, ANYCAST] addresses: VirtualTopic.audit.events: routing-types: [MULTICAST] queues: VirtualTopic.audit.events::junit: address: VirtualTopic.audit.events routing-type: MULTICAST
此配置让VirtualTopic.audit.events地址以MULTICAST路由运行,队列VirtualTopic.audit.events::junit绑定到该地址的MULTICAST路由,确保主题消息能路由到消费队列。
2. 修正JMS目标解析逻辑
原DynamicDestinationResolver未区分主题发送与队列接收场景,修改如下:
@Bean public DynamicDestinationResolver dynamicDestinationResolver() { return new DynamicDestinationResolver() { @Override public Destination resolveDestinationName(Session session, String destinationName, boolean pubSubDomain) throws JMSException { // VirtualTopic开头且无::后缀的是主题,按发布订阅处理 if (destinationName.startsWith("VirtualTopic.") && !destinationName.contains("::")) { return super.resolveDestinationName(session, destinationName, true); } // 带::后缀的是消费队列,按点对点处理 if (destinationName.contains("::")) { return super.resolveDestinationName(session, destinationName, false); } return super.resolveDestinationName(session, destinationName, pubSubDomain); } }; }
3. 拆分JMS模板配置
全局设置spring.jms.pub-sub-domain=true会导致队列接收也按主题处理,需拆分发送和接收模板:
@Bean public JmsMessagingTemplate jmsTopicMessagingTemplate(ConnectionFactory connectionFactory) { JmsMessagingTemplate template = new JmsMessagingTemplate(connectionFactory); template.setPubSubDomain(true); // 专门用于发送主题消息 return template; } @Bean public JmsMessagingTemplate jmsQueueMessagingTemplate(ConnectionFactory connectionFactory) { JmsMessagingTemplate template = new JmsMessagingTemplate(connectionFactory); template.setPubSubDomain(false); // 专门用于接收队列消息 return template; }
测试中发送用jmsTopicMessagingTemplate,接收用jmsQueueMessagingTemplate。
4. 启用OpenWire协议(兼容旧客户端)
为支持WebLogic等使用OpenWire的旧客户端,在application.yml添加协议配置:
spring: artemis: embedded: config: core: acceptors: openwire-acceptor: tcp://localhost:61616?protocols=OPENWIRE
5. 优化测试代码可靠性
移除不稳定的sleep(1000),改用CountDownLatch实现同步等待:
def 'notify a success status event'() { given: CountDownLatch latch = new CountDownLatch(1) StatusEvent receivedEvent = null jmsQueueMessagingTemplate.listen(config.statusEventDestination + "::junit", Message.class) { message -> receivedEvent = jsonService.fromString((String) message.payload, StatusEvent.class) latch.countDown() } when: Message message = buildMessage(false) service.notify(message.headers, message.headers.getId(), StatusType.AUDIT_STORE_SUCCESS) latch.await(10, TimeUnit.SECONDS) then: receivedEvent != null receivedEvent.id == message.headers.getId().toString() receivedEvent.statusDate != null receivedEvent.status == StatusType.AUDIT_STORE_SUCCESS receivedEvent.event == StatusEvent.CCNCSI_EVENT_STATUS receivedEvent.error == null }
内容的提问来源于stack exchange,提问作者Themikebe
相关产品推荐
相关产品推荐

