Major refactoring for Jackson 3.0: JSTEP-4, make Jackson exceptions unchecked (don't extend IOException)

31 views
Skip to first unread message

Tatu Saloranta

unread,
Jan 19, 2021, 12:18:55 AM1/19/21
to jacks...@googlegroups.com
After getting Jackson 2.12.1 patch released, to resolve urgent issues
with 2.12 (and creating 2.13 branches for developing next minor
versions, in due time), I have started working on Jackson 3.0 again.

As a brief historical background, work on 3.0 was started in 2017
after release of 2.9.0, original intention being that we wouldn't need
to go on double-digits minor version.
But during initial major changes for 3.0 it became clear that there
would be quite a bit room in 2.x series within existing constraints;
there would be benefit form coordinating changes in 3.0 and 2.x (to
ease transition); and finally the situation with polymorphic
deserialization (CVEs) escalated in a way that security features were
absolute required for 2.10 (as new API was needed).
And once I got started on this, I realized how much has still possible
to do with 2.x, especially in areas of "future-proofing" API: we now
have Builder-style construction available (even if full benefits only
come with 3.0) and better separation of format-specific features.
Downside, tho, is that 3.0 itself was put mostly on backburner -- yet
changes from 2.x have had to be merged still.

So it is now time to go back developing 3.0 with plans to release it
in some form during 2021.

The first major chunk to undertake is JSTEP-4:
https://github.com/FasterXML/jackson-future-ideas/wiki/JSTEP-4

"Replace checked JsonProcessingException with unchecked JacksonException"

First, why? JSTEP-4 page gives the full scope, but basically time of
checked exceptions with Java has sort of come to an end, with Java 8
Streams style processing, and the general incompatibility of checked
exceptions with closure-style programming.
While there was some convenience in using IOException (since low-level
I/O typically requires its handling or exposure anyway), it is time to
move on.
But while necessary, in my opinion, it is also a royal PITA to change:
effectively the whole codebase will need to be touched; every single
module will have some changes.
I believe it is worth the effort, but even so it definitely can only
be done with a major version upgrade.

Second: what / how?

The simplest way this could have been done would be to simply change
`JsonProcessingException` to extend `RuntimeException` instead of
`IOException` -- and then all the changes the necessitates.
JSTEP-4 page lists Github issues specifically related to core changes,
but the order is about as follows:

1. In 2.12, new "JacksonException" was added as a new base class for
`JsonProcessingException`. For 2.x it extends `IOException`. The idea
here is to create a new base class with both more generic name (not
just Json-things) and more descriptive (all exceptions Jackson itself
throws)
2. In 3.0 change `JacksonException` to extend `RuntimeException` instead
3. ... and then change A LOT of code (in Jackson 3.0, "master"
branch), mostly signatures but only that, across ALL Jackson packages
* Low-level i/o (read/write) code needs to catch and re-throw
things; added new "WrappedIOException" , as well as helper methods
(_wrapIOFailure(e))
* Most existing streaming and databind methods need to change
signature as they have had to expose `IOException` in 2.x -- but can
no longer do that
* Since `JacksonException` and subtypes are unchecked, we COULD
just drop declarations altogether, but I prefer trying to declare
likeliest ones for documentation purposes
4. For bonus points, do some more refactoring: JSTEP-4 page has
details, but basically exceptions with "Json" in their names will get
a replacement (namely, StreamReadException, StreamWriteException,
DatabindException) -- these can and will be added in 2.12, although
benefits are mostly for 3.0 -- but addition may help some of
transition

Now. At this point, I have created new branches -- named
"exp/jstep-4-for-3.0" for most modules -- on most repos, with
converted code.
I plan on starting to merge these tomorrow, (Tuesday, January 19th),
after which there will be some time during which some builds of the
"master" branch will fail, until things settle for a bit.

But I will also need help especially regarding 2 modules:

* jackson-module-kotlin
* jackson-module-scala

and will coordinate with their respective authors.

So... that was a mouthful. WDYT? Thoughts, suggestions, questions?

-+ Tatu +-

Mark Derricutt

unread,
Jan 20, 2021, 4:34:09 PM1/20/21
to jacks...@googlegroups.com

Could that switch from IOException to UncheckedIOException rather than directly moving to RuntimeException?

https://docs.oracle.com/javase/8/docs/api/java/io/UncheckedIOException.html

Tatu Saloranta

unread,
Jan 20, 2021, 4:41:04 PM1/20/21
to jacks...@googlegroups.com
On Wed, Jan 20, 2021 at 1:34 PM Mark Derricutt <ma...@talios.com> wrote:
>
> Could that switch from IOException to UncheckedIOException rather than directly moving to RuntimeException?
>
> https://docs.oracle.com/javase/8/docs/api/java/io/UncheckedIOException.html

I did consider that, but as per JSTEP-4 page:

"An alternative would be for it to extend UncheckedIOException (an
existing JDK type): problem is that one can only be created if there
is an actual IOException to wrap -- and this would only be true for
streaming read/write methods, but not for exceptions Jackson itself
throws."

so that at least for exceptions Jackson itself throws this would be
cumbersome as an `IOException` must be available for wrapping.
So actual decode/parse exceptions would always be wrapped if so (or
use bogus thing to wrap).

For IOExceptions from below it would be possible, but at this point I
prefer just having "WrappedIOException" that extends JacksonException;
this way everything that Jackson constructs or wraps will be of type
JacksonException.

-+ Tatu +-

>
>
>
>
> From: Tatu Saloranta <ta...@fasterxml.com>
> Reply: jacks...@googlegroups.com <jacks...@googlegroups.com>
> Date: 19 January 2021 at 6:18:42 PM
> To: jacks...@googlegroups.com <jacks...@googlegroups.com>
> Subject: [jackson-dev] Major refactoring for Jackson 3.0: JSTEP-4, make Jackson exceptions unchecked (don't extend IOException)
>
> 2. In 3.0 change `JacksonException` to extend `RuntimeException` instead
>
> --
> You received this message because you are subscribed to the Google Groups "jackson-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to jackson-dev...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/jackson-dev/CALYGm1y2N480q853TX809mej93hcMSkyd7hWMXcGfrqmfSPG-A%40mail.gmail.com.
Reply all
Reply to author
Forward
0 new messages