The DataBufferLimitException in Spring WebFlux typically occurs when the data buffer size exceeds the maximum allowed limit while processing large payloads. This can be encountered when dealing with large request or response bodies. To resolve this exception, we can adjust the buffer limits or handle large data more efficiently.
This DataBufferLimitException indicates that the cumulative number of bytes consumed from a stream of DataBuffer has exceeded some pre-configured limit. In this article, we will discuss how to resolve the Spring WebFlux DataBufferLimitException with related examples and output for better understanding.
Below are some scenarios where we might encounter a DataBufferLimitException:- Large File Uploads: When users attempt to upload files that exceed the configured buffer size limit.
- Large Responses: When your application receives responses from external services or APIs that are larger than the configured buffer size limit.
- Streaming Large Data: If your application is streaming data and attempting to buffer it in memory, and the data size exceeds the configured limit.
- Processing Large Requests: When your application processes incoming requests that contain large payloads.
To handle DataBufferLimitException, - Adjust the buffer size limit in your Spring WebFlux configuration.
- Implement streaming techniques to process or handle large data without buffering it entirely in memory.
- Handle the exception gracefully in your application logic and provide appropriate error responses to clients
Steps To Resolve Spring WebFlux DataBufferLimitExceptionTo Resolve Spring WebFlux DataBufferLimitException, here we created a Spring Boot project which is maven type. For this project, we use below dependencies.
Project Dependencies:<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> </dependencies> Project Folder Structure:
After creating the project, the structure will be like below:
 project folder
Step 1: Main Class FileOnce project is created, automatically Spring framework creates this class with main function and spring application execution starts from here only.
Java
package com.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DatabufferApplication {
public static void main(String[] args) {
SpringApplication.run(DatabufferApplication.class, args);
}
}
Step 2: applicatoin.propertiesThis file is located in the resource folder in the project folder. In this file, we define some configurations which are used for tracing logs as well as creating upload directory in the project folder. Here, we define maximum file upload size is 1MB only.
spring.main.allow-bean-definition-overriding=true logging.level.org.springframework.web=DEBUG logging.level.org.springframework.web.reactive.function=TRACE spring.codec.max-in-memory-size=1MB
upload.dir=upload-dir
Step 3: Create ControllerWe created a RestController class by using @RestController annotation with name FileUploadController in main package of project. This class is used for define the API endpoints as well as defining the required business logic in this class. Below we provide that handler code.
In this class, we define the file upload functionality by using FilePart. And, here, we created a method called uploadFile() for uploading the file into given file path.
@Value("${upload.dir:upload-dir}") private String uploadDir; Here, we declare a string value that is uploadDir this variable takes value from application.propertiles with property name upload.dir
FileUploadController.java:
Java
package com.app;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.buffer.DataBufferLimitException;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import reactor.core.publisher.Mono;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
@RestController
public class FileUploadController {
@Value("${upload.dir:upload-dir}")
private String uploadDir;
@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public Mono<String> uploadFile(@RequestPart("file") FilePart file) {
// Check file size
return file.content().map(dataBuffer -> dataBuffer.readableByteCount()).reduce(Integer::sum).flatMap(size -> {
if (size > 1048576) { // 1MB in bytes
return Mono
.error(new DataBufferLimitException("File size exceeds limit. Please upload file size with 1MB or Below Only"));
} else {
// Ensure the directory exists
Path dirPath = Paths.get(uploadDir);
if (!Files.exists(dirPath)) {
try {
Files.createDirectories(dirPath);
} catch (Exception e) {
return Mono.error(new RuntimeException("Could not create upload directory", e));
}
}
// Define the path where the file will be saved
Path filePath = dirPath.resolve(Objects.requireNonNull(file.filename()));
// Save the file content to the defined path
return file.transferTo(filePath).then(Mono.just("File uploaded: " + file.filename()));
}
}).onErrorResume(DataBufferLimitException.class,
e -> Mono.just("Failed to upload file: File size exceeds limit."));
}
}
- In the above code, first we created a String and assign a value from application.properties file.
- After that, we define the Request mapping type and here we use POST Mapping with API name upload and this API accept MULTIPART_FORM_DATA_VALUE also.
- Now, we create a method called uploadFile which can take request part as input by using FilePart. Then inside method we define business logic for uploading file.
- Before uploading, we check the file size is less then 1MB or equals to 1MB then only file will be uploaded otherwise we throw DataBufferLimitException exception.
Step 4: Run the ProjectOnce project is completed with required logic, run the project as a Spring Boot App or we can run this project by using Maven commands also. Here, we will run this project as Spring Boot App. This project is running on 8080 port number with Netty server by default.
 project running
Step 5: Test API EndpointNow test API endpoint. Here we will use the Postman tool for testing API endpoint.
Testing with Postman:- Open Postman and create a new request.
- Set the request type to POST and enter the endpoint URL.
- http://localhost:8080/upload
- Now, go to Body tab and then select form-data.
- Add a new field with the key file and change the type to File.
- Choose a large file from your file system to upload.
- Send the request.
- Check the response. You should receive a success message if the file is uploaded successfully.
Case 1: - Here we upload a file with less then 1MB size and it is POST mapping.
- Once file is successfully uploaded, a new folder is created in project folder with upload file.
- Below we provide that image also and compare the image with the above project folder image.
http://localhost:8080/upload Output: output
Updated Project Folder Structure:Below is the updated folder structure of the project.
 updated project folder
Case 2: If we upload a file with size more then 1MB then we throw an exception.
Output: output
|