24

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?

Community
  • 1
  • 1
Jan
  • 241
  • 2
  • 6
  • Were you able to solve this. I am also facing the same issue and haven't been able to figure out a solution? Also the numbers mentioned in `container.setMaxTextMessageBufferSize(16384)`, is it in bits, bytes kbs or what? – BiJ May 16 '17 at 09:00
  • No, unfortunately not. We ended up implementing the partial messaging ourselves by chunking at the sender and reassembling at the receiver. The setMaxTextMessageBufferSize is in bytes AFAIK. – Jan May 23 '17 at 15:25
  • Could you use a sticky session-like load balancer to split the messages? It almost sounds like you need to implement a reactive stream or use a proper scale out messaging queue outside of regular sockets to handle your messages. – Dr.Knowitall Jul 17 '17 at 15:31
  • @Jan Can you share some details how you did this? Did you use a `WebSocketHandlerDecorator` or something more application level? What about the client? – Michiel Haisma May 08 '18 at 23:35
  • I don't have access to the code anymore, but if I remember correctly, I ended up handling it all on the application layer. Something like wrapping the whole message in a JSON object, splitting it manually into 1MB chunks and then buffering on the receiver side until the final '}' arrives. – Jan May 10 '18 at 12:24

1 Answers1

1

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.

jornathan
  • 646
  • 5
  • 13