How to Use Apache POI with Maven: A Step‑by‑Step Guide
Apache POI makes it possible to read, create, and modify Microsoft Office files directly from Java. Pairing it with Maven streamlines dependency management and keeps your project tidy. This guide walks you through everything you need to get POI up and running in a Maven‑based build.
What Is Apache POI and Why Use Maven?
Apache POI is an open‑source library that supports the older binary formats (like .xls) as well as the newer XML‑based Office Open XML formats (such as .xlsx and .docx). It covers spreadsheets, Word documents, PowerPoint decks, and even Visio files. Without Maven, you’d have to hunt down the right JARs, watch for transitive dependencies, and manually update them whenever a new POI version appears. Maven automates all that, letting you focus on the code that actually manipulates the files.
Setting Up a Maven Project for POI
The first step is to make sure you have a Maven project skeleton. If you’re starting from scratch, run:
mvn archetype:generate -DgroupId=com.example -DartifactId=poi-demo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseThis creates a basic pom.xml and a simple Java source layout. Open the generated pom.xml and add the POI dependency block inside the <dependencies> section.
Choosing the Right POI Modules
POI is split into several modules so you can pull in only what you need. The most common combination looks like this:
- poi – Core classes for the older binary formats.
- poi-ooxml – Support for the newer OOXML formats (.xlsx, .docx, .pptx).
- poi-ooxml-schemas – Optional, provides full OOXML schema support (useful for advanced features).
- commons-collections4 – Required by POI for some collection utilities.
Here’s a minimal dependency snippet that works for most spreadsheet tasks:
<dependency><groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.3</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
Replace 5.2.3 with the latest stable release you find on Maven Central. Keeping the version consistent across modules avoids class‑path conflicts.
Quick Example: Reading an Excel Workbook
Once the dependencies are in place, create a simple Java class to read data from a .xlsx file. The code below demonstrates the typical flow:
import java.io.File;import java.io.FileInputStream;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelReader {
public static void main(String[] args) throws Exception {
File file = new File("sample.xlsx");
try (FileInputStream fis = new FileInputStream(file);
Workbook workbook = new XSSFWorkbook(fis)) {
Sheet sheet = workbook.getSheetAt(0);
for (Row row : sheet) {
for (Cell cell : row) {
System.out.print(cell.toString() + "\t");
}
System.out.println();
}
}
}
}
This snippet opens the first sheet, iterates over rows and cells, and prints each value to the console. Note the use of a try‑with‑resources block; it guarantees that the file handle closes properly, which is especially important when dealing with large workbooks.
Writing Data Back to Excel
Creating a new workbook follows a similar pattern, but you start with an empty XSSFWorkbook instance. Here’s a concise example that builds a tiny report:
import java.io.FileOutputStream;import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class ExcelWriter {
public static void main(String[] args) throws Exception {
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("Report");
// Header row
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("Item");
header.createCell(1).setCellValue("Quantity");
header.createCell(2).setCellValue("Price");
// Sample data
Object[][] data = {
{"Apples", 12, 0.99},
{"Bananas", 8, 0.79},
{"Cherries", 15, 2.49}
};
int rowNum = 1;
for (Object[] rowData : data) {
Row row = sheet.createRow(rowNum++);
for (int i = 0; i < rowData.length; i++) {
Cell cell = row.createCell(i);
if (rowData[i] instanceof Number) {
cell.setCellValue(((Number) rowData[i]).doubleValue());
} else {
cell.setCellValue(rowData[i].toString());
}
}
}
try (FileOutputStream fos = new FileOutputStream("report.xlsx")) {
wb.write(fos);
}
wb.close();
}
}
The code builds a header, loops through a two‑dimensional array, and writes numeric values appropriately. When the program finishes, you’ll have a ready‑to‑open report.xlsx file.
Common Pitfalls and How to Avoid Them
- Version mismatches. POI’s core and OOXML modules must share the same version number. Mixing
5.2.0and5.2.3can causeNoSuchMethodErrorat runtime. - Large files. For workbooks larger than a few megabytes, consider using the
SXSSFWorkbookstreaming API, which writes rows to disk instead of keeping everything in memory. - Missing transitive dependencies. Some POI features rely on Apache XMLBeans. If you see “class not found” errors related to
org.apache.xmlbeans, add thexmlbeansdependency explicitly. - Incorrect cell type handling. Calling
cell.getStringCellValue()on a numeric cell throws an exception. Usecell.toString()for a quick‑and‑dirty display, or inspectcell.getCellType()first.
Best Practices for Maven‑Managed POI Projects
To keep your build clean and performant, follow these guidelines:
- Declare the POI version in a
<properties>block so you can bump it in one place. - Use the
maven‑shadeplugin if you need a single runnable JAR that bundles POI and its dependencies. - Run
mvn dependency:treeperiodically to spot unwanted transitive libraries that may bloat your artifact. - Write unit tests with
Apache POI Testkitor simple JUnit assertions that open a generated workbook and verify cell values.
FAQ
Do I need both poi and poi‑ooxml for .xlsx files?
Yes. poi‑ooxml handles the OOXML formats, but it depends on the core poi module for shared utilities. Adding only poi‑ooxml will cause missing‑class errors.
Can Maven resolve POI’s optional schemas automatically?
Not by default. The poi‑ooxml‑schemas JAR is optional; you must add it manually if your code uses advanced features like custom data validation or embedded charts.
How do I manage memory when processing huge Excel files?
Switch to SXSSFWorkbook, which writes rows to temporary files as you go. Combine this with the Maven maven‑compiler‑plugin setting -Xmx to allocate sufficient heap.
Is it safe to use Apache POI in a multithreaded application?
POI objects themselves are not thread‑safe. Create a separate Workbook instance per thread, or synchronize access if you must share a single workbook.