I've been using JXL for a while to process excel files from inside the webapp folder. This works in both development and production. I just inject a ServletContext
and call something like:
Workbook.getWorkbook(new File(servletContext.getRealPath("WEB-INF/myfile.xls")))
and JXL can read the file and process it.
Now I need to switch to using Apache POI, as JXL can only read .xls
files, and not .xlsx
ones (which can have more than 65536 rows).
When I try to do the same using POI I get an exception:
[ERROR] java.security.AccessControlException: access denied ("java.io.FilePermission" "C:\Users\Drew\IntelliJ\UsavApp\target\UsavAppV7-1.0-SNAPSHOT\WEB-INF\myfile.xlsx" "write")
[ERROR] at java.security.AccessControlContext.checkPermission(AccessControlContext.java:372)
[ERROR] at java.security.AccessController.checkPermission(AccessController.java:559)
[ERROR] at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
[ERROR] at com.google.appengine.tools.development.DevAppServerFactory$CustomSecurityManager.checkPermission(DevAppServerFactory.java:429)
[ERROR] at java.lang.SecurityManager.checkWrite(SecurityManager.java:979)
[ERROR] at java.io.RandomAccessFile.<init>(RandomAccessFile.java:229)
[ERROR] at org.apache.poi.poifs.nio.FileBackedDataSource.newSrcFile(FileBackedDataSource.java:130)
[ERROR] at org.apache.poi.poifs.nio.FileBackedDataSource.<init>(FileBackedDataSource.java:46)
[ERROR] at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:218)
[ERROR] at org.apache.poi.poifs.filesystem.NPOIFSFileSystem.<init>(NPOIFSFileSystem.java:166)
[ERROR] at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:278)
[ERROR] at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:250)
[ERROR] at org.apache.poi.ss.usermodel.WorkbookFactory.create(WorkbookFactory.java:229)
[ERROR] at com.utilitiessavings.usavappv7.server.handler.parse.ParseElecTariffBooksHandler.processTariffsFromExcel(ParseElecTariffBooksHandler.java:108)
[ERROR] at com.utilitiessavings.usavappv7.server.handler.parse.ParseElecTariffBooksHandler.execute(ParseElecTariffBooksHandler.java:91)
[ERROR] at com.utilitiessavings.usavappv7.server.handler.parse.ParseElecTariffBooksHandler.execute(ParseElecTariffBooksHandler.java:39)
...etc
From reading around I gather POI isn't totally compatible with GAE, but most people talk about creating files from scratch, or writing them to the local disk. I'm not doing either of those so I wanted to be sure this is a limitation of App Engine and not something I'm doing.
My guess from the exception would be that POI needs write access even to read the file, whereas JXL didn't. Anyone shed any light on this?
Promoting a comment to an answer - in a case like this you should explicitly tell Apache POI to open your file in read-only mode
For a .xlsx
file, do that with
OPCPackage pkg = OPCPackage.open(new File("input.xlsx"), PackageAccess.READ);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
For a .xls
file, do that with
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File("input.xls"), true);
HSSFWorkbook wb = new HSSFWorkbook(fs);
Reading from an InputStream
is always read-only, it's with Files where there's an option
See the constructor javadocs for a little bit more details
Promoting a comment to an answer - in a case like this you should explicitly tell Apache POI to open your file in read-only mode
For a .xlsx
file, do that with
OPCPackage pkg = OPCPackage.open(new File("input.xlsx"), PackageAccess.READ);
XSSFWorkbook wb = new XSSFWorkbook(pkg);
For a .xls
file, do that with
NPOIFSFileSystem fs = new NPOIFSFileSystem(new File("input.xls"), true);
HSSFWorkbook wb = new HSSFWorkbook(fs);
If you're using WorkbookFactory
, then you can do that by passing in null
for the password and setting the read-only flag with
Workbook wb = WorkbookFactory.create(new File("input.xlsx"), null, true);
In general, reading from an InputStream
is always read-only, it's with Files where there's an option for read-only vs read-write
See the constructor javadocs for a little bit more details, and the WorkbookFactory one too.