fix: resolve Windows fill template copy failures (#1021) - #1034
Open
Mikkey-f wants to merge 4 commits into
Open
Conversation
…1021) The constructor opens the output file stream before copying the template. If initialization fails (e.g. missing template), the stream was never closed, leaving the target file locked on Windows. Close streams opened by the holder on failure; caller-provided streams remain the caller's responsibility.
…1021) URL.getPath() returns the encoded path. On Windows, template file names built with File.separator ('\') are percent-encoded as %5C in the resource URL, so the returned path pointed at a non-existent file and fill examples failed with 'Copy template failure'. Decode via URL.toURI() instead.
delei
reviewed
Aug 23, 2026
| initHandler(writeWorkbook, null); | ||
| copyTemplate(); | ||
| } catch (IOException e) { | ||
| closeOutputStreamIfOwned(); |
Member
There was a problem hiding this comment.
Could we gate closeOutputStreamIfOwned() with autoCloseStream instead of file != null?
autoCloseStream is more consistent with existing close behavior (while still not closing caller-provided streams).
Author
There was a problem hiding this comment.
Thanks for the suggestion — updated. The failure path in WriteWorkbookHolder now gates the close on autoCloseStream instead of file != null, which mirrors the success-path behavior. Callers using autoCloseStream(false) keep their streams unclosed on failure as well, and the test now sets autoCloseStream(false) explicitly to assert that contract.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Fixes the
Copy template failureerrors that the fill examples(
FillBasicExample,FillComplexExample) hit on Windows. Two root causes:1.
WriteWorkbookHolderleaks the output stream it opens when initialization failsThe constructor opens a
FileOutputStreamfor the target file before copyingthe template. When the copy fails (or any later initialization step throws),
the stream was never closed — the file stays locked on Windows. Unix lets you
delete an open file, which is why CI stayed green. This is a cross-platform
resource leak; Windows just surfaces it first.
Fix: wrap
initHandler+copyTemplateso the stream opened by the holder isclosed before the exception propagates. Caller-provided streams are untouched —
ownership stays with the caller.
2.
ExampleFileUtilreturns the percent-encoded URL pathURL.getPath()does not decode. On Windows, template file names built withFile.separator(\) are encoded as%5Cin the resource URL, so the returnedpath pointed at a file literally named
templates%5Clist.xlsx— which does notexist →
Copy template failure. On Unix the separator/needs no encoding,which is why CI passed.
Fix: decode via
URL.toURI()in a sharedtoFilePathhelper. This also fixespaths containing spaces or other reserved characters (
%20etc.).Tests
WriteWorkbookHolderOutputStreamTest(2 cases): the stream opened by theholder is closed on init failure (on Windows an open stream locks the file, so
deletion fails without the fix); caller-provided streams are not closed.
FillBasicExampleITCase,FillComplexExampleITCase) nowpass on Windows; they previously failed with
Copy template failure.fesod-sheet / fesod-sheet-examples),
spotless:checkandjavadoc:javadocpass.Closes #1021