Export Excel File in Micronaut Controller
Micronaut is a modern, JVM-based, full-stack framework designed for building modular, easily testable microservice and serverless applications. Returning an Excel file from a controller is a common requirement for exporting data reports in enterprise applications. Let us understand how to return an Excel file in a Micronaut controller, a common requirement when building microservices that serve dynamic reports or tabular data.
1. What is Micronaut?
Micronaut is a modern, JVM-based, full-stack framework specifically designed for building modular, high-performance microservices, serverless applications, and cloud-native systems. It offers first-class support for Java, Kotlin, and Groovy, making it a flexible choice for JVM developers.
Unlike traditional Java frameworks that rely heavily on runtime reflection and proxies (such as Spring), Micronaut uses compile-time annotation processing for dependency injection, AOP (Aspect-Oriented Programming), and configuration. This unique approach drastically reduces memory usage and startup time, making it ideal for microservices and serverless environments like AWS Lambda or Google Cloud Functions.
Micronaut also integrates seamlessly with GraalVM to enable ahead-of-time (AOT) compilation into native executables, further improving performance and resource efficiency.
Key features of Micronaut include:
- Compile-time dependency injection: No reflection or runtime proxies, leading to better performance and smaller memory footprint.
- Fast startup time and low memory usage: Ideal for microservices and containerized environments.
- Seamless integration with GraalVM: Supports building native images for ultra-fast execution and minimal memory use.
- Reactive and non-blocking: Includes built-in support for reactive programming using RxJava, Project Reactor, etc.
- Built-in HTTP server/client: Lightweight Netty-based web server and declarative HTTP clients with easy configuration.
- Cloud-native readiness: Support for service discovery, distributed tracing, configuration management, and more.
- Modular architecture: Encourages separation of concerns and better maintainability.
2. Code Example and Explanation
In this section, we’ll walk through how to generate an Excel file dynamically using Apache POI and return it as a downloadable file from a Micronaut controller. This includes setting up dependencies, writing service, and injecting it into a controller.
2.1 Add dependencies (pom.xml)
First, we set up the required dependencies in our pom.xml.
<dependencies>
<dependency>
<groupId>io.micronaut</groupId>
<artifactId>micronaut-http-server-netty</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>jar__latest__version</version>
</dependency>
</dependencies>
2.2 Creating a Service Layer
The ExcelExportService class is a singleton Java service that generates an Excel file using the Apache POI library. Within the generateExcel() method, it creates a new workbook and adds a sheet named “Users”. It first defines a header row with columns “ID”, “Name”, and “Email”, and then inserts three rows of hardcoded user data. Each row is filled by iterating through a 2D object array and writing values as strings into cells. After populating the data, the method auto-sizes the first three columns for optimal display. The workbook is then written to a ByteArrayOutputStream and returned as a ByteArrayInputStream. If an IOException occurs during processing, it is caught and rethrown as a runtime exception.
package com.jcg.service;
import jakarta.inject.Singleton;
import org.apache.poi.ss.usermodel. * ;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@Singleton
public class ExcelExportService {
// Method to generate an Excel file and return it as a ByteArrayInputStream
public ByteArrayInputStream generateExcel() {
try (Workbook workbook = new XSSFWorkbook()) { // Create a new Excel workbook using XSSFWorkbook (for .xlsx format)
// Create a sheet named "Users"
Sheet sheet = workbook.createSheet("Users");
// Create header row and set cell values for the column names
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID"); // Column for ID
header.createCell(1).setCellValue("Name"); // Column for Name
header.createCell(2).setCellValue("Email"); // Column for Email
// Sample data to be added to the Excel sheet
Object[][] data = {
{
1,
"John Doe",
"john@example.com"
},
{
2,
"Jane Smith",
"jane@example.com"
},
{
3,
"Alice Johnson",
"alice@example.com"
}
};
// Loop through the data and create rows for each entry in the Excel sheet
for (int i = 0; i < data.length; i++) {
Row row = sheet.createRow(i + 1); // Create a new row starting from index 1 (after header)
for (int j = 0; j < data[i].length; j++) {
row.createCell(j).setCellValue(String.valueOf(data[i][j])); // Populate cells with data values
}
}
// Auto size the columns to fit content
for (int i = 0; i < 3; i++) {
sheet.autoSizeColumn(i); // Adjust column width for columns 0, 1, and 2
}
// Write the workbook to a ByteArrayOutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
workbook.write(out);
// Return the Excel data as a ByteArrayInputStream
return new ByteArrayInputStream(out.toByteArray());
} catch(IOException e) {
// Handle any IOExceptions by throwing a runtime exception
throw new RuntimeException("Failed to generate Excel file", e);
}
}
}
2.3 Creating a Controller Class
The ExcelExportController class is a Micronaut HTTP controller that exposes an API endpoint for downloading an Excel file. It is mapped to the path /api/export/excel and produces a response with the MIME type application/octet-stream, indicating a binary file download. The controller injects an instance of ExcelExportService, which is responsible for generating the Excel content. When a GET request is made to this endpoint, the exportExcel() method is called, which retrieves the Excel data as a ByteArrayInputStream, wraps it in a StreamedFile, and sets the content disposition to trigger a file download with the filename “users.xlsx”. The method then returns the file in the HTTP response using HttpResponse.ok().
package com.jcg.controller;
import com.example.service.ExcelExportService;
import io.micronaut.http.HttpResponse;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
import io.micronaut.http.server.types.files.StreamedFile;
import java.io.ByteArrayInputStream;
@Controller("/api/export") // Defines the base URL for the controller's API endpoint
public class ExcelExportController {
private final ExcelExportService excelExportService; // Declare a reference to the ExcelExportService
// Constructor to inject ExcelExportService into the controller
public ExcelExportController(ExcelExportService excelExportService) {
this.excelExportService = excelExportService;
}
// Define a GET endpoint at /api/export/excel, which produces an octet-stream (binary) response type
@Get(uri = "/excel", produces = MediaType.APPLICATION_OCTET_STREAM)
public HttpResponse<StreamedFile> exportExcel() {
// Call the generateExcel method from ExcelExportService to get the Excel file content
ByteArrayInputStream excelStream = excelExportService.generateExcel();
// Create a StreamedFile with the Excel data stream and specify the content type as application/octet-stream
// This sets up the response as a downloadable file named "users.xlsx"
StreamedFile streamedFile = new StreamedFile(excelStream, MediaType.APPLICATION_OCTET_STREAM_TYPE)
.attach("users.xlsx");
// Return the HTTP response with the streamed file attached
return HttpResponse.ok(streamedFile);
}
}
2.4 Run the Application
Once everything is in place, run the application using mvn mn:run. Navigate to http://localhost:8080/api/export/excel in your browser and you’ll get a file named users.xlsx downloaded with the following content:
ID Name Email 1 John Doe john@example.com 2 Jane Smith jane@example.com 3 Alice Johnson alice@example.com
3. Conclusion
With Micronaut’s fast startup and simple configuration, generating and exporting Excel files becomes easy and efficient. Splitting logic into controller and service layers improves testability and maintainability. This foundation can be expanded to support database integration, parameterized downloads, and style reports.



