Bug 59634

Summary: XSSFWorkbook#close() violates contract from Workbook#close()
Product: POI Reporter: Michael <michael.holtermann>
Component: XSSFAssignee: POI Developers List <dev>
Status: RESOLVED FIXED    
Severity: normal CC: hartmut_juergens, jbatchelor, lianyining, scorpdaddy.ch
Priority: P2    
Version: 3.14-FINAL   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Bug Depends on: 59287    
Bug Blocks: 59678    
Attachments: TestCase demonstrating the issue

Description Michael 2016-05-25 14:46:53 UTC
Created attachment 33890 [details]
TestCase demonstrating the issue

According to Workbook#close() it should not have any effect on newly created workbooks.

This is true for HSSFWorkbooks.

For XSSFWorkbooks it's not possible to write the document to an OutputStream after calling #close().

Since I'm mostly creating Workbooks from scratch, I thought I can call #close() just after creation of Worbook, instead of somewhere later when the document was written to outside world.

Please see the attached test case that should demonstrate the issue.


(Side note: The documentation states #close() will close the underlying input resource the Workbook was created from (e.g. calls to constructor HSSFWorkbook(InputStream)?). Shouldn't be the creator of that InputStream responsible for closing that Stream?)

Regards,
Michael
Comment 1 Michael 2016-05-26 06:40:57 UTC
In addition it's not possible to read from the workbook after it has been closed. A NPE will be thrown.
Comment 2 Dominik Stadler 2016-05-29 10:25:57 UTC
For dicussion, the current javadoc for Workbook.close() is

     * Close the underlying input resource (File or Stream),
     *  from which the Workbook was read. After closing, the
     *  Workbook should no longer be used.
     * <p>This will have no effect newly created Workbooks.

HSSFWorkbook.close()

     * Closes the underlying {@link NPOIFSFileSystem} from which
     *  the Workbook was read, if any. Has no effect on Workbooks
     *  opened from an InputStream, or newly created ones.

XSSFWorkbook.close()

     * Closes the underlying {@link OPCPackage} from which this
     *  document was read, if there is one

We should probably rephrase those to state more in the order of "do not use at all after closing" and "it will close resources that have been passed in the constructor". This makes it as simple as possible and does not lead to very hard to find bugs if passed in resources are closed at some point.

This way would also be consistent with what many other Java-Closeable-instances will do when they receive some resource themselves, e.g. see FileInputStreamReader, FileOutputStreamWriter, ...
Comment 3 Michael 2016-06-08 08:08:51 UTC
Sounds legit. I'd support that solution.
Comment 4 Dominik Stadler 2016-06-09 09:40:07 UTC
*** Bug 59678 has been marked as a duplicate of this bug. ***
Comment 5 Dominik Stadler 2016-07-24 18:57:46 UTC
The JavaDoc was partly updated in r1749213 and further refined in r1753912 to state that the close() call may also invalidate other things and should only be called before work with the object is done.

I have also removed the "has no effect on newly created... ", as I don't think we should limit ourselves this way here, we should be able to do optimizations in the future which make use of this. All other Java Closables do it this way and thus let's do the same here.
Comment 6 Dominik Stadler 2016-07-26 05:54:21 UTC
*** Bug 59356 has been marked as a duplicate of this bug. ***
Comment 7 Dominik Stadler 2016-07-26 19:38:10 UTC
*** Bug 53613 has been marked as a duplicate of this bug. ***
Comment 8 Dominik Stadler 2017-02-21 13:56:08 UTC
*** Bug 60754 has been marked as a duplicate of this bug. ***