(and here’s what got added post 2.16.0-rc1)
After a bit over 3 weeks of pre-release testing, official Jackson 2.16.0 release is now out. Most things included were already there in 2.16.0-rc1 (see “2.16.0-rc1 Overview”), but aside from bug fixes — which pushed total count of included changes over 100! — there are two other important things added that you might want to hear about.
Support for Java Records on Android
Something I was not aware of until very recently is that not only are Java Records supported on recent Android SDKs, but that they can work on earlier Android versions using technique called “desugaring” (constructing classes similar to Records but without using new types like
java.lang.Record which weren’t included in already released older SDKs). (for full description of what this means see “Records in Android Studio Flamingo”)
But even if such “Android Records” can be used directly from Java code (when running on Android) they wouldn’t be supported by Jackson since they just look like “Weird POJOs”, and not Records — as they do not extend
java.lang.Record and — like regular Java Records — do not have either getters, setters, or
public Fields (requirement for auto-detection of properites). So before Jackson 2.16 you would need custom handling to support these types.
jackson-module-android-record to the rescue! Thanks to the contribution by Eran Leshem (thank you!) Jackson 2.16.0 now includes this module. It comes from
jackson-modules-base Github repo: https://github.com/FasterXML/jackson-modules-base/tree/2.17/android-record.
After registering the module as usual:
ObjectMapper mapper = JsonMapper.builder() // or mapper for other dataformats
// add other modules, configure, etc
these funny-looking Android-flavored Records should work similar to regular Plain Java Records (with all the usual caveats about first versions of new modules :) ).
Reproducible Builds for Jackson jars
An interesting and important effort — Reproducible Builds — has been working on various ecosystems, including JVM, for past couple of years.
The goal is to make it possible to repeat the build process used to produce any official artifact from source version to the artifact, and to be able to verify that the results are identical. This can serve as a verification that a given artifact has not been tampered with.
Although there are multiple potential benefits from builds used for producing globally shared artifacts (jars for Java, mostly), the most prominent one is to allow better verification of shared jars from Maven Central and other repositories. This can help improve overall security of Java build systems, by reducing the risk of supply-chain attacks where bad actors could “inject” modified jars to gain access to system that deploy said jars (or get data behind firewalls etc. etc).
Jackson project has worked with RB experts like Hervé Boutemy (who helped improve Jackson Maven build definitions) since Jackson 2.14.
But due to some tooling issues, the final piece was only put in place with Jackson 2.16 — thanks to the release of version 1.1 of excellent Moditect Maven build plug-in which is used to produce
module-info.class for JDK 8 builds (Jackson 2.16 still supports Java 8).
With that all official Jackson 2.16 artifacts should be verifiable.
This is a big milestone and hopefully helps not just Jackson project but also the Reproducible Build effort due to visibility of Jackson within Java ecosystem.
As I wrote in “Jackson 2.16-rc1 overview”, there is to be focused effort on Property Introspection rewrite, to sort of “close off” must-have changes for 2.x, to allow focus on making Jackson 3.0 reality.
But concurrent with that, I am thinking of getting back to Blogging MORE — maybe I’ll set up some actual goals for that for 2024. Like, maybe — just maybe! — I will commit to 12 Blogs for 2024. And the initial focus should probably be writing more about internal logic of Jackson, for things like:
- How does Property Detection actually work? (from POJO methods, fields, to actual serializers, deserializers)
- How to write “perfect” Serializers, Deserializers (for Scalar types, for Collections, Maps) — that is, what all aspects a properly working fully-functioning (de)serializer should support (and consequences of leaving them out)