Reputation: 1953
I am implementing Spring WebSocket into our Spring MVC web application. However I am running into message over size limits when I am trying to send a really big message to an endpoint.
I am getting the following error:
message:The 'content-length' header 68718 exceeds the configured message buffer size limit 65536
14:49:11,506 ERROR [org.springframework.web.socket.messaging.StompSubProtocolHandler] (http-localhost/127.0.0.1:8080-4) Failed to parse TextMessage payload=[13684590},..], byteCount=16384, last=true] in session vlsxdeol. Sending STOMP ERROR to client.: org.springframework.messaging.simp.stomp.StompConversionException: The 'content-length' header 68718 exceeds the configured message buffer size limit 65536
at org.springframework.messaging.simp.stomp.BufferingStompDecoder.checkBufferLimits(BufferingStompDecoder.java:148) [spring-messaging-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.messaging.simp.stomp.BufferingStompDecoder.decode(BufferingStompDecoder.java:124) [spring-messaging-4.1.6.RELEASE.jar:4.1.6.RELEASE]
Here is my configuration:
@MessageMapping("/user/sockettest" )
@SendTo("/topic/sockettestresult")
public String sockAdd(ListId[] listIds) {
..
SecurityContextHolder.getContext().getAuthentication().getPrincipal();
return stringRet;
}
The xml config looks like the following:
<websocket:stomp-endpoint path="/user/sockettest">
<websocket:sockjs/>
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic"/>
<websocket:message-converters register-defaults="false">
<bean id="mappingJackson2MessageConverter" class="org.springframework.messaging.converter.MappingJackson2MessageConverter">
<property name="objectMapper" ref="objectMapper"></property>
</bean>
</websocket:message-converters>
</websocket:message-broker>
The client side code looks like this:
function versionFiles() {
stompClient.send("/testbrkr/user/sockettest", {}, JSON.stringify(listIds));
}
Can you let me know what would be a good work-around?
Answer: If you know what would be the maximum size limit
<websocket:transport message-size="75536" send-buffer-size="75536"></websocket:transport>
I am looking on how to do partial messaging, will post it here as soon as I find out and get it working
Upvotes: 9
Views: 25236
Reputation: 11
I've faced the same issue and solved by configuring WebSocketTransportRegistration and ServletServerContainerFactoryBean.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketTransportRegistration;
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/echo").setAllowedOrigins("*");
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(2048 * 2048);
registration.setSendBufferSizeLimit(2048 * 2048);
registration.setSendTimeLimit(2048 * 2048);
}
@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean factoryBean = new ServletServerContainerFactoryBean();
factoryBean.setMaxTextMessageBufferSize(2048 * 2048);
factoryBean.setMaxBinaryMessageBufferSize(2048 * 2048);
factoryBean.setMaxSessionIdleTimeout(2048L * 2048L);
factoryBean.setAsyncSendTimeout(2048L * 2048L);
return factoryBean;
}
}
Upvotes: 1
Reputation: 1
Consider <websocket:transport message-size=""/>
option for the <websocket:message-broker>
definition:
Configure the maximum size for an incoming sub-protocol message. For example a STOMP message may be received as multiple WebSocket messages or multiple HTTP POST requests when SockJS fallback options are in use.
The same can be achieved in annotation configuration using
WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration)
implementation and with the setMessageSizeLimit()
on the matter.
This is right but... If you are using Spring WebSocket then the stomp message is
StompSubProtocolHandler
and
@Override
public void afterSessionStarted(WebSocketSession session, MessageChannel outputChannel) {
if (session.getTextMessageSizeLimit() < MINIMUM_WEBSOCKET_MESSAGE_SIZE) {
session.setTextMessageSizeLimit(MINIMUM_WEBSOCKET_MESSAGE_SIZE);
}
this.decoders.put(session.getId(), new BufferingStompDecoder(this.stompDecoder, getMessageSizeLimit()));
}
so here is the spring bug message size is set as websocket:transport message-size but the WebSocketSession is not ... is 8KB and this method will double it. No as the message that we want to send.
I do not know how to fix that; You need to set WebSocketSession TextMessageSizeLimit
. Maybe someone how know better spring boot factory knows a spring way to change the WebSocketSession textMessageSizeLimit
.
Anyway I did with Aop DelegatingIntroductionInterceptor
in the WebSocketMessageBrokerConfigurer
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
registry.setMessageSizeLimit(50 * 1024 * 1024); //this not work todo
registry.setSendBufferSizeLimit(50 * 1024 * 1024);
registry.setDecoratorFactories(agentWebSocketHandlerDecoratorFactory());
}
@Bean
public AgentWebSocketHandlerDecoratorFactory agentWebSocketHandlerDecoratorFactory() {
return new AgentWebSocketHandlerDecoratorFactory();
}
the AgentWebSocketHandlerDecoratorFactory
will proxy the WebSocketHandler
to a custom DelegatingIntroductionInterceptor
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultIntroductionAdvisor;
import org.springframework.aop.target.SingletonTargetSource;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.handler.WebSocketHandlerDecoratorFactory;
public class AgentWebSocketHandlerDecoratorFactory implements WebSocketHandlerDecoratorFactory {
@Override
public WebSocketHandler decorate(WebSocketHandler handler) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetClass(AopUtils.getTargetClass(handler));
proxyFactory.setTargetSource(new SingletonTargetSource(handler));
proxyFactory.addAdvisor(new DefaultIntroductionAdvisor(new SubProtocolWebSocketHandlerInterceptor()));
proxyFactory.setOptimize(true);
proxyFactory.setExposeProxy(true);
return (WebSocketHandler) proxyFactory.getProxy();
}
}
and the custom DefaultIntroductionAdvisor
will intercept the WebSocketHandler afterConnectionEstablished
and set WebSocketSession textMessageSizeLimit
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
import org.springframework.web.socket.WebSocketSession;
public class SubProtocolWebSocketHandlerInterceptor extends DelegatingIntroductionInterceptor {
@Override
protected Object doProceed(MethodInvocation mi) throws Throwable {
if(mi.getMethod().getName().equals("afterConnectionEstablished") ) {
WebSocketSession session = (WebSocketSession) mi.getArguments()[0];
session.setTextMessageSizeLimit(50*1024*1024);
}
return super.doProceed(mi);
}
}
This is tested and will accept message biger the 16KB in the presented case message limit size is 50 * 1024 * 1024
Upvotes: 0
Reputation: 647
List<Transport> transports = new ArrayList<Transport>();
WebSocketContainer container = ContainerProvider.getWebSocketContainer();
container.setDefaultMaxTextMessageBufferSize(512*1024); //FIX
WebSocketClient wsClient = new StandardWebSocketClient(container);
transports.add(new WebSocketTransport(wsClient));
// transports.add(new RestTemplateXhrTransport());
SockJsClient sockJsClient = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new SimpleMessageConverter());
stompClient.setInboundMessageSizeLimit(512 * 1024); //FIX
Upvotes: 1
Reputation: 1244
I was getting similar javascript errorr when the default value of 65kb was set.. then i set it to some random and again got some error like the
connection was interrupted
. So tried increasing the time limit and that worked for me. Actually when the limit exceeds, the messages are sent into packets/or frames, and while it was receiving the response from server, it timed out.
You can use tweak it as below
@EnableWebSocketMessageBroker
public class AppWebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
----
---
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(200000); // default : 64 * 1024
registration.setSendTimeLimit(20 * 10000); // default : 10 * 10000
registration.setSendBufferSizeLimit(3* 512 * 1024); // default : 512 * 1024
}
---
}
Upvotes: 8
Reputation: 121177
Consider <websocket:transport message-size=""/>
option for the <websocket:message-broker>
definition:
Configure the maximum size for an incoming sub-protocol message. For example a STOMP message may be received as multiple WebSocket messages or multiple HTTP POST requests when SockJS fallback options are in use.
The same can be achieved in annotation configuration using WebSocketMessageBrokerConfigurer.configureWebSocketTransport(WebSocketTransportRegistration)
implementation and with the setMessageSizeLimit()
on the matter.
Upvotes: 6