[jaxrs-spec] useRecords pojo parity + records samples for every library in CI - #24562
Draft
Ignacio-Vidal wants to merge 3 commits into
Draft
[jaxrs-spec] useRecords pojo parity + records samples for every library in CI#24562Ignacio-Vidal wants to merge 3 commits into
Ignacio-Vidal wants to merge 3 commits into
Conversation
Adds a useRecords option to the jaxrs-spec generator. When useRecords=true, the concrete subtypes that implement a generated oneOf interface render as Java records instead of mutable classes. - JavaJAXRSSpecServerCodegen: useRecords option, and postProcessAllModels marks record-eligible implementors with x-jaxrs-record (no parent, no additional properties, implements a generated oneOf interface). - record.mustache renders the record; model.mustache routes x-jaxrs-record to it. - oneof_interface.mustache declares the discriminator accessor in record style (petType()) under useRecords so records satisfy the interface via their canonical accessors; sealed.mustache no longer marks a record final. - pom.mustache bumps java.version to 17 when useRecords (records need JDK 16+). - Adds testOneOfRecordImplementationGeneration and a jaxrs-spec-records sample (registered in the JDK17 samples workflow). useRecords is independent of useSealed. The feature stays opt-in; default jaxrs-spec output is unchanged.
Records stay scoped to the implementations of a generated oneOf interface (useOneOfInterfaces=true) and now additionally require useSealed=true. Models outside that hierarchy - ordinary pojos, inheritance participants and models with additionalProperties - are left untouched and keep rendering as classes. Brings record.mustache to feature parity with pojo.mustache for the records that are emitted: - defaults (scalar, enum, container) applied in a compact canonical constructor - x-is-jackson-optional-nullable properties render as JsonNullable components defaulting to undefined - byte[] properties get content-based equals/hashCode overrides (the implicit record equals compares arrays by reference) - password properties are masked in an explicit toString override - property doc annotations (@ApiModelProperty/@Schema/MicroProfile @Schema) emitted on the record components - generateBuilders produces a flat builder inside the record carrying the pojo field defaults, as a fluent replacement for setters - useRecords + withXml is rejected (JAXB requires mutable JavaBeans) The oneOf interface only drops the get-prefix from its accessor when records are actually emitted (useRecords and useSealed), so with useRecords alone the interface keeps getX() and still matches the classes implementing it.
useRecords is implemented in the shared model/record templates, so it applies to all five jaxrs-spec libraries, but only the default one had a sample. Add a records sample per library - helidon, kumuluzee, openliberty, quarkus and thorntail - and register all five in the JDK17 samples workflow so they are compiled on every push and pull request. Two things had to be fixed to make those samples compile: * Each library overrides pom.mustache and hardcoded Java 1.8 (helidon: 11), so a records or sealed sample could not build. Gate the compiler source/target on useSealed/useRecords exactly as the base pom.mustache already does. * record.mustache imported JsonNullable unconditionally. The import is already contributed through the imports block for the models that use it, so records with a nullable component carried a duplicate import, and records without one carried an unused import that fails to compile on the libraries whose pom does not ship jackson-databind-nullable. kumuluzee, openliberty and thorntail additionally set openApiNullable=false in their sample config: their poms omit jackson-databind-nullable while the pojo template imports JsonNullable whenever openApiNullable is on, which is a pre-existing issue unrelated to records (it reproduces with no records flags set at all). All six records samples plus jaxrs-spec-sealed build under JDK 17.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
1. Bring
useRecordsrecords to pojo feature parityRecords emitted for oneOf-interface implementations were missing behaviour the
pojo template already had. Each feature is gated on a vendor extension computed
in
postProcessAllModels, so records without the relevant properties areunaffected:
x-jaxrs-record-has-defaultsnull(scalar, enum, container, andJsonNullable→of(default)/undefined())x-jaxrs-record-has-byte-arrayequals/hashCodeusingArrays.*, since the implicit record versions compare arrays by referencex-jaxrs-record-has-passwordtoStringmaskingformat: passwordvaluesAlso: doc annotations on record components,
JsonNullable<T>component types,and
generateBuilderssupport via a flat static nested builder (records cannotuse the pojo's abstract builder hierarchy).
useRecords+withXmlnow throwsIllegalArgumentExceptionrather thangenerating something that cannot work.
2. Samples for every jaxrs-spec library, compiled in CI
useRecordslives in the shared model/record templates, so it applies to allfive libraries — but only the default one had a sample. This adds one per
library (helidon, kumuluzee, openliberty, quarkus, thorntail) and registers all
five in the JDK17 samples workflow, so they are compiled on every push and PR.
Two fixes were needed to make them compile:
Library poms hardcoded Java 1.8 (helidon: 11). Every library overrides
pom.mustache, so none inherited the base template'suseSealed/useRecords→ 17 gating. Applied the same gating to all five.
record.mustacheimportedJsonNullableunconditionally. The import isalready contributed through the imports block for models that use it, so
records with a nullable component carried a duplicate import, and records
without one carried an unused import that fails to compile on libraries
whose pom omits
jackson-databind-nullable.kumuluzee, openliberty and thorntail set
openApiNullable=falsein their sampleconfig. Their poms omit
jackson-databind-nullablewhile the pojo templateimports
JsonNullablewheneveropenApiNullableis on. That is pre-existing andunrelated to records — it reproduces with no records flags set at all — so it is
worked around here rather than fixed in this PR.
Verification
JavaJAXRSSpecServerCodegenTest, 730 Java codegen tests — all greenjaxrs-spec-sealedbuild under JDK 17Two unrelated pre-existing bugs found while testing this are split into their
own PRs rather than bundled here:
equalsNullablecalls whose helpers are never definedJsonNullablepropertySummary by cubic
Brings
useRecordsinjaxrs-specto full parity with POJOs for oneOf interface implementations and adds record samples for every library, compiled in CI. Also gates alljaxrs-specpoms to JDK 17 whenuseRecords/useSealedare enabled and documents the new option.useOneOfInterfaces=true,useSealed=true, anduseRecords=true(JDK 17). All other models remain classes.JsonNullable<T>components default toundefined(), content-basedequals/hashCodeforbyte[], maskedtoStringfor password fields, doc annotations on components, and a flatgenerateBuildersbuilder.useRecordscannot be combined withwithXml(throwsIllegalArgumentException).helidon,kumuluzee,openliberty,quarkus, andthorntail, and included them in the JDK 17 samples workflow. Fixed duplicateJsonNullableimport inrecord.mustache. Librarypom.mustachefiles now set source/target to 17 whenuseRecordsoruseSealed; docs updated to includeuseRecords.Written for commit 20a862f. Summary will update on new commits.