Software Development

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.

Yatin Batra

An experience full-stack engineer well versed with Core Java, Spring/Springboot, MVC, Security, AOP, Frontend (Angular & React), and cloud technologies (such as AWS, GCP, Jenkins, Docker, K8).
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button