OpenAPITools / OpenAPITools/openapi-generator

[BUG][JAVA][Spring] Required child attributes that override optional parent attributes are ignored by validation and required args constructors

Open
#22,686 0 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Bug
Dominant language
Java
Stars
26.8k
Forks
7.7k
PR merge metrics
PR metrics pending

Description

Bug Report Checklist
  • Have you provided a full/minimal spec to reproduce the issue?
  • Have you validated the input using an OpenAPI validator?
  • Have you tested with the latest master to confirm the issue still exists?
  • Have you searched for related issues/PRs?
  • What's the actual output vs expected output?
  • [Optional] Sponsorship to speed up the bug fix or feature request (example)
Description

With REF_AS_PARENT_IN_ALLOF=true, when a child type inherits an optional attribute and overrides it as required, the child type's required args constructor ignores that optional attribute.

For example, the following class is generated for the parent type, with the single required property accepted in the required args constructor:

public class ParentType {

  private @Nullable String optionalProp;

  private String requiredProp;

  public ParentType() {
    super();
  }

  /**
   * Constructor with only required parameters
   */
  public ParentType(String requiredProp) {
    this.requiredProp = requiredProp;
  }

  @Schema(name = "optionalProp", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
  @JsonProperty("optionalProp")
  public @Nullable String getOptionalProp() {
    return optionalProp;
  }

  // ...

  @NotNull 
  @Schema(name = "requiredProp", requiredMode = Schema.RequiredMode.REQUIRED)
  @JsonProperty("requiredProp")
  public String getRequiredProp() {
    return requiredProp;
  }

  // ...
}

When a child type inherits from ParentType and marks the inherited optionalProp as required, the following is generated:

public class ChildType extends ParentType {

  public ChildType() {
    super();
  }

  /**
   * Constructor with only required parameters
   */
  public ChildType(String optionalProp, String requiredProp) { // <-- `optionalProp` is ignored!
    super(requiredProp);
  }

  // ... no overridden getter for `optionalProp` with `@NotNull`
}

Note how the child's constructor accepts but then ignores the optionalProp attribute.
Also, @NotNull should be added to an overridden getter to enforce that the attribute is required in this child type.

One workaround to avoid accidental use of the constructor is to disable the generation of the required args constructor with -p generatedConstructorWithRequiredArgs=false (e.g. by Jackson, which as of Jackson 3 uses that constructor, resulting in optionalProp values from incoming JSON not to be bound).
Apart from refactoring the spec, I haven't found a workaround to have the correct validation annotations to be generated on the child type.

openapi-generator version

7.18.0, 7.19.0-SNAPSHOT

OpenAPI declaration file content or url
openapi: 3.0.3
info:
  title: Title
  version: "1"
paths:
  /test:
    get:
      responses:
        "200":
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ChildType'
components:
  schemas:
    ParentType:
      type: object
      properties:
        optionalProp:
          type: string
        requiredProp:
          type: string
      required:
       - requiredProp
    ChildType:
      allOf:
        - $ref: '#/components/schemas/ParentType'
        - type: object
          required:
            - optionalProp
Generation Details

java -jar openapi-generator-cli-7.19.0-SNAPSHOT.jar generate -g spring -i spec.yaml -o out --openapi-normalizer REF_AS_PARENT_IN_ALLOF=true

Suggest a Fix

The required args constructor of the child should set the affected attribute itself, and the child should override the parent's getter and add @NotNull.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the issue with the provided OpenAPI declaration and the Spring generation command using REF_AS_PARENT_IN_ALLOF=true. Inspect the generated ParentType and ChildType constructors, inherited properties, and validation annotations. The issue is done when ChildType passes the required inherited value to its parent and overrides the getter with @NotNull so validation and JSON binding work correctly.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
backend-api-design, tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.