sameer
sameer

Reputation: 31

stomp disconnects its processing twice in channel interceptor and SimpleBrokerMessageHandler

I have modified to implement channel interceptor in spring-websocket-portfolio sample application (https://github.com/rstoyanchev/spring-websocket-portfolio). whenever the client disconnects, channel interceptor is processed twice. I have similar implementation in my production application. As it is being invoked twice so it has unwanted result for the 2nd invocation. I had put work around for the time being. But wondering why my channel interceptor is invoked twice? Any help would be highly appreciated.

modified items:
WebSocketConfig.java:

@Override
public void configureClientInboundChannel(ChannelRegistration registration)    {
    registration.setInterceptors(channelInterceptor());
 }

@Bean
public ChannelInterceptor channelInterceptor() {
    return new ChannelInterceptor();
}

ChannelInterceptor :

package org.springframework.samples.portfolio.config;

import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.messaging.support.ChannelInterceptorAdapter;

public class ChannelInterceptor extends ChannelInterceptorAdapter {

@Override
public void postSend(Message<?> message, MessageChannel channel, boolean   sent) {
    StompHeaderAccessor sha = StompHeaderAccessor.wrap(message);
    System.out.println(sha.getCommand() + "  " + sha);
    switch (sha.getCommand()) {
        case CONNECT: {
            System.out.println("connected:"+sha.getSessionId());
             break;
        }
        case DISCONNECT: {
            System.out.println("disconnected:"+sha.getSessionId());
            break;
        }
        default:
            System.out.println("default:"+sha.getCommand());
            break;
      }
  }
}

logs:

**disconnected**:9k1hvln6
**disconnected**:9k1hvln6

Upvotes: 3

Views: 2228

Answers (2)

Rossen Stoyanchev
Rossen Stoyanchev

Reputation: 5018

Generally a DISCONNECT frame comes the client side, is processed in the StompSubProtocolHandler, and is then propagated to the broker. However, a connection can also be closed or lost without a DISCONNECT frame. Regardless of how a connection is closed, the StompSubProtocolMessageHandler generates a DISCONNECT frame. So there is some redundancy on the server side to ensure the broker is aware the client connection is gone.

As Sergi mentioned you can either subscribe to listen for SessionDisconnectEvent (of which there should be only one) and other AbstractSubProtocol events or ensure your code is idempotent.

Upvotes: 2

Sergi Almar
Sergi Almar

Reputation: 8414

Disconnect events may happen more than once for the same session, your interceptor should be idempotent and ignore duplicate events.

You may also consider using application events (SessionConnectEvent, SessionDisconnectEvent...) instead of a channel interceptor. Here's an example of an idempotent event listener: https://github.com/salmar/spring-websocket-chat/blob/master/src/main/java/com/sergialmar/wschat/event/PresenceEventListener.java

Upvotes: 2

Related Questions