[Java][Spring] useRecords: allOf families as an interface and flat records

SE
7h ago
+1719-527

Sixth step towards #10490, allOf. With useRecords, a family one level below a parent with a discriminator becomes an interface for the parent, keeping the type-info block, and a flat record per child. A family that cannot, such as one with a redeclared property, stays classes and the reason is logged. Unlike the class, the parent can no longer be read under its own name.

@cachescrubber @welshm @MelleD @atextor @manedev79 @javisst @borsch @banlevente @Zomzog @martin-mfg @KannaKim

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Continues the useRecords work by turning allOf families into interfaces and flat records. A parent with a discriminator whose children extend it one level down becomes a sealed (with useSealed) interface that keeps the type-info annotations and declares an annotated accessor for each property; each child becomes a record that implements the parent, contains all family properties, and has a builder covering all components. Families that cannot be represented this way (a deeper hierarchy, a redeclared property, a parent with additionalProperties, a member bound from request parameters, and others) stay classes, and the log names the parent and the cause.

The parent can no longer be deserialized under its own name; only the children records are usable as JSON payloads.