Issue
I have an app with a front-end in React and back-end in Java & Spring Boot.
The front-end subscribes to many topics via websockets, and it always goes fine, except when the messages are too long. It turns out, when the websocket message is longer than 64KB, the message is not sent, but no error is reported. Plus, any subsequent attempts to send more messages on that connection, even if the message is short, are also lost.
On the back-end, first we configure the websocket. I tried the suggestions of other answers that say to increase size limits: here and here, but none of them worked. It seems that those values are ignored altogether, as if I set a ridiculously low value, longer messages can still go through (if less than 64K).
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config)
{
config.enableSimpleBroker("/ws");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry)
{
registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS();
}
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry)
{
registry.setMessageSizeLimit(1000000);
registry.setSendBufferSizeLimit(1000000);
registry.setSendTimeLimit(100000);
}
}
Here is a simplified example that sends the websocket messages, that I have also tested and continues to have the same issue. Just calling an HTTP endpoint from the application so it will trigger the notification.
@RestController
@RequestMapping("/greeting")
public class GreetingController {
@Autowired
private SimpMessagingTemplate messageTemplate;
@GetMapping("/{length}")
public ResponseEntity<?> sendGreeting(@PathVariable int length)
{
String destination = "/ws/subscribedGreeting";
char[] charArray = new char[length];
Arrays.fill(charArray, '*');
String messageString = new String(charArray);
messageTemplate.convertAndSend(destination, messageString);
return ResponseEntity.noContent().build();
}
}
And sample code in the front-end:
import SockJS from 'sockjs-client';
import Stomp from 'stomp-websocket';
...
useEffect(() => {
const sock = new SockJS('my-ws-url'); // replace depending on your environment
const stompClient = Stomp.over(sock);
stompClient.connect({}, () => {
stompClient.subscribe('/ws/subscribedGreeting', (messageFromSocket) => {
console.log(`Message! ${messageFromSocket.body.length}`);
});
});
}, []);
And finally, make calls to the /greeting/{length}
endpoint. I just did it with Postman for quick testing.
Works well (logs to console the length) if I call with low length values: /greeting/100
, /greeting/10000
, /greeting/60000
, but if I set greeting/70000
, the message is not received and any further calls will not work (but it's OK for any new subscriptions). The worst part is that there are no logs of any sort reporting a problem.
I have been looking for alternatives for a couple of days now but have not found any answer.
Any ideas? How is it that the values I configured do not work? Perhaps there is an alternate way to set the size limits?
Thanks in advance.
Solution
I had not realized, I was using a "gateway" component, and that is where the maximum payload was configured by default to 64K. By setting the property like in this answer I was able to fix the issue.
Answered By - edurric
Answer Checked By - Candace Johnson (JavaFixing Volunteer)