0

One of the use cases of project is when user connects to the server with userId the session should be maintained. If any server events happen (a record added or in any business logic) we should notify the connected user.

I'm trying to persist the websocket session in hazelcast so that it will be available to all the application instances if any instance goes down.

import com.fasterxml.jackson.databind.ObjectMapper; import com.hazelcast.config.Config; import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance;

import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
import  org.springframework.session.web.socket.events.SessionConnectEvent;

@Component
public class SocketHandler extends TextWebSocketHandler {

    List<WebSocketSession> sessions = new CopyOnWriteArrayList<>();
    private static final Object LOCK = new Object();
    private Map<String, WebSocketSession> userSessionMap = new HashMap<>();
    //Session s = null;

    Config cfg = new Config();
    HazelcastInstance instance = Hazelcast.newHazelcastInstance(cfg);
    Map<String, SessionConnectEvent> sharedData = instance.getMap("shared");

    @Override
    @SuppressWarnings("unchecked")
    public void handleTextMessage(WebSocketSession session, TextMessage message)
            throws InterruptedException, IOException {
        Map<String, String> value = new ObjectMapper().readValue(message.getPayload(), Map.class);
        String userId = value.get("userId");

        synchronized(LOCK) {
            if(!sharedData.containsKey(userId)) {          
                sharedData.put(userId, session);
            }
        }
        session.sendMessage(new TextMessage("Hello " + value.get("userId") + ". Your Trip Notifications appear below !"));
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
    }

During run time below exception occur.

com.hazelcast.nio.serialization.HazelcastSerializationException: There is no suitable serializer for class org.springframework.web.socket.adapter.standard.StandardWebSocketSession
    at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:218)
    at com.hazelcast.nio.serialization.SerializationServiceImpl.toData(SerializationServiceImpl.java:203)
    at com.hazelcast.map.impl.AbstractMapServiceContextSupport.toData(AbstractMapServiceContextSupport.java:68)
    at com.hazelcast.map.impl.DefaultMapServiceContext.toData(DefaultMapServiceContext.java:28)
    at com.hazelcast.map.impl.proxy.MapProxySupport.toData(MapProxySupport.java:1042)
    at com.hazelcast.map.impl.proxy.MapProxyImpl.put(MapProxyImpl.java:101)
    at com.hazelcast.map.impl.proxy.MapProxyImpl.put(MapProxyImpl.java:89)
    at com.ecab.driver.socket.SocketHandler.handleTextMessage(SocketHandler.java:43)
    at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
    at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
    at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
    at org.springframework.web.socket.handler.ExceptionWebSocketHandlerDecorator.handleMessage(ExceptionWebSocketHandlerDecorator.java:58)
mperle
  • 3,342
  • 8
  • 20
  • 34

1 Answers1

2

First, WebSocketSession is not Serializable, hence your error.

Then, from a conceptual point-of-view, it's not possible to persist a stateful connection (e.g. FTP, WebSocket, etc.). What you should do it persist all connection parameters, and then re-open the connection from another instance if the connection went down on a node.

Nicolas
  • 1,155
  • 6
  • 17
  • Could you guide to achieve the same with any working examples for a websocket. – mperle May 23 '20 at 12:56
  • Sorry, but in my answer, I tried to explain you why it cannot work, and why you shouldn't do it. Create a web socket connection settings class that is `Serializable`, create an instance of such a class with the relevant values, this is the object you can store. – Nicolas May 23 '20 at 16:29