2

I'm researching switching to WildFly 10 and, subsequently, Artemis. I've set up a simple Spring Websocket project, as described here: https://spring.io/guides/gs/messaging-stomp-websocket/. The meat of the project are WebSocketConfig:

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
    config.enableStompBrokerRelay("/queue/", "/topic/");
    config.setApplicationDestinationPrefixes("/app");
}

And controller:

@MessageMapping("/hello")
@SendTo("/topic/greetings")
public Greeting greeting(HelloMessage message) throws Exception {
    return new Greeting("Hello, " + message.getName() + "!");
}

This works like a charm as it is with ActiveMQ, no additional configuration required on the broker side.

Knowing that Artemis requires either a pre-created destination, or a specific mention of automatic queue creation, i added this to my broker.xml:

<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>
</address-settings>

However, this didn't work as i expected and broker still refused to create /queue/greetings. So, i've researched a bit more and found that Artemis, in fact, likes queues to be names with jms.queue.* prefix. I renamed my queue to jms.queue.greetings and made the following changes to Spring code: Configuration:

...
config.setPathMatcher(new AntPathMatcher("."));
...

Controller:

...
@SendTo("jms.queue.greetings")
...

To my understanding, this should have forced my controller to send messages to this queue. Broker liked this change and finally created the queue, but Spring controller on the other hand did not - no messages appear in jms.queue.greetings.

I can force my way around the issue by making code less pretty, subscribing to required queues with some hand-made injected services, but that way i will loose Spring sockJS magic - Artemis (unlike RabbitMQ) doesn't seem to provide http endpoint to Stomp, and connecting to ws:// will just lead to CORS errors. No inbuilt CORS support either, it seems.

I will appreciate any thoughts on how i might overcome this issue.

EDIT: My JS looks like this:

var ws = new SockJS('/hello');
client = Stomp.over(ws);
...
client.connect(login, passcode, function(frame) {
    client.debug("connected to Stomp");
    ....
    client.subscribe('jms.queue.greetings', function(message) {
        ...
    });
});
...
client.send("jms.queue.greetings", {}, JSON.stringify({ 'name': text }));
...
Justin Bertram
  • 29,372
  • 4
  • 21
  • 43

1 Answers1

1

Based on your update

When sending to jms.queue.greeting you are telling spring to redirect your request directly to Broker without entering any controller if you want to send message to controller and then it forward it to broker you should send per your configuration to app.greeting and that controller will forward it back to jms.queue.greeting

if you are using . as delimiter use it in all annotation

check this diagram and it will show you the difference between sending to /app and /queue or /topic the first go into controller the second is only redirect

I am using the below and i am able to send and receive message

//Configuration
    @Override
        public void configureMessageBroker(MessageBrokerRegistry config) {
            config.enableStompBrokerRelay("jms.topic", "jms.queue")
            .setRelayHost("192.168.65.24")
            .setRelayPort(5445)
            .setSystemLogin("root")
            .setSystemPasscode("XXXXX")
            .setClientLogin("root")
            .setClientPasscode("XXXXX");
            config.setApplicationDestinationPrefixes("app");
            //config.setUserDestinationPrefix("user"); 
            config.setPathMatcher(new AntPathMatcher("."));
        }

        @Override
        public void registerStompEndpoints(StompEndpointRegistry registry) {
            registry.addEndpoint("/stomp");
        }


//Subscribtion
     stompClient.subscribe('jms.queue.call', function(greeting){
                        showGreeting(JSON.parse(greeting.body).name);
                    });

//Sending
    stompClient.send("jms.queue.call", {}, JSON.stringify({ 'name': message }));

One issue still pending with artemis is the /user/ where DefaultUserDestinationResolver is hardcoded with / for user parsing .

Shahbour
  • 1,323
  • 1
  • 16
  • 42
  • Do you have some sort of a controller on the Spring side? I see in your snippet that you have "app" prefix set up, but it's not used anywhere. – Dmitry Korchemkin Mar 14 '16 at 12:08
  • Thanks for the advice, Shahbour, the diagram really helped. – Dmitry Korchemkin Mar 14 '16 at 14:38
  • Sorry for writing 3rd comment in a row, but i've faced another issue. Spring doesn't want to map message to an endpoint when i use `antPathMatcher(".")`. Doesn't matter if i use `"/app"` and `"/app/hello"` prefix and endpoint or `"app"` and `"app.hello"`, Spring doesn't call the controller at all in this case. Without `AntPathMatcher` controller is called, but obviously cannot send to `"jms.queue.greetings"` Any idea what can i do? – Dmitry Korchemkin Mar 14 '16 at 14:51
  • Create github project and share it – Shahbour Mar 14 '16 at 14:52
  • Nevermind, i figured it out thanks to this page http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html. Turns out i should have bee using "/app/hello" in JS and just map my controller to "hello". Thank you again for your help. – Dmitry Korchemkin Mar 14 '16 at 15:23