Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Partial messages with SockJS in Spring-Websockets 4.2

I am using Spring-Websockets 4.2 with SockJS.

Since the messages received by clients can be quite large, I would like to use partial messages. My subclass of TextWebSocketHandler does override supportsPartialMessages to return true. However, since the SockJsWebSocketHandler that is created by Spring does not support partial messages, I still get an error code=1009, reason=The decoded text message was too big for the output buffer and the endpoint does not support partial messages.

As a workaround, I've increased the buffer size to 1 MB as described here, but since I have to support quite a large number of clients (~2000 at the same time), this requires way too much memory.

Is there any way to use partial messages with SockJS?

like image 275
Jan Avatar asked Sep 11 '25 11:09

Jan


1 Answers

In my case, my tomcat server work with TextWebSocketHandler.
Before doing this, you need to check this, supportsPartialMessages.

First of all, override supportsPartialMessages() as below.

//This value set as true in my properties file. Just for test. actually you don't need this.
@Value("#{config['server.supportsPartialMessages']}")
private boolean supportsPartialMessages;

//If you need to handle partial message, should return true.
@Override
public boolean supportsPartialMessages() {
    return supportsPartialMessages;     
}

And then I add "messageRoom" attribute to store partial message to each websocket session when connection is established.

@Override
public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    super.afterConnectionEstablished(session);

    //I think this is easier to keep each message and each client.
    session.getAttributes().put("messageRoom", new StringBuilder(session.getTextMessageSizeLimit()));
}

When you get message from client, do this.

@Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
    super.handleTextMessage(session, message);

    StringBuilder sbTemp = (StringBuilder)session.getAttributes().get("messageRoom");

    //isLast() will tell you this is last chunk or not.
    if(message.isLast() == false) {     
        sbTemp.append(Payload);

    }else {
        if(sbTemp.length() != 0) {          
            sbTemp.append(Payload);     

            this.logger.info(session.getRemoteAddress() + ":RECEIVE_TO[CLIENT][PARTIAL][" + sbTemp.length() + "]:" + sbTemp.toString());
            doYourWork(session, sbTemp.toString());
            //Release memory would be nice.
            sbTemp.setLength(0);
            sbTemp.trimToSize();

        }else {         
            this.logger.info(session.getRemoteAddress() + ":RECEIVE_TO[CLIENT][WHOLE]:" + message.getPayload());
            doYourWork(session, Payload);
        }
    }
}

This is done a few years ago, so I can't remember where I got this. But I still appreciate to them.

like image 157
jornathan Avatar answered Sep 15 '25 10:09

jornathan