Table Of Content
1. Introduction
2. Why configure maxSwallowSize property
3. How to configure maxSwallowSize property
4. Conclusion
1. Introduction
At first, let's understand what does 'maxSwallowSize' property signify?
maxSwallowSize : From Apache Tomcat 8 Configuration Reference documentation[1]:
"The maximum number of request body bytes (excluding transfer encoding overhead) that will be swallowed by Tomcat for an aborted upload. An aborted upload is when Tomcat knows that the request body is going to be ignored but the client still sends it. If Tomcat does not swallow the body, the client is unlikely to see the response. If not specified the default of 2097152 (2 megabytes) will be used. A value of less than zero indicates that no limit should be enforced."maxSwallowSize is a property of the connector. Although the swallow size isn't specific to file uploads but generally in case file uploads , the request size tend be larger as compared to normal requests. Therefore for file uploads, one might need to configure this property otherwise Tomcat may terminate the connection when user tries to upload files having size larger than the maxSwallowSize threshold and user would not be able to see the meaningful message about what just happened with the application.
Currently maxSwallowSize property can't be configured by Spring Boot's configuration file i.e. application.yml / application.properties [2]. But it might come up as the future enhancement. For now, Java configuration is required for this.
2. Why configure maxSwallowSize property?
There is one reason for configuring maxSwallowSize property which is described below:
To avoid the Connection Reset issue while file uploads:
When users tries to upload files whose size exceeds the maxSwallowSize property value then Tomcat terminate the connection and user would see the ERR_CONNECTION_RESET error in the browser. Even if, user have their Controller Advice Interceptor class[3] in place for catching the exception, it will never be invoked. Therefore one need to configure maxSwallowSize property for embedded Tomcat.
3. How to configure maxSwallowSize property?
Since maxSwallowSize is a property of a Connector. We need to use the TomcatConnectorCustomizer functional interface for setting the maxSwallowSize property and then associate it with the TomcatEmbeddedServletContainerFactory class. One can use any one of the below code snippet in their main Spring Boot application class.
- Using simple java
#application.properties maxswallowsize.inmb = -1 or #application.yml maxswallowsize: inmb: -1 import org.apache.coyote.http11.AbstractHttp11Protocol; import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; @Value("${maxswallowsize.inmb}") private int maxSwallowSizeInMb; @Bean public TomcatEmbeddedServletContainerFactory containerFactory() { TomcatEmbeddedServletContainerFactory containerFactory = new TomcatEmbeddedServletContainerFactory(); TomcatConnectorCustomizer tomcatConnectorCustomizer = new TomcatConnectorCustomizer() { @Override public void customize(Connector connector) { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { // -1 means, accept unlimited bytes, get this value from application.yml using @Value ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(maxSwallowSizeInMb); } } }; containerFactory.addConnectorCustomizers(tomcatConnectorCustomizer); return containerFactory; }
- Using Java Lambda Expression
@Bean public TomcatEmbeddedServletContainerFactory containerFactory() { TomcatEmbeddedServletContainerFactory tomcatContainerFactory = new TomcatEmbeddedServletContainerFactory(); tomcatContainerFactory.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> { if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol)) { ((AbstractHttp11Protocol) connector.getProtocolHandler()).setMaxSwallowSize(-1); } }); return tomcatContainerFactory; }
For example: Upload Form 1 [max upload file size = 10MB], Upload Form 2 [max upload file size = 20MB] & Upload Form 3 [max upload file size = 30MB] then maxSwallowSize property value = max(10MB,20MB,30MB) = 30MB.
4. Conclusion
Now we know, 'Why' & 'How to' configure the maxSwallowSize property value for the embedded Tomcat. Therefore, if one have properly configured maxSwallowSize property value & a Controller Advice Interceptor class then one could avoid the connection reset issue and display a meaningful, user friendly validation message to the user for any file upload related Exception.Appendix:
[1]: The standard HTTP connectors attributes
[2]: Common Spring Boot application properties
[3]: Class annotated with @ControllerAdvice is required for catching the file upload related Exception. Our controller can't catch these type of exception as the request is rejected for these type of exception and control never goes to Controller method in debug mode.
[2]: Common Spring Boot application properties
[3]: Class annotated with @ControllerAdvice is required for catching the file upload related Exception. Our controller can't catch these type of exception as the request is rejected for these type of exception and control never goes to Controller method in debug mode.
No comments:
Post a Comment