Reputation: 15028
I've stumbled across the following construct in-house:
class OurXmlWriter implements AutoCloseable {
private XMLStreamWriter streamWriter;
public OurXmlWriter(OutputStream stream) {
streamWriter = XMLOutputFactory.newInstance()
.createXMLStreamWriter(outputStream, "UTF-8");
}
@Override
public void close() {
try {
// is this allowed?
streamWriter.writeEndDocument();
} catch (XMLStreamException e) {
throw new RuntimeException();
} finally {
try {
streamWriter.close();
} catch (XMLStreamException e) {
throw new RuntimeException();
}
streamWriter = null;
}
}
}
The problem we've had with this is:
try (OurXmlWriter writer = new OurXmlWriter(new FileOutputStream("output.xml"))) {
writer.writeStartTag();
// write some data elements correctly
throw new OutOfMemoryError(); // that's not done explicitly but happens
}
This still calls close()
- which is fine as such but results in the xml being closed correctly (albeit unreliably because I'm sure it's not guaranteed to succeed after an Error
).
So the issue is basically that the XML is valid although we'd prefer it not be (so the output is not accidentally processed further in case the Error is missed). I'm pondering on how to best approach the situation - remove the end tag writing from close()
- which would require a lot of analysis retesting - or just not use try-with-resource to have control over whether it is called.
But the general question I have is:
Does the AutoCloseable
contract allow to still write into your resources when you're told to close()
? I've been reading the javadoc but it doesn't really explicitly disallow it. Am I missing something?
Upvotes: 3
Views: 666
Reputation: 719709
There are examples in the Java Standard class libraries where the close()
method has to perform a write. One such example is DeflaterOutputStream
whose javadoc states:
Writes remaining compressed data to the output stream and closes the underlying stream.
The point being that the last bit of a compressed stream can only be when you know that the stream is being closed. Flushing is not sufficient.
So combine this with @Kayaman and there is clear evidence that it is permitted for a stream to perform a write during close()
.
(And another example would be BufferedOutputStream
where close()
does the equivalent of a flush()
call if required.)
Upvotes: 1
Reputation: 73578
Basically there's nothing in the Javadoc to indicate it wouldn't be allowed, and in fact it says that
Note that unlike the
close
method ofjava.io.Closeable
thisclose
method is not required to be idempotent. In other words, calling thisclose
method more than once may have some visible side effect, unlikeCloseable.close
which is required to have no effect if called more than once.
which allows for side effects and doesn't even require the method to be idempotent. Considering that writing the end of the document is a relatively unsurprising side effect, I'd say that's alright. But of course just because it's not forbidden doesn't mean it's allowed, YMMV, opinion based, consult your in-house rulebook etc.
Upvotes: 2