mpilone / hazelcastmq

Messaging, STOMP server, Camel component, and JMS provider for Hazelcast
Apache License 2.0
81 stars 15 forks source link

Feature request, support for stomp version 1.1 #2

Closed properotech closed 10 years ago

properotech commented 10 years ago

Hello!

Thank you for a very interesting library!

I'm trying to use your libraries together with spring4, websockets, sockjs and stompjs, which unfortunately do not support stomp version 1.2, which is what hazelcastmqstomp dictates, not sure if it is technical requirement in your code?... the differences between 1.2 and 1.1 are slim - (accordingly to the stomp documentation 1.2 is almost 100% backwards compatible).

It would be really nice if your amazing hazelcastmq with stomp support would become compatible with stomp1.1 , mening it could be used with spring4s "new" support for web-socket messaging using sockjs.js and stomp.js which only supports the '1.0', and '1.1' protocols.

I have almost got it to work, with really simple configurations using spring4 WebSocketMessageBrokerConfig :) would be amazing using your hazelcastmqstompserver instead of an external broker.

Here is how easy it is to set up websockets with spring4: http://spring.io/guides/gs/messaging-stomp-websocket/

what do you think?

mpilone commented 10 years ago

I think it should be doable. The actual code change is just a single line but I'll have to read through the 1.1 spec to make sure I'm handling everything properly. I'll take a look soon.

mpilone commented 10 years ago

The latest 1.1.0-SNAPSHOT (in the develop branch and in my snapshots repo) has STOMP 1.1 support enabled in HazelcastMQ Stomp. I grabbed the Spring example and got it working with HzMq with a few modifications.

First, write a config class to create the HzMq Stomp instance as a Spring bean:

@Configuration
public class HzMqConfig {

  @Bean(destroyMethod = "shutdown")
  public HazelcastMQStompInstance hazelcastMqStomp() {

    // Hazelcast Instance
    Config hzConfig = new Config();
    HazelcastInstance hzInstance = Hazelcast.newHazelcastInstance(hzConfig);

    // HazelcastMQ Instance
    HazelcastMQConfig mqConfig = new HazelcastMQConfig(hzInstance);
    HazelcastMQInstance mqInstance = HazelcastMQ.
        newHazelcastMQInstance(mqConfig);

    // HazelcastMQ Stomp Instance
    HazelcastMQStompConfig mqStompConfig =
        new HazelcastMQStompConfig(mqInstance);
    mqStompConfig.setPort(8035);
    return HazelcastMQStomp.newHazelcastMQStompInstance(mqStompConfig);
  }
}

Next, modify the included WebSocketConfig to relay STOMP frames to HzMq:

@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
  config.enableStompBrokerRelay("/topic").setRelayHost("localhost").
    setRelayPort(8035).setVirtualHost("spring-demo");

  // config.enableSimpleBroker("/topic");
  config.setApplicationDestinationPrefixes("/app");
}

Finally, add the reactor-net (required by Spring) and HzMq dependencies:

<dependency>
  <groupId>org.projectreactor</groupId>
  <artifactId>reactor-net</artifactId>
</dependency>
<dependency>
  <groupId>org.mpilone.hazelcastmq</groupId>
  <artifactId>hazelcastmq-stomp</artifactId>
  <version>1.1.0-SNAPSHOT</version>
</dependency>

I'm no expert in Spring Boot or WebSockets but this seems to do the job. I was able to broadcast a greeting across multiple browsers.

Let me know how it works out for you.

jerrinot commented 10 years ago

awesome work Mike!

properotech commented 10 years ago

Yes it works! Nice work, thank your for a fast response in this matter.

I actually got everything working yesterday with 1.0.0 by implementing a org.springframework.messaging.support.ChannelInterceptorAdapter that adds the version 1.2 to all incoming messages - I know Its a hack but at least it worked, and showed there where no direct technical protocol obstacles. (My plan today was actually to fork your code and implement the changes you now already have done in the snapshot).

Both direct messaging using springs @SendToUser (which is the queue messaging) and the @SendTo (which is the publish to topic messaging) worked fine. (When sending to only one user/websession there is more going on since the framework translates the destinations to a user specific queue).

Also using an instance of springs SimpMessagingTemplate and the convertAndSendToUser(...) method worked fine, which gives the capabilities to send a message to specific user form basically anywhere in the application (as long as one know their Principal username - (which one often have in any case to identify the user with)).

I will be testing this out further today, and be doing some performance testings on it also. Maybe i will need to add some hooks at the stomp DISCONNECT event to clean up the users specific websession iqueue's created in hazelcast, or maybe hazelcast can invalidate those after some time automatically after nonactivity (im no hazelcast expert).

Maybe there is room for a hazelcastmq-spring artifact? Designed for this use case, since using a clustered in-memory message broker in a spring websockets with stomp webapplication could be beneficial to a huge number of projects and people! - think about it - everyone wants clustering, everyone wants websockets, a lot of people want to use spring, but! not everyone wants the hassle to set up a clustered external message borker like ActiveMQ or start to learn the play framework or vertx.

cheers!

mpilone commented 10 years ago

Glad it worked out for you. STOMP over websockets to HzMq is definitely an interesting use case and very different from how I'm using it now. I'll have to read up on Spring 4's new(-ish) messaging stuff and see if there are some better integration points. I already had a hazelcastmq-spring in mind because I want to make HzMq available as a transaction resource so you could easily link DB and HzMq transactions via a Spring transaction manager.