XSSFWorkbook when written creates a corrupted .xlsx document in Spring Boot application using JDBC


XSSFWorkbook when written creates a corrupted .xlsx document in Spring Boot application using JDBC



For a project I need to create an .xlsm excel document automatically filling out a template file. Problem is, that the output is corrupted and cannot be read by Excel 365 nor by Apache POI.


.xlsm



I have distilled it down to the following minimal example, that can run in a main method. To be completely safe it is using the .xlsx format.


main


.xlsx


public static void main(String args) {
XSSFWorkbook document = new XSSFWorkbook();
XSSFSheet spreadsheet = document.createSheet("Test");
spreadsheet.createRow(0).createCell(0).setCellValue("Testie test");

// Output .xlsx file
FileOutputStream stream;
try {
stream = new FileOutputStream("test_output.xlsx");
document.write(stream);
stream.flush();
stream.close();

} catch (IOException e) {
System.err.println("Error" + e.getMessage());
e.printStackTrace();
}
...



The created file test_output.xlsx cannot be opened by Excel 365 and has a size of only 4kb, while a manually created one would take up 9kb, so there must be something missing in the output that I have not specified?


test_output.xlsx



I'm using Apache POI version 3.17 imported via Gradle using


compile('org.apache.poi:poi-ooxml:3.17')



and also with Apache POI version 3.13 to have a version from before 2016. No luck in both cases.



When the main method is extended to also reopen the same file, that was just created, as shown below


...
// Try to read it again
try {
document = new XSSFWorkbook("test_output.xlsx");
System.out.println(document.getSheetAt(0).getRow(0).getCell(0).getStringCellValue());

} catch (IOException e) {
e.printStackTrace();
}
}



then I end up in the following exception


java.io.IOException: org.apache.poi.openxml4j.exceptions.InvalidFormatException: Can't read content types part !
at org.apache.poi.POIXMLDocument.openPackage(POIXMLDocument.java:91)
at org.apache.poi.xssf.usermodel.XSSFWorkbook.<init>(XSSFWorkbook.java:340)
...



If on the other hand all XSSF* is replaced with HSSF* and the file type made into a .xls file, then the document outputted is fine, yet I need to create a working Excel 365 document, not an Excel 2003 one.


XSSF*


HSSF*


.xls



The following is [Content_Types].xml file in the manually made .xlsx document


[Content_Types].xml


.xlsx


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default Extension="rels" ContentType="application/vnd.openxmlformats-package.relationships+xml"/>
<Default Extension="xml" ContentType="application/xml"/>
<Override PartName="/xl/workbook.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml"/>
<Override PartName="/xl/worksheets/sheet1.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml"/>
<Override PartName="/xl/theme/theme1.xml" ContentType="application/vnd.openxmlformats-officedocument.theme+xml"/>
<Override PartName="/xl/styles.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml"/>
<Override PartName="/xl/sharedStrings.xml" ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml"/>
<Override PartName="/docProps/core.xml" ContentType="application/vnd.openxmlformats-package.core-properties+xml"/>
<Override PartName="/docProps/app.xml" ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml"/>
</Types>



While the following is [Content_Types].xml in the POI created file .xlsx


[Content_Types].xml


.xlsx


<?xml version = '1.0' encoding = 'UTF-8' standalone = 'yes'?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ="rels"/>
<Default ="xml"/>
<Override ="/docProps/app.xml"/>
<Override ="/docProps/core.xml"/>
<Override ="/xl/sharedStrings.xml"/>
<Override ="/xl/styles.xml"/>
<Override ="/xl/workbook.xml"/>
<Override ="/xl/worksheets/sheet1.xml"/>
</Types>





Have you tried with earlier versions of library?
– soulcoder
Jul 3 at 9:36





I have tried with 3.13 to get a version earlier than 2016 without any luck.
– Steffan Sølvsten
Jul 3 at 9:38





in fact I just try your example but it works, (I'm using Numbers in macOS)
– Azarea
Jul 3 at 9:39





What Java version are you using? Maybe any kind of Java 10 problem?
– Axel Richter
Jul 3 at 9:52






The lower file size is not any hint to failure here. Excel puts some unnecessary data in new files which POI doesn't. A *.xlsx file can simply be unzipped. Do that and do comparing /[Content_Types].xml of Excel generated and POI generated file. Because of error "Can't read content types part !".
– Axel Richter
Jul 3 at 10:03



*.xlsx


/[Content_Types].xml




1 Answer
1



Based on the suggestions of @AxelRichter when all other dependencies are removed in build.gradle then [Content_Types].xml looks as follows.


build.gradle


<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<Types xmlns="http://schemas.openxmlformats.org/package/2006/content-types">
<Default ContentType="application/vnd.openxmlformats-package.relationships+xml" Extension="rels"/>
<Default ContentType="application/xml" Extension="xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.extended-properties+xml" PartName="/docProps/app.xml"/>
<Override ContentType="application/vnd.openxmlformats-package.core-properties+xml" PartName="/docProps/core.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml" PartName="/xl/sharedStrings.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.styles+xml" PartName="/xl/styles.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml" PartName="/xl/workbook.xml"/>
<Override ContentType="application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" PartName="/xl/worksheets/sheet1.xml"/>
</Types>



And the above code runs without issues and the file can be opened in Office 365. The problem lies in the import of


compile('com.oracle.jdbc:ojdbc8:12.2.0.1')



Which creates a conflict in the classpath for the XML parser used by Apache POI, meaning either the Excel part needs to be done in another project with Gradle handling the dependency issues.





I am curious what exact class is in conflict there. But seems as if ojdbc8.jar is not public available, at least not without creating a Oracle account, what I don't want to do. Is there at least a class list of ojdbc8.jar public available somewhere?
– Axel Richter
Jul 4 at 9:20


ojdbc8.jar


ojdbc8.jar





@AxelRichter Maybe not exactly what you were asking for, but I've run a .bat script to extract all the content of the .jar file. pastebin.com/9Nzw2REH
– Steffan Sølvsten
Jul 5 at 11:53






Thank you. That is exactly what I was after. But now I also cannot see where the conflict may be. There are involved classes having same name Element : org.w3c.dom.Element and oracle.jdbc.pooling.LinkedListPool.Element and oracle.jdbc.pooling.PoolIteratorQueue.Element. But they are fully qualified named and imported. So there should not be any conflict. Mysterious that.
– Axel Richter
Jul 5 at 13:08



org.w3c.dom.Element


oracle.jdbc.pooling.LinkedListPool.Element


oracle.jdbc.pooling.PoolIteratorQueue.Element





@AxelRichter Maybe it is in the dependency of the xmlparserv2.jar also downloaded together with ojdbc8.jar? It contains pastebin.com/LLEquXVf . It seems especially like there is some rerouting in the META-INF/services folder.
– Steffan Sølvsten
Jul 6 at 6:36





Yes, seems xmlparserv2.jar is the problem here. See stackoverflow.com/questions/6412736/…. Maybe good to know for others who wants using apache poi and Spring Boot together.
– Axel Richter
Jul 6 at 8:23


xmlparserv2.jar


apache poi


Spring Boot






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

api-platform.com Unable to generate an IRI for the item of type

How to set up datasource with Spring for HikariCP?

Display dokan vendor name on Woocommerce single product pages