Spring Boot + Stomp over WS with embedded Artemis broker“Destination is not exist”

时间:2015-12-25 09:36:14

标签: spring spring-boot stomp spring-websocket activemq-artemis

我有一个使用Stomp over Websocket进行Spring启动的示例。当我将代理注册从SimpleBrokerRegistration更改为StompBrokerRelayRegistration时,它无法正常工作。

这是我的Websocket配置:

subQuery.lessThanOrEqualTo("endDate", convertDate);
   subQuery.greaterThanOrEqualTo("createdAt", convertDate);
   subQuery.equalTo("type","free");

和ArtemisConfig:

@Configuration
@EnableWebSocketMessageBroker
@ConfigurationProperties(prefix = "spring.artemis")
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
//...
 @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        // If STOMP broker not configured, create an simple fallback
        if (!StringUtil.isEmpty(host) || port > 0) {
            config.enableStompBrokerRelay("/topic", "/queue")
                    .setRelayHost(host)
                    .setRelayPort(port);
        } else {
            config.enableSimpleBroker("/topic", "/queue");
        }
        config.setApplicationDestinationPrefixes("/app");
    }
@Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/hello")
                .withSockJS();
    }
//...
}

然后,我使用javascript连接:

  @Configuration
    @ConfigurationProperties(prefix = "spring.artemis")
    public class JmsConfig implements ArtemisConfigurationCustomizer {
        private static final String DEFAULT_TRANSPORT_PROTOCOLS = "STOMP";

        private String host;
        private int port;
        private String protocols;
    // ...
        @Override
        public void customize(org.apache.activemq.artemis.core.config.Configuration configuration) {
            host = StringUtil.hasText(host)?host:TransportConstants.DEFAULT_HOST;
            port = port > 0? port:TransportConstants.DEFAULT_PORT;
            protocols = StringUtil.hasText(protocols)?protocols:DEFAULT_TRANSPORT_PROTOCOLS;
            Set<TransportConfiguration> acceptors = configuration.getAcceptorConfigurations();
            Map<String, Object> params = new HashMap<>();
            params.put(TransportConstants.HOST_PROP_NAME, host);
            params.put(TransportConstants.PORT_PROP_NAME, port);
            params.put(TransportConstants.PROTOCOLS_PROP_NAME, protocols);
            TransportConfiguration tc = new TransportConfiguration(NettyAcceptorFactory.class.getName(), params);
            acceptors.add(tc);
        }
//...
}

它说无法找到队列/主题/问候

当我像这样使用SimpMessagingTemplate时:

var socket = new SockJS('/hello');
            stompClient = Stomp.over(socket);
            stompClient.connect('guest', 'guest', function(frame) {
                setConnected(true);
                console.log('Connected: ' + frame);
                stompClient.subscribe('/topic/greetings', function(greeting){
                    showGreeting(greeting.body);
                });
            });

它抛出一个错误:

messagingTemplate.convertAndSend("/topic/greetings", "WARN: " + warningString());

我不知道为什么它不能用作SimpleBroker。

3 个答案:

答案 0 :(得分:1)

您是否事先在Artemis broker.xml中创建了此目的地?与ActiveMQ不同,您必须这样做,或者在地址设置块中指定自动创建,如下所示:

<!--default for catch all-->
<address-setting match="#">
    <dead-letter-address>jms.queue.DLQ</dead-letter-address>
    <expiry-address>jms.queue.ExpiryQueue</expiry-address>
    <redelivery-delay>0</redelivery-delay>
    <max-size-bytes>10485760</max-size-bytes>
    <message-counter-history-day-limit>10</message-counter-history-day-limit>
    <address-full-policy>BLOCK</address-full-policy>
    <auto-create-jms-queues>true</auto-create-jms-queues>
</address-setting>

在这种情况下,将创建任何目的地。但是,这里有一个问题。定义队列时,如下所示:

<queue name="selectorQueue">
    <entry name="/queue/selectorQueue"/>
    <selector string="color='red'"/>
    <durable>true</durable>
</queue>

它实际上将遵循jms命名约定,并且实际名称为jms.queue.selectorQueue。您也可以尝试映射到该名称。

答案 1 :(得分:0)

由于我不知道的某些原因,Artemis(使用Stomp协议)似乎期望主题名称以jms.topic.开头,队列名称jms.queue.

因此,请将您的主题重命名为jms.topic.greetings,并确保您还将StompBrokerRelay配置更改为:

config.enableStompBrokerRelay("jms.topic", "jms.queue")

在此设置中,将在需要时自动创建队列/主题。

(我使用的是Artemis 1.3。)

答案 2 :(得分:0)

对于在 2021 年寻找如何使用 Spring 的 SimpMessageSendingOperations (STOMP) 和嵌入式 ActiveMQ Artemis 的人?花了半天时间,我可以告诉你。

添加以下依赖(因为目前有依赖冲突,自己找最新版本)。由于某种原因,spring 目前需要 reactor-netty,您可以尝试在没有它的情况下运行。

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-artemis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>artemis-jms-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.activemq</groupId>
            <artifactId>artemis-stomp-protocol</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-reactor-netty</artifactId>
        </dependency>

创建以下配置类。这是将嵌入式 artemis 服务器暴露给外部虚拟机连接所必需的。据我所知,默认情况下只使用虚拟机内连接,我还没有找到一种方法来利用这些与 stomp 中继。

@Configuration
public class ArenaArtemisConfiguration {

    private final ArtemisProperties artemisProperties;

    public ArenaArtemisConfiguration(ArtemisProperties artemisProperties) {
        this.artemisProperties = artemisProperties;
    }

    @Bean
    public ArtemisConfigurationCustomizer customizer() {
        return configuration -> {
            try {
                configuration.addAcceptorConfiguration(
                        "netty", "tcp://" + artemisProperties.getHost() + ":" + artemisProperties.getPort()
                );
            } catch (Exception e) {
                throw new IllegalStateException(e);
            }
        };
    }
}

将以下内容添加到您的 application.yml

spring.artemis:
  mode: embedded
  host: localhost
  port: 61616

通过中继配置一个 webSocket 消息代理(在我们的例子中是 artemis)

@Configuration
public class WebSocketConfiguration extends DelegatingWebSocketMessageBrokerConfiguration {

    private final ArtemisProperties artemisProperties;

    public WebSocketConfiguration(ArtemisProperties artemisProperties) {
        this.artemisProperties = artemisProperties;
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableStompBrokerRelay("/your-topics")
                .setRelayHost(artemisProperties.getHost())
                .setRelayPort(artemisProperties.getPort());
    }
}

其余的应该与 enableSimpleBroker 相同。