zyro23 / grails-spring-websocket

93 stars 28 forks source link

Can I create a custom handler to handle websocket handshake? #35

Closed ghost closed 8 years ago

zyro23 commented 8 years ago

you should be able to use a custom config (create-web-socket-config) and then set your handshake handler, something like:

@Override
void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/stomp").setHandshakeHandler(myCustomHandshakeHandler);
}
ghost commented 8 years ago

I'm using Grails 2.4.3 and command (create-web-socket-config) not works for me. How can I do this on my Grails version? Also I found, that in your plugin exists class WebSocketConfig.groovy. As I understand, I need to override this class. But when I override it, it ignores during application start. Is it required additional configuration? Thanks.

zyro23 commented 8 years ago

then make sure to stick to the 1.2.x branch: https://github.com/zyro23/grails-spring-websocket/tree/1.2.x

If you need more sophisticated configuration options, currently the way to go would be using the useCustomConfig setting and heading over to the Spring docs/apis/samples covering the configuration of websockets/messaging. You can of course use the plugin's WebSocketConfig for orientation. It uses @EnableWebSocketMessageBroker and implements WebSocketMessageBrokerConfigurer

that means:

@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    void configureMessageBroker(MessageBrokerRegistry mbr) {
        mbr.enableSimpleBroker "/queue", "/topic"
        mbr.setApplicationDestinationPrefixes "/app"
        mbr.setUserDestinationPrefix "/user/"
    }

    @Override
    void registerStompEndpoints(StompEndpointRegistry ser) {
        ser.addEndpoint("/stomp").setHandshakeHandler(myCustomHandshakeHandler).withSockJS()
    }

}
beans = {
    webSocketConfig my.package.WebSocketConfig

    grailsSimpAnnotationMethodMessageHandler(
        GrailsSimpAnnotationMethodMessageHandler,
        ref("clientInboundChannel"),
        ref("clientOutboundChannel"),
        ref("brokerMessagingTemplate")
    ) {
        destinationPrefixes = ["/app"]
    }
}

and of course, upgrade to grails-3.1.x as soon as possible :)

ghost commented 8 years ago

Thank you!!! It really works for me. I have the last question. The root of my problem is next: I run my Grails app on AWS instances behind the ELB. ELB not supports websocket protocol and transport switches to use XHR Streaming. The problem is, that during handshake the new SockJS session was created, for example, on instances A, but second xhr request ELB directs to instance B, where SockJS session with the same ID is not created and I get next network error: https://my.server/stomp/340/xm75x5k1/xhr_streaming - status 200 https://my.server/stomp/340/xm75x5k1/xhr_send - status 404 My variant to solve this is 1) handle event, where new SockJS session creates (you helped me to do that) 2) send event to other AWS instances to programmatically create SockJS session. Sending event is not a problem. The problem is, that I can't realize, how can I programmatically create SockJS session. My question is, do you know how to do that or maybe you know another workaround to fix such problem? Thank you in advance for any ideas!!!

zyro23 commented 8 years ago

hmm.. im not really into aws/elb. however, looks like it should be possible to enable sticky sessions with elb so that all requests from a certain user session hit the same instance, thus preventing the issue you described (http://docs.aws.amazon.com/ElasticLoadBalancing/latest/DeveloperGuide/elb-sticky-sessions.html). closing this one as the remaining problem is not really related to this plugin - hope thats ok.

ghost commented 8 years ago

Yes, thanks for help!

kastork commented 8 years ago

@strateg29 ELB sticky sessions should solve the instance routing part as zyro23 said. I think making the ELB route TCP rather than HTTP will avoid the sockjs fallback completely. Problem there is you have to do your own SSL termination at the instance instead of at the load balancer.