Skip to content

Manveroo/spring-web-streaming

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Purpose

This is a demonstrator to show how streaming a large requests with spring used to work, but is now buffering the whole object in memory.

Startup

  • mvn clean install (Apache Maven 3.9.11)
  • Launch the spring boot application via com.github.manveroo.spring_web_streaming.SpringWebStreamingApplication.
  • Don't forget to limit the available memory by adding -Xmx500m.
  • Open the UI on http://localhost:8080/
  • Click the button "Start Streaming Working" to stream a temp file without any issues since it uses the old implementation or use curl -XPOST http://localhost:8080/startWorking to trigger the endpoint.
  • Click the button "Start Streaming Broken" to stream a temp file and end up in a java.lang.OutOfMemoryError: Java heap space error or use curl -XPOST http://localhost:8080/startBroken to trigger the endpoint.
  • Code is found in the package: com.github.manveroo.spring_web_streaming.Controller

Web UI with two buttons which allow the triggering of either the working streaming implemenation or the broken one

Explanation

Any version of spring-web starting with 6.1.x is using a FastByteArrayOutputStream while processing a request at: AbstractClientHttpRequest:getBody -> AbstractStreamingClientHttpRequest:getBodyInternal -> new FastByteArrayOutputStream

Before (e.g. spring-web version 6.0.23), AbstractClientHttpRequest:getBody -> SimpleStreamingClientHttpRequest:getBodyInternal -> HttpURLConnection:getOutputStream

The implementation using the FastByteArrayOutputStream is buffering the whole request in memory which will trigger an OOM exception at some point when the request is too large. E.g.:

...
Processed 268238848 bytes
Processed 268304384 bytes
Processed 268369920 bytes
2025-10-15T13:42:46.654+02:00 ERROR 19436 --- [spring-web-streaming] [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.OutOfMemoryError: Java heap space] with root cause

java.lang.OutOfMemoryError: Java heap space
	at org.springframework.util.FastByteArrayOutputStream.addBuffer(FastByteArrayOutputStream.java:323) ~[spring-core-6.2.11.jar:6.2.11]
	at org.springframework.util.FastByteArrayOutputStream.write(FastByteArrayOutputStream.java:118) ~[spring-core-6.2.11.jar:6.2.11]
	at com.github.manveroo.spring_web_streaming.Controller.doStream(Controller.java:138) ~[classes/:na]
	at com.github.manveroo.spring_web_streaming.Controller.lambda$startBroken$0(Controller.java:84) ~[classes/:na]
	at com.github.manveroo.spring_web_streaming.Controller$$Lambda/0x000001ed0151eb38.doWithRequest(Unknown Source) ~[na:na]
	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:898) ~[spring-web-6.2.11.jar:6.2.11]
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:801) ~[spring-web-6.2.11.jar:6.2.11]
	at com.github.manveroo.spring_web_streaming.Controller.startBroken(Controller.java:90) ~[classes/:na]
	at java.base/java.lang.invoke.LambdaForm$DMH/0x000001ed01308400.invokeVirtual(LambdaForm$DMH) ~[na:na]
	at java.base/java.lang.invoke.LambdaForm$MH/0x000001ed01335000.invoke(LambdaForm$MH) ~[na:na]
	at java.base/java.lang.invoke.Invokers$Holder.invokeExact_MT(Invokers$Holder) ~[na:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invokeImpl(DirectMethodHandleAccessor.java:153) ~[na:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:258) ~[spring-web-6.2.11.jar:6.2.11]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:191) ~[spring-web-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:991) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:896) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.46.jar:6.0]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.2.11.jar:6.2.11]
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.46.jar:6.0]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.46.jar:10.1.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.46.jar:10.1.46]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.46.jar:10.1.46]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.46.jar:10.1.46]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.46.jar:10.1.46]

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published