Bug Report Checklist
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
- Save the above OpenAPI spec to
spec.yaml
- Run the generation command
- Try to compile the generated code with
mvn compile
- 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:
- Mark
java as a reserved word (breaking change for existing users)
- 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 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).
Bug Report Checklist
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 likejava.util.Locale.ROOTwhich get shadowed by instance fields namedjava.openapi-generator version
7.18.0, 7.19.0, 7.25.0, and current master
OpenAPI declaration file content or url
Generation Details
Steps to reproduce
spec.yamlmvn compileRelated issues/PRs
java.util.Localein Generated Classes #22342 (commit 149fdcb) - Introduced the regressionSuggest a fix
Root Cause: Commit 149fdcb (PR #22342) removed
import java.util.Locale;and changed all occurrences to use the fully-qualified namejava.util.Locale.ROOT. When a field is namedjava, it shadows thejava.*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:
Generated Code (Broken):
Proposed Fix: Revert to using imports. Add
import java.util.Locale;and useLocale.ROOT:Why this works:
Localeis a class name, not a field name, so it doesn't conflict with thejavafield.Files to modify:
modules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/pojo.mustachemodules/openapi-generator/src/main/resources/Java/libraries/okhttp-gson/model.mustacheAlternative solutions:
javaas a reserved word (breaking change for existing users)import static java.util.Locale.ROOT;Real-world impact: This affects the stackrox/jenkins-plugin where the StackRox API contains
ScannerV1LanguageComponentwith ajavafield.Workaround (for affected users):
Regression timeline:
Locale.ROOTwith import ✅ (correct, no shadowing)java.util.Locale.ROOTwithout import ❌ (breaks withjavafield)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).