Skip to content

[BUG][JAVA] Field named 'java' shadows package namespace causing compilation failure in v7.18.0+ #24835

Description

@janisz

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

When an OpenAPI schema contains a field named java, the generated Java code fails to compile in versions 7.18.0 and later. The issue is caused by using fully-qualified names like java.util.Locale.ROOT which get shadowed by instance fields named java.

openapi-generator version

7.18.0, 7.19.0, 7.25.0, and current master

OpenAPI declaration file content or url

openapi: 3.0.0
info:
  title: Minimal Reproduction
  version: 1.0.0
paths: {}
components:
  schemas:
    LanguageComponent:
      type: object
      required:
        - name
      properties:
        name:
          type: string
        java:
          $ref: '#/components/schemas/JavaComponent'
    JavaComponent:
      type: object
      properties:
        util:
          type: string

Generation Details

openapi-generator-cli generate \
  -g java \
  --library okhttp-gson \
  -i spec.yaml \
  -o ./generated

Steps to reproduce

  1. Save the above OpenAPI spec to spec.yaml
  2. Run the generation command
  3. Try to compile the generated code with mvn compile
  4. Observe compilation failure

Related issues/PRs

Suggest a fix

Root Cause: Commit 149fdcb (PR #22342) removed import java.util.Locale; and changed all occurrences to use the fully-qualified name java.util.Locale.ROOT. When a field is named java, it shadows the java.* package namespace, causing compilation failures.

Affected versions: 7.18.0 through 7.25.0 (and master)

Previously working: 7.16.0-7.17.0 (used import java.util.Locale; + Locale.ROOT)

Error Message:

[ERROR] non-static variable java cannot be referenced from a static context
[ERROR] cannot find symbol
  symbol:   variable util
  location: variable java of type JavaComponent

Generated Code (Broken):

package org.openapitools.client.model;

// No import for Locale (removed in commit 149fdcb61f6)

public class LanguageComponent {
  private JavaComponent java;  // Field shadows java.* package

  public static void validateJsonElement(JsonElement jsonElement) throws IOException {
    if (jsonElement == null) {
      if (!LanguageComponent.openapiRequiredFields.isEmpty()) {
        // BUG: 'java' refers to the field, not the package!
        throw new IllegalArgumentException(String.format(
          java.util.Locale.ROOT,  // <-- Compilation error
          "The required field(s) %s in LanguageComponent is not found",
          LanguageComponent.openapiRequiredFields.toString()
        ));
      }
    }
  }
}

Proposed Fix: Revert to using imports. Add import java.util.Locale; and use Locale.ROOT:

package org.openapitools.client.model;

import java.util.Locale;  // Add back the import

public class LanguageComponent {
  private JavaComponent java;

  public static void validateJsonElement(JsonElement jsonElement) throws IOException {
    if (jsonElement == null) {
      if (!LanguageComponent.openapiRequiredFields.isEmpty()) {
        throw new IllegalArgumentException(String.format(
          Locale.ROOT,  // Use short name - no conflict with field
          "The required field(s) %s in LanguageComponent is not found",
          LanguageComponent.openapiRequiredFields.toString()
        ));
      }
    }
  }
}

Why this works: Locale is a class name, not a field name, so it doesn't conflict with the java field.

Files to modify:

  • modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustache
  • modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/model.mustache
  • Similar files in other Java libraries (jersey2, jersey3, native, feign, etc.)

Alternative solutions:

  1. Mark java as a reserved word (breaking change for existing users)
  2. Use static import: import static java.util.Locale.ROOT;

Real-world impact: This affects the stackrox/jenkins-plugin where the StackRox API contains ScannerV1LanguageComponent with a java field.

Workaround (for affected users):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-antrun-plugin</artifactId>
  <version>3.1.0</version>
  <executions>
    <execution>
      <phase>process-sources</phase>
      <goals><goal>run</goal></goals>
      <configuration>
        <target>
          <replaceregexp
              file="${project.basedir}/target/generated-sources/.../LanguageComponent.java"
              match="(package .*;)"
              replace="\1&#10;&#10;import java.util.Locale;"
              byline="false"/>
          <replaceregexp
              file="${project.basedir}/target/generated-sources/.../LanguageComponent.java"
              match="java\.util\.Locale\.ROOT"
              replace="Locale.ROOT"
              byline="true"
              flags="g"/>
        </target>
      </configuration>
    </execution>
  </executions>
</plugin>

Regression timeline:

  • v7.14.0 and earlier: No Locale specified (incorrect but no shadowing)
  • v7.16.0-v7.17.0: Used Locale.ROOT with import ✅ (correct, no shadowing)
  • v7.18.0+: Uses java.util.Locale.ROOT without import ❌ (breaks with java field)

The irony is that commit 149fdcb was trying to avoid naming conflicts by using fully-qualified names, but actually created a new class of conflicts (field shadowing).

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

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions