1

Websocket configuration:

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/patrol").withSockJS();
    }    
}  

Endpoint:

@MessageMapping("/detection/face/frontal")
@SendTo("/topic/detection/face/frontal")
public String frontalFaceDetection(String encodedImage) throws IOException {
    System.out.println("frontalFaceDetection was called");
    byte[] imageBytes = javax.xml.bind.DatatypeConverter.parseBase64Binary(encodedImage);
    return "TEST";
}    

With this configuration when I call the endpoint sending an encoded (base64) image as String the endpoint returns:

java.lang.Exception: java.net.SocketException: Broken pipe


I tried changing the size of the message for the ServletServerContainerFactoryBean adding this code in the WebSocketConfig class:

@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(Integer.MAX_VALUE);
    container.setMaxBinaryMessageBufferSize(Integer.MAX_VALUE);
    return container;
}  

But now the error is:

java.lang.OutOfMemoryError: Requested array size exceeds VM limit


I encoded the image on a client Android like this:

private String drawableToBase64(int resId) {
    Bitmap bitmapOrg = BitmapFactory.decodeResource(getResources(), resId);
    ByteArrayOutputStream bao = new ByteArrayOutputStream();
    bitmapOrg.compress(Bitmap.CompressFormat.JPEG, 100, bao);
    byte[] ba = bao.toByteArray();
    return Base64.encodeToString(ba, Base64.DEFAULT);
}  

Debugging the code the size of the message is: 2622244 so I tried changing the size of the messages (server side) like this:

@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(2622244 + 1);
    container.setMaxBinaryMessageBufferSize(2622244 + 1);
    return container;
}  

Now I get

o.s.w.s.m.StompSubProtocolHandler        : Failed to parse TextMessage payload=[SEND
desti..], byteCount=2622291, last=true] in session ccfa1dfa-7076-395d-9c26-e0a8d106ba81. Sending STOMP ERROR to client.    
org.springframework.messaging.simp.stomp.StompConversionException: The configured STOMP buffer size limit of 65536 bytes has been exceeded  

I tried the solution proposed in this SO thread too, no more memory related errors but i get again:

java.lang.Exception: java.net.SocketException: Broken pipe


Anyone have experience with this issue? I'm trying different solutions but it doesn't work. Where I'm wrong? Any idea?
Thank you.

Roberto Manfreda
  • 2,345
  • 3
  • 25
  • 39
  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit comes because you tried to set the buffer size larger than the Heap size as defined in Xmx in the JVM here - container.setMaxTextMessageBufferSize(Integer.MAX_VALUE); I suggest setting the max size as large as you expect and set the Xmx accordingly (probably a few 100MB more than max message size) – Aditya Sep 03 '19 at 11:50

1 Answers1

0

The only way i found is adding this code in the configuration:

@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registry) {
    registry.setMessageSizeLimit(2048 * 2048);
    registry.setSendBufferSizeLimit(2048 * 2048);
    registry.setSendTimeLimit(2048 * 2048);
}

@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
    ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
    container.setMaxTextMessageBufferSize(2048 * 2048);
    container.setMaxSessionIdleTimeout(2048L * 2048L);
    container.setAsyncSendTimeout(2048L * 2048L);
    container.setMaxBinaryMessageBufferSize(2048 * 2048);
    return container;
}
Roberto Manfreda
  • 2,345
  • 3
  • 25
  • 39
  • Did this worked for anyone? I am still getting the error message when sending large (150K) message Buffer size 4206421 bytes for session '5s41tqiq' exceeds the allowed limit 4194304" – Paul Gobin Dec 22 '20 at 19:58