13

I have used spring implementation of sockjs websocket server and unable to transmit message over 8KB, following is the error

2014-02-12 19:36:29,990 - org.springframework.web.socket.sockjs.transport.session.WebSocketServerSockJsSession - DEBUG - SockJS session id=35n41xel was closed, CloseStatus [code=1009, reason=The decoded text message was too big for the output buffer and the endpoint does not support partial messages]

Any Idea how can I increase the buffer size


I used following factory as spring sockjs leverages tomcat container (App is deployed in tomcat and I also debugged to confirm that it indeed uses tomcat lib)

@Bean
public WebSocketContainerFactoryBean createWebSocketContainer() {
    WebSocketContainerFactoryBean container = new WebSocketContainerFactoryBean();
    container.setMaxTextMessageBufferSize(16384);
    container.setMaxBinaryMessageBufferSize(8192);
    return container;
}

And then my URL mapping looks

@Override 
public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
    registry.addHandler(coBrowseSockJsCustomerHandler(), "/sockjs/cobrowse/customer/").withSockJS();}

Do I need to set this bean with sockjs somewhere? how does sockjs knows that it has to use this facory?

Taryn
  • 242,637
  • 56
  • 362
  • 405
cpandey05
  • 1,241
  • 2
  • 17
  • 30

5 Answers5

18

Solved it by using clue from http://docs.spring.io/spring/docs/4.0.1.RELEASE/javadoc-api/index.html?org/springframework/web/socket/sockjs/SockJsService.html -got hold of ServletServerContainerFactoryBean and set the properties, this worked

@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(32768);
    container.setMaxBinaryMessageBufferSize(32768);
    logger.info("Websocket factory returned");
    return container;
}
cpandey05
  • 1,241
  • 2
  • 17
  • 30
13

for client side:

@Bean
public static WebSocketStompClient getClient() {
    List<Transport> transports = new ArrayList<>();
    WebSocketContainer container = ContainerProvider.getWebSocketContainer();
    container.setDefaultMaxBinaryMessageBufferSize(1024 * 1024);
    container.setDefaultMaxTextMessageBufferSize(1024 * 1024);
    transports.add(new WebSocketTransport(new StandardWebSocketClient(container)));
    WebSocketClient webSocketClient = new SockJsClient(transports);
    WebSocketStompClient stompClient = new WebSocketStompClient(webSocketClient);
    stompClient.setInboundMessageSizeLimit(Integer.MAX_VALUE);
    stompClient.setMessageConverter(new MappingJackson2MessageConverter());
    return stompClient;
}

for server side:

@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(32768);
    container.setMaxBinaryMessageBufferSize(32768);
    logger.info("Websocket factory returned");
    return container;
}
gstackoverflow
  • 36,709
  • 117
  • 359
  • 710
  • What if I'm not using Spring? – Albert Hendriks Mar 25 '18 at 12:59
  • 1
    @Albert Hendriks, I don't know. Question tagged as spring related – gstackoverflow Mar 25 '18 at 13:06
  • @AlbertHendriks WebSocketContainer container = ContainerProvider.getWebSocketContainer(); container.setDefaultMaxBinaryMessageBufferSize(1024 * 1024); is not specific to Spring so it is the same for non-spring apps – Adelin Aug 07 '19 at 17:17
  • It took me days to find MY mistake in clientside code and hopefully it saves someone others day: You can find nearly the same snippet of code in the spring docs, except the three lines of code which are about the Websocket container, so i copied these three lines and inserted them before the snippet from spring. but i missed the next line, which has an important change and uses the container in `new StandardWebSocketClient(container)` as a paramater. As a result, the container gets initialized again in the empty constructor of StandardWebsocketClient with default values for message sizes. – Sunchezz Nov 26 '19 at 17:27
1

You can configure the websocket engine and increase the buffer size.

Watch out, depending on the actual size you'd like to use, remember that those messages will be buffered entirely in memory! You may want to consider using partial messages if your client supports it.

Brian Clozel
  • 56,583
  • 15
  • 167
  • 176
  • I used that to configure the engine -In my case spring sockjs is using tomcat engine, but it did not work – cpandey05 Feb 16 '14 at 16:39
  • Brian, Can you help me as how to set the container properties? In my case it's tomcat. I took a look at http://tomcat.apache.org/tomcat-7.0-doc/web-socket-howto.html as how to increase the buffer size and as suggested tried setting the servlet context initialization parameter .. But it did not work! Is there any interceptor or configuration which can be used to achieve this? – cpandey05 Feb 16 '14 at 18:43
  • This works if I pass file from client to server but doesn't if I senf file from server to client – gstackoverflow Jul 10 '17 at 12:57
1

Before you start the spring app you can set the property

System.setProperty("org.apache.tomcat.websocket.DEFAULT_BUFFER_SIZE", (1024*1024).toString()).

I've tried multiple bean configurations that didn't work but this property seems to be read in multiple places when I looked at the code. I'm sure there is some bean configuration that would have worked but if you don't want to bother trying many different ones until one works you can just set this parameter.

Piacenti
  • 1,188
  • 10
  • 9
0

Setting this in my web.xml file worked for me:

<context-param>
  <param-name>org.apache.tomcat.websocket.textBufferSize</param-name>
  <param-value>65536</param-value>
</context-param>
<context-param>
  <param-name>org.apache.tomcat.websocket.binaryBufferSize</param-name>
  <param-value>65536</param-value>
</context-param>
akenney
  • 297
  • 3
  • 9