Skip to content

Extract jjq-value module compilable at Java 17 for broader ecosystem compatibility #46

Description

@stalep

Problem

jjq-core is compiled with <release>22</release>, which means any project that wants to use JqValue as a data type must also target Java 22+. This prevents adoption in ecosystems with older Java baselines.

Concrete use case: We are building a Jenkins plugin for h5m (the next-generation Horreum). Jenkins requires Java 17 (as of Jenkins 2.479+). The plugin needs to send and receive JSON data from h5m's REST API, which uses JqValue as its JSON representation. Ideally the plugin would use JqValue directly for type safety and to avoid a separate JSON library (Jackson) in the data path. However, the plugin cannot depend on jjq-core because the compiled bytecode requires Java 22, while Jenkins runs on Java 17.

Analysis

I audited the value types in io.hyperfoil.tools.jjq.value (JqValue, JqNull, JqBoolean, JqNumber, JqString, JqArray, JqObject, JqValues, JqTypeError, BytOutput, SwarUtil). The language features they use are:

Feature Java version (final) Used in
sealed interface + permits Java 17 JqValue.java:8-9
record Java 16 JqObject.java:543 (MergeFrame)
Pattern matching for instanceof Java 16 JqString.java, JqValues.java (multiple sites)
List.getFirst() / List.getLast() Java 21 (SequencedCollection) JqArray.java:164,167,275 (3 call sites)

The only API requiring Java 21+ is List.getFirst()/getLast() — 3 call sites in JqArray.java. These can be trivially replaced with list.get(0) and list.get(list.size() - 1) without any performance impact (ArrayList random access is O(1)).

All imports in the value types come from java.base (java.math, java.util, java.io, java.nio, java.lang.invoke). There are zero external runtime dependencies.

The jq engine code (lexer, parser, AST, evaluator, builtins, VM) likely uses Java 22+ features more extensively and should stay at Java 22.

Proposal

Extract a jjq-value module containing only the value type classes from io.hyperfoil.tools.jjq.value:

jjq-value/
  src/main/java/io/hyperfoil/tools/jjq/value/
    JqValue.java
    JqNull.java
    JqBoolean.java
    JqNumber.java
    JqString.java
    JqArray.java
    JqObject.java
    JqValues.java
    JqTypeError.java
    BytOutput.java
    SwarUtil.java

With:

  • <maven.compiler.release>17</maven.compiler.release>
  • jjq-core depends on jjq-value (the engine uses these types)
  • Replace 3x List.getFirst()/getLast() calls in JqArray.java with Java 17-compatible equivalents

Constraints

  • Must not affect performance. The replacement for getFirst()/getLast() is get(0)/get(size()-1) on ArrayList, which has identical performance (both are O(1) direct array index access — getFirst()/getLast() are just convenience methods added in Java 21).
  • No API changes to any value type.
  • jjq-core continues at Java 22 — only the value types module drops to Java 17.

Benefits

  • Jenkins plugins, Gradle plugins, and other Java 17+ tools can use JqValue as a JSON data type
  • h5m's REST API consumers get type-safe JSON handling without needing Java 22
  • Zero-dependency value types module (jjq-value has no transitive deps, same as today)
  • The jjq-jackson, jjq-jakarta, and jjq-fastjson2 adapter modules can also lower their Java requirement since they primarily bridge external libraries to JqValue

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions