Skip to content

0.8.0

Choose a tag to compare

@jwcarman jwcarman released this 07 Sep 05:39
· 30 commits to main since this release

Breaking changes

  • Every failure Codec.encode and Codec.decode report is now a
    CodecException from codec-core, in one of four families keyed to what the
    caller does next: InvalidValueException (fix the value),
    InvalidPayloadException (quarantine), UnsupportedFormatException (hold for
    a newer reader), TransientCodecException (retry). Anything catching
    IllegalArgumentException, IllegalStateException, UncheckedIOException,
    ClassCastException, or a Jackson/Gson/JSON-B/Fory/protobuf exception from
    encode/decode must catch the family (or CodecException) instead; the
    library's exception is still there as the cause. Construction-time exceptions
    are unchanged. codec-crypto's DecryptionException, KeyAccessException
    and EncryptionException keep their names and messages and now extend
    InvalidPayloadException, TransientCodecException and
    TransientCodecException respectively; an unknown envelope version or
    algorithm id is now UnsupportedFormatException, not a rejection.
    codec-versioned's UnknownVersionException now extends
    UnsupportedFormatException and is no longer a VersionedFormatException.
    See the new Handling failures
    guide.
  • Base32Codec.standard() and .hex() decode canonically: upper case only, and
    non-zero trailing bits in the final symbol are rejected (MZ====== is an
    error; MY====== is f). Callers who fed lower-case input opt back in with
    .caseInsensitive()

Changed

  • The build compiles with -Xlint:all,-processing,-unchecked -Werror: any javac
    warning in an enabled category fails compilation. unchecked is off because
    TypeRef.rawClass() is the one unchecked cast the type system cannot express;
    no other is permitted. The Gson, Protobuf and Fory backends no longer carry
    unchecked casts, and every exception class declares a serialVersionUID
  • codec-gson encodes by the codec's declared type (Gson.toJson(value, type))
    rather than the value's runtime class, matching what decode already did; a
    polymorphic value now serialises as its declared T
  • codec-fory: Apache Fory 1.1.0 → 1.7.1. ForyCodecFactory.of(...) takes Fory's
    defaults, and Fory's default changed from schema-consistent to compatible mode
    in 1.2.0 (without a release note), so payloads now carry their class schema:
    a reader whose class has gained or lost a field decodes correctly where
    schema-consistent mode silently returned a mis-shifted object. It costs a few
    bytes per class per message — a lone four-field record roughly doubles, a
    100-item order grows 2%; throughput is unchanged. Payloads written by earlier
    releases still decode, but bytes written by this release cannot be read by a
    schema-consistent Fory. Callers who want a specific mode build their own
    ThreadSafeFory and pass it to the constructor. Per Fory's security guidance
    the helper also sets deserializeUnknownClass(false), so a payload naming an
    unregistered class is rejected rather than materialised as an anonymous struct
  • JacksonCodecFactory, Jackson2CodecFactory, and GsonCodecFactory now reject a
    null engine or TypeRef with a labelled NullPointerException, matching the
    JSON-B and Fory factories; CompressionStreamCodec likewise rejects null on
    encode and decode before touching a stream, matching the other transforms

Added

  • TypeRef.rawClass(): the erased class of the captured type, typed Class<T>,
    so a backend can use the checked Class.cast instead of an unchecked cast of
    its own. It is the single unchecked cast in the codebase and its Javadoc says so
  • codec-versioned: VersionedCodec prefixes each payload with a magic and
    version header and dispatches decoding on it, so a storage strategy can change
    without a flag day — old versions stay registered and readable while an
    explicit write version makes a two-phase rollout possible
  • codec-benchmarks: JMH benchmarks for every compression transform (deflate
    and zstd at several levels), encoding, backend (a small record and a
    100-item object graph), and the envelope-encryption strategies (not
    published), with the results and a benchmarks page in the docs
  • Base32Codec.of(alphabet) and of(alphabet, pad): a strict codec over any
    32-symbol ASCII alphabet, with caseInsensitive() and aliasing(...) as
    decode-side opt-ins; crockford() (ULIDs), zBase32() and geohash()
    presets. The encode and decode loops are specialised for whole groups, about
    4x the throughput of the previous implementation

Documentation

  • Fixed a newcomer-walkthrough review's findings: the Composition guide's
    chaining sample and the Codec.andThen Javadoc snippet now build
    EnvelopeCodec (there is no AesCodec); the landing page states the Java
    25 / Spring Boot 4.x requirement; the landing page and Getting Started link
    Apache Kafka and Spring Data Redis; the Guides nav orders Handling Failures
    before Evolving Stored Formats; the Kafka guide covers
    RecordDeserializationException/ErrorHandlingDeserializer and declares
    its config variable; the Spring Boot guide states what happens with no
    backend on the classpath; and the Redis guide turns its auto-configuration
    prerequisites into a checklist and adds a codec.redis.cache.* properties
    table
  • Benchmarks re-run on 2026-09-06 with Fory 1.7.1, zstd-jni 1.5.7-15, and
    lz4-java 1.11.2: zstd decodes 1 MB payloads 18–29% faster at every level, the
    backend numbers and encoded sizes reflect Fory's compatible mode, and the Fory
    guide gains a schema-evolution section
  • Compression claims corrected against the benchmarks: the JDK codecs are
    fastest on payloads under a few hundred bytes, zstd's default level is not
    smaller than gzip on prose, and LZ4-HC is a decode-side optimisation
  • New guide, Evolving Stored Formats:
    how codec-versioned works, a worked upgrade, the fleet rollout order, and
    what belongs inside the versioned codec versus outside it
  • The aggregated Javadoc for every module is published with the site at
    jwcarman.github.io/codec/api, one set
    per release, built from the release tag