jakartaee / jakartaee/jsonb-api
Jsonb close contract should be revisited
- Dominant language
- Java
- Stars
- 95
- Forks
- 41
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 35
Description
The `Json` methods that take IO streams should have their `#close()` contract revisited.
The current situation is:
- The methods taking an `InputStream` or `OutputStream` as an argument specify
"Upon a successful completion, the stream will be closed by this method."
- No contract exits for the method taking a `Reader` or `Writer` as an argument.
The issues with this are:
1. If the method throws an exception it is not specified wether the streams are closed. This leaves it unclear whether the caller is responsible for calling `#close()` in these cases.
2. It is inconsistent that the byte oriented streams (`InputStream` / `OutputStream`) are closed but the character oriented streams (`Reader` / `Writer`) are not.
Secondly, it is debatable whether `Json` should call `#close()` on the streams passed at all or whether that should be left to the caller. In my personal view it is idiomatic Java if the creator of a "resource", eg. IO stream, is responsible for its closing. Meaning generally calling code should look like this
```java
try (var ioStream = createIoStream()) {
jsonb.toJson(object, ioStream);
}
```
This also integrates well with static analysis tools looking for resource leaks. If a user wants to keep the IO stream open, eg. to implement line oriented JSON, they can do this by simply not calling `#close()`. Otherwise they would have to wrap the IO stream with one suppressing `#close()`.
This is similar to C where in general code calling `malloc` is also responsible for calling `free`. Functions are in general not expected to clean up memory they are passed.
I could find no written rule or recommendation for this but the majority of the JDK code I can find does not close IO streams passed as an argument and leaves calling `#close()` to the caller.
Examples from the JDK where calling `#close()` is left to the caller:
- `Properties#load(Reader)`
- `KeyStore#load(InputStream, char[])`
- `javax.imageio.ImageIO#read(InputStream)`
- `java.util.logging.LogManager#readConfiguration(InputStream)`
- `javax.tools.Tool#run(InputStream, OutputStream, OutputStream, String...)`
Examples from the JDK where `#close()` is only called if the method returns without throwing an exception (strict interpretation of the current `Jsonb` API contract)
- `Properties#loadFromXML(InputStream)`
Examples from the JDK with no specified contract for calling `#close()`, likely left to the caller:
- `javax.script.ScriptEngine#eval(Reader)`
- `javax.xml.parsers.DocumentBuilder#parse(InputStream)`
See also https://github.com/eclipse-ee4j/yasson/pull/586
Contributor guide
Research direction
Start by reviewing the Json methods that accept InputStream, OutputStream, Reader, and Writer, then read the discussion linked from issue #346 and pull request #586. Done means reaching and documenting a clear, consistent close contract for these methods, with the affected API behavior reflected in the project’s validation.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100