[java] honor useJspecify in restclient/webclient ApiClient support class
PR: [java] honor useJspecify in restclient/webclient ApiClient support class
PR checklist
- Read the contribution guidelines.
- Pull Request title clearly describes the work and is named according to our commit naming conventions.
- File the PR against the correct branch:
master(no breaking changes). - Run the shell script
./bin/generate-samples.shto update all Petstore samples related to your fix. Regenerated the affected samples and committed the changes. - If your PR is targeting a particular programming language and you want a community member to review it, find them in the list of technical committee members and @ mention them.
cc Java technical committee: @bbdouglas @sdltj @martin-mfg @welshm @Bridgevine — and @jpfinne (author of useJspecify, #23256).
Description
Fixes #24054.
useJspecify=true converts model/API nullness to org.jspecify.annotations.Nullable, but the
restclient and webclient ApiClient support classes still hardcoded
import {{javaxPackage}}.annotation.Nullable;. That left every generated client mixing JSpecify
everywhere except the ApiClient, which kept jakarta.annotation.Nullable (or javax.*),
breaking "JSpecify-only" enforcement (ArchUnit / NullAway).
@Nullable is referenced as a simple name in both templates (createDefaultMapper(@Nullable DateFormat dateFormat)), so only the import line needs to be made conditional. No usage sites
change; behavior with useJspecify=false is unchanged. The other java-library ApiClient
templates do not import Nullable and are unaffected.
Diff
--- a/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache
@@ -79,7 +79,12 @@
import java.util.TimeZone;
import java.util.function.Supplier;
-import {{javaxPackage}}.annotation.Nullable;
+{{#useJspecify}}
+import org.jspecify.annotations.Nullable;
+{{/useJspecify}}
+{{^useJspecify}}
+import {{javaxPackage}}.annotation.Nullable;
+{{/useJspecify}}
{{#jsr310}}
--- a/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache
+++ b/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache
@@ -82,7 +82,12 @@
import java.util.Map.Entry;
import java.util.TimeZone;
-import {{javaxPackage}}.annotation.Nullable;
+{{#useJspecify}}
+import org.jspecify.annotations.Nullable;
+{{/useJspecify}}
+{{^useJspecify}}
+import {{javaxPackage}}.annotation.Nullable;
+{{/useJspecify}}
{{#jsr310}}
How to verify
./bin/generate-samples.sh bin/configs/java-restclient-*.yaml
./bin/generate-samples.sh bin/configs/java-webclient-*.yaml
Generate with useJspecify=true and confirm ApiClient.java imports
org.jspecify.annotations.Nullable; generate with useJspecify=false and confirm it still
imports {{javaxPackage}}.annotation.Nullable (jakarta or javax per useJakartaEe).
Notes
- Run
./bin/generate-samples.sh+./bin/utils/export_docs_generators.shbefore pushing so the
committed Petstore samples for anyuseJspecifyrestclient/webclient config are regenerated;
CI fails if samples are stale. - Commit message (their Conventional-ish convention):
[java] honor useJspecify in restclient/webclient ApiClient.
Summary by cubic
Honor useJspecify in Java restclient and webclient ApiClient templates by making the @Nullable import conditional: org.jspecify.annotations.Nullable when useJspecify=true, otherwise {{javaxPackage}}.annotation.Nullable.
This removes mixed nullness annotations in generated clients and keeps behavior unchanged when JSpecify is off.