Skip to content

[JAVA] [Spring] JSpecify, fix nullable + required field - #24711

Draft
jpfinne wants to merge 26 commits into
OpenAPITools:masterfrom
jpfinne:bug/nullableRequired
Draft

[JAVA] [Spring] JSpecify, fix nullable + required field#24711
jpfinne wants to merge 26 commits into
OpenAPITools:masterfrom
jpfinne:bug/nullableRequired

Conversation

@jpfinne

@jpfinne jpfinne commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

fix #24686

For a type:

type: object
required:
  - name
properties:
   name:
     type: string
     nullable: true

Ensure that the following json are accepted:

json valid
{ "name": "john" } yes
{ "name": null } yes
{ } no

Keep jspecify @Nullable annotation for builder with an improved RemoveAnnotationLambda. Other annotations like @Valid are still removed.
Ensure setter, chain setters, builder, constructors contain the correct JSpecify @Nullable annotation.

Add more combination of readonly, nullable and required in the samples.

For nullable attributes:

Update @Schema annotation to add nullable=true

For required+nullable attributes:

For Spring:

  • openapiNullable=false: remove @NotNull
  • openapiNullable=true: assign null to JsonNullable<> field,. so that bean validation uses @NotNull on getter to detect missing attributes (like { })

For java:

  • correct missing JSpecify, javax or jakarta @Nullable annotation

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

Fixes Java and Spring handling of required+nullable under jspecify and aligns Bean Validation. Previously these fields were non-null and Spring added @NotNull; now required+nullable are annotated @Nullable on fields, constructors, builders, and chain setters, and @NotNull is emitted only when appropriate. Also adds nullable = true in @Schema for nullable properties and updates FileApi to return FileContent JSON.

  • Java/Spring templates: add constructor and chain-setter partials for nullable args; standardize nullable_var_annotations.mustache; expose removeAnnotations lambda to templates; compute fully qualified nullable annotation from javaxPackage so javax.annotation.Nullable is not emitted under jspecify.
  • Spring Bean Validation: move @NotNull to notNull.mustache; emit only when “required AND not readOnly AND (not nullable OR openApiNullable)”; keep @NotNull for JsonNullable fields. With openApiNullable=true, required+nullable JsonNullable<T> fields now initialize to null (not undefined()), so validation can trigger.
  • OpenAPI/annotations: generate @Schema(..., nullable = true) for nullable properties across Java library templates.
  • Samples/tests: add RequiredAndNullable schema and endpoints; assert constructor/chain-setter annotations and absence of javax.annotation.Nullable under jspecify; change FileApi to return FileContent with Accept: application/json.

Migration

  • Spring generators no longer emit @NotNull for required+nullable unless you enable openApiNullable. If you relied on Bean Validation to reject nulls without openApiNullable, add explicit constraints or mark fields non-nullable.
  • When openApiNullable is enabled, required+nullable JsonNullable<T> fields now default to null. If you depended on undefined(), update handling accordingly.

Written for commit f11445b. Summary will update on new commits.

Review in cubic

@jpfinne jpfinne changed the title Bug/nullable required [JAVA] [Spring] Fix nullable field + required/readonly Aug 15, 2026
@jpfinne
jpfinne marked this pull request as ready for review August 15, 2026 12:34

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7 issues found across 125 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/FileApi.java">

<violation number="1" location="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/FileApi.java:234">
P2: When the JVM default charset is not UTF-8, this response parser corrupts non-ASCII `FileContent` values before Jackson deserializes them. Decode JSON with `StandardCharsets.UTF_8` explicitly.</violation>
</file>

<file name="samples/client/petstore/java/webclient-springBoot4-jackson3-jspecify/README.md">

<violation number="1" location="samples/client/petstore/java/webclient-springBoot4-jackson3-jspecify/README.md:98">
P3: The new README example `FileContent result = apiInstance.fileIdGet(id);` does not compile: this is a reactive WebClient client and `FileApi#fileIdGet` returns `Mono<FileContent>`, not `FileContent`. Assigning the `Mono` to a `FileContent` variable is a type mismatch, and the reactive result is never subscribed. Use `Mono<FileContent>` plus `.block()` (or subscribe) in the example, consistent with the actual returned type.</violation>
</file>

<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java">

<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java:7186">
P2: These jspecify tests verify that a required non-nullable property (`getRequiredDt`) still gets `@NotNull`, but they never assert that the required+nullable properties (`getStr`/`setStr`) in the new `RequiredAndNullable` model do NOT get `@NotNull` — which is the core behavior this PR changes. The `fileContains` signatures such as `"@Nullable String getStr()"` are substring matches and still pass even if `@NotNull` were emitted as `@NotNull @Nullable String getStr()`, so they give false confidence. Add an explicit negative assertion, e.g. `.assertMethod("getStr").assertMethodAnnotations().doesNotContainWithName("NotNull")` (and likewise for `setStr`), so a regression that re-adds `@NotNull` on required+nullable members fails these tests.</violation>
</file>

<file name="samples/client/petstore/java/restclient-springBoot4-jackson3-jspecify-openapiNullable/src/main/java/org/openapitools/client/model/FileContent.java">

<violation number="1" location="samples/client/petstore/java/restclient-springBoot4-jackson3-jspecify-openapiNullable/src/main/java/org/openapitools/client/model/FileContent.java:92">
P2: The @JsonCreator constructor parameters for the nullable fields `size` and `virusScan` are missing the `@Nullable` annotation, even though the same fields are emitted as `@Nullable` on their getters and on the builder chain-setters (`size(@Nullable Integer size)`, `virusScan(@Nullable VirusScanEnum virusScan)`). The `@JsonCreator` constructor comes from the readOnly-constructor branch of `pojo.mustache` (restclient, lines ~115-124), which still renders `{{{datatypeWithEnum}}}` without the `{{>nullableArgumentWithEnum}}` helper applied to the all-args constructor at line 133. So for this all-readOnly model, every nullable constructor arg lacks `@Nullable`. This contradicts the PR's stated goal (emit jspecify `@Nullable` on nullable constructor args) and is inconsistent with `RequiredAndNullable.java` in the same sample, whose all-args constructor carries `@Nullable`. Update the readOnly constructor rendering to use the nullable args helper too.</violation>
</file>

<file name="modules/openapi-generator/src/main/resources/Java/nullableArgument_builder.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/nullableArgument_builder.mustache:1">
P2: With `useJspecify`, this wrapper removes the `@Nullable` emitted for nullable builder arguments, making them unannotated non-null types. Strip annotations only from raw `datatypeWithEnum`, while rendering `nullable_var_annotations` outside `removeAnnotations`.</violation>
</file>

<file name="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/RequiredAndNullableApi.java">

<violation number="1" location="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/RequiredAndNullableApi.java:155">
P2: When a server controls `Content-Disposition`, `prepareDownloadFile` can write outside its temporary directory because it resolves the raw filename. Reduce the filename to a basename before resolving it.</violation>

<violation number="2" location="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/RequiredAndNullableApi.java:234">
P2: On a JVM whose default charset is not UTF-8, non-ASCII JSON response data is decoded incorrectly before Jackson deserializes it. Decode the response body as UTF-8 explicitly.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic




String responseBody = new String(localVarResponseBody.readAllBytes());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When the JVM default charset is not UTF-8, this response parser corrupts non-ASCII FileContent values before Jackson deserializes them. Decode JSON with StandardCharsets.UTF_8 explicitly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/FileApi.java, line 234:

<comment>When the JVM default charset is not UTF-8, this response parser corrupts non-ASCII `FileContent` values before Jackson deserializes them. Decode JSON with `StandardCharsets.UTF_8` explicitly.</comment>

<file context>
@@ -217,20 +221,31 @@ public ApiResponse<Void> fileIdGetWithHttpInfo(String id, Map<String, String> he
+
+        
+        
+        String responseBody = new String(localVarResponseBody.readAllBytes());
+        FileContent responseValue = responseBody.isBlank()? null: memberVarObjectMapper.readValue(responseBody, new TypeReference<FileContent>() {});
+        
</file context>
Suggested change
String responseBody = new String(localVarResponseBody.readAllBytes());
String responseBody = new String(localVarResponseBody.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);




String responseBody = new String(localVarResponseBody.readAllBytes());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: On a JVM whose default charset is not UTF-8, non-ASCII JSON response data is decoded incorrectly before Jackson deserializes it. Decode the response body as UTF-8 explicitly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/RequiredAndNullableApi.java, line 234:

<comment>On a JVM whose default charset is not UTF-8, non-ASCII JSON response data is decoded incorrectly before Jackson deserializes it. Decode the response body as UTF-8 explicitly.</comment>

<file context>
@@ -0,0 +1,289 @@
+
+        
+        
+        String responseBody = new String(localVarResponseBody.readAllBytes());
+        RequiredAndNullable responseValue = responseBody.isBlank()? null: memberVarObjectMapper.readValue(responseBody, new TypeReference<RequiredAndNullable>() {});
+        
</file context>
Suggested change
String responseBody = new String(localVarResponseBody.readAllBytes());
String responseBody = new String(localVarResponseBody.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already existed

File file = null;
if (filename != null) {
java.nio.file.Path tempDir = java.nio.file.Files.createTempDirectory("swagger-gen-native");
java.nio.file.Path filePath = java.nio.file.Files.createFile(tempDir.resolve(filename));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When a server controls Content-Disposition, prepareDownloadFile can write outside its temporary directory because it resolves the raw filename. Reduce the filename to a basename before resolving it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/RequiredAndNullableApi.java, line 155:

<comment>When a server controls `Content-Disposition`, `prepareDownloadFile` can write outside its temporary directory because it resolves the raw filename. Reduce the filename to a basename before resolving it.</comment>

<file context>
@@ -0,0 +1,289 @@
+    File file = null;
+    if (filename != null) {
+      java.nio.file.Path tempDir = java.nio.file.Files.createTempDirectory("swagger-gen-native");
+      java.nio.file.Path filePath = java.nio.file.Files.createFile(tempDir.resolve(filename));
+      file = filePath.toFile();
+      tempDir.toFile().deleteOnExit();   // best effort cleanup
</file context>
Suggested change
java.nio.file.Path filePath = java.nio.file.Files.createFile(tempDir.resolve(filename));
java.nio.file.Path filePath = java.nio.file.Files.createFile(tempDir.resolve(java.nio.file.Path.of(filename).getFileName()));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already existed

).fileDoesNotContain(
"javax.annotation.Nullable",
"jakarta.annotation.Nullable")
.assertMethod("getRequiredDt").assertMethodAnnotations().containsWithName("NotNull").containsWithName("Valid");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: These jspecify tests verify that a required non-nullable property (getRequiredDt) still gets @NotNull, but they never assert that the required+nullable properties (getStr/setStr) in the new RequiredAndNullable model do NOT get @NotNull — which is the core behavior this PR changes. The fileContains signatures such as "@Nullable String getStr()" are substring matches and still pass even if @NotNull were emitted as @NotNull @Nullable String getStr(), so they give false confidence. Add an explicit negative assertion, e.g. .assertMethod("getStr").assertMethodAnnotations().doesNotContainWithName("NotNull") (and likewise for setStr), so a regression that re-adds @NotNull on required+nullable members fails these tests.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/java/org/openapitools/codegen/java/spring/SpringCodegenTest.java, line 7186:

<comment>These jspecify tests verify that a required non-nullable property (`getRequiredDt`) still gets `@NotNull`, but they never assert that the required+nullable properties (`getStr`/`setStr`) in the new `RequiredAndNullable` model do NOT get `@NotNull` — which is the core behavior this PR changes. The `fileContains` signatures such as `"@Nullable String getStr()"` are substring matches and still pass even if `@NotNull` were emitted as `@NotNull @Nullable String getStr()`, so they give false confidence. Add an explicit negative assertion, e.g. `.assertMethod("getStr").assertMethodAnnotations().doesNotContainWithName("NotNull")` (and likewise for `setStr`), so a regression that re-adds `@NotNull` on required+nullable members fails these tests.</comment>

<file context>
@@ -7179,7 +7180,10 @@ public void testJspecify(String library, int springBootVersion) throws IOExcepti
+                ).fileDoesNotContain(
+                        "javax.annotation.Nullable",
+                        "jakarta.annotation.Nullable")
+                .assertMethod("getRequiredDt").assertMethodAnnotations().containsWithName("NotNull").containsWithName("Valid");
         JavaFileAssert.assertThat(files.get("FooApi.java"))
                 .assertTypeAnnotations().doesImportAnnotation("org.jspecify.annotations.Nullable").toType()
</file context>

String id = "id_example"; // String |
try {
apiInstance.fileIdGet(id);
FileContent result = apiInstance.fileIdGet(id);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The new README example FileContent result = apiInstance.fileIdGet(id); does not compile: this is a reactive WebClient client and FileApi#fileIdGet returns Mono<FileContent>, not FileContent. Assigning the Mono to a FileContent variable is a type mismatch, and the reactive result is never subscribed. Use Mono<FileContent> plus .block() (or subscribe) in the example, consistent with the actual returned type.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/webclient-springBoot4-jackson3-jspecify/README.md, line 98:

<comment>The new README example `FileContent result = apiInstance.fileIdGet(id);` does not compile: this is a reactive WebClient client and `FileApi#fileIdGet` returns `Mono<FileContent>`, not `FileContent`. Assigning the `Mono` to a `FileContent` variable is a type mismatch, and the reactive result is never subscribed. Use `Mono<FileContent>` plus `.block()` (or subscribe) in the example, consistent with the actual returned type.</comment>

<file context>
@@ -95,7 +95,8 @@ public class FileApiExample {
         String id = "id_example"; // String | 
         try {
-            apiInstance.fileIdGet(id);
+            FileContent result = apiInstance.fileIdGet(id);
+            System.out.println(result);
         } catch (ApiException e) {
</file context>

Comment thread modules/openapi-generator/src/test/resources/3_0/java/jspecify.yaml Outdated
@jpfinne jpfinne changed the title [JAVA] [Spring] Fix nullable field + required/readonly [JAVA] [Spring] JSpecify, fix nullable field + required Aug 15, 2026
@jpfinne jpfinne changed the title [JAVA] [Spring] JSpecify, fix nullable field + required [JAVA] [Spring] JSpecify, fix nullable + required field Aug 15, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 27 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

@jpfinne
jpfinne marked this pull request as draft August 16, 2026 05:26
Make JSonNullable<> field = null for nullable+required
@jpfinne
jpfinne marked this pull request as ready for review August 16, 2026 08:27

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 197 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="samples/client/petstore/java/resttemplate-springBoot4-jackson3-jspecify/src/main/java/org/openapitools/client/model/RequiredAndNullable.java">

<violation number="1" location="samples/client/petstore/java/resttemplate-springBoot4-jackson3-jspecify/src/main/java/org/openapitools/client/model/RequiredAndNullable.java:17">
P3: `java.util.Arrays` is imported twice (and is unused in the file body). The template's generic import block and the per-array-var import block each emit `import java.util.Arrays;`, producing lines 17 and 24. Remove the redundant duplicate import in the generated model (the root cause is the template emitting the same import from two sources).</violation>
</file>

<file name="samples/openapi3/server/petstore/springboot-4-jspecify-useOptional/src/main/java/org/openapitools/model/RequiredAndNullable.java">

<violation number="1" location="samples/openapi3/server/petstore/springboot-4-jspecify-useOptional/src/main/java/org/openapitools/model/RequiredAndNullable.java:161">
P2: In `addListItem`, when `_list` is a present-but-null `JsonNullable` (i.e. created via `JsonNullable.of(null)`), the guard passes but the add throws an NPE. This is reachable: the public constructor takes `@Nullable List<String> _list` and wraps it with `JsonNullable.of(_list)` (line 57), so `new RequiredAndNullable(..., null)` yields `_list = JsonNullable.of(null)`; then `!this._list.isPresent()` is false, `this._list.get()` returns null, and `.add(_listItem)` throws. Guard on whether the wrapped value is actually a non-null list before calling `.get().add(...)`.</violation>
</file>

<file name="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java">

<violation number="1" location="modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java:4720">
P3: testJspecify uses the bare string key `"annotationLibrary"` while testJspecify_openapiNullable (added in this same PR) uses the `ANNOTATION_LIBRARY` constant for the identical setting. Import and use the `ANNOTATION_LIBRARY` constant from `DocumentationProviderFeatures` to keep the two tests consistent and avoid typos in the magic string.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment on lines +161 to +166
public RequiredAndNullable addListItem(String _listItem) {
if (this._list == null || !this._list.isPresent()) {
this._list = JsonNullable.of(new ArrayList<>());
}
this._list.get().add(_listItem);
return this;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: In addListItem, when _list is a present-but-null JsonNullable (i.e. created via JsonNullable.of(null)), the guard passes but the add throws an NPE. This is reachable: the public constructor takes @Nullable List<String> _list and wraps it with JsonNullable.of(_list) (line 57), so new RequiredAndNullable(..., null) yields _list = JsonNullable.of(null); then !this._list.isPresent() is false, this._list.get() returns null, and .add(_listItem) throws. Guard on whether the wrapped value is actually a non-null list before calling .get().add(...).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/openapi3/server/petstore/springboot-4-jspecify-useOptional/src/main/java/org/openapitools/model/RequiredAndNullable.java, line 161:

<comment>In `addListItem`, when `_list` is a present-but-null `JsonNullable` (i.e. created via `JsonNullable.of(null)`), the guard passes but the add throws an NPE. This is reachable: the public constructor takes `@Nullable List<String> _list` and wraps it with `JsonNullable.of(_list)` (line 57), so `new RequiredAndNullable(..., null)` yields `_list = JsonNullable.of(null)`; then `!this._list.isPresent()` is false, `this._list.get()` returns null, and `.add(_listItem)` throws. Guard on whether the wrapped value is actually a non-null list before calling `.get().add(...)`.</comment>

<file context>
@@ -0,0 +1,334 @@
+    return this;
+  }
+
+  public RequiredAndNullable addListItem(String _listItem) {
+    if (this._list == null || !this._list.isPresent()) {
+      this._list = JsonNullable.of(new ArrayList<>());
</file context>
Suggested change
public RequiredAndNullable addListItem(String _listItem) {
if (this._list == null || !this._list.isPresent()) {
this._list = JsonNullable.of(new ArrayList<>());
}
this._list.get().add(_listItem);
return this;
public RequiredAndNullable addListItem(String _listItem) {
if (this._list == null || !this._list.isPresent() || this._list.get() == null) {
this._list = JsonNullable.of(new ArrayList<>());
}
this._list.get().add(_listItem);
return this;
}

package org.openapitools.client.model;

import java.util.Objects;
import java.util.Arrays;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: java.util.Arrays is imported twice (and is unused in the file body). The template's generic import block and the per-array-var import block each emit import java.util.Arrays;, producing lines 17 and 24. Remove the redundant duplicate import in the generated model (the root cause is the template emitting the same import from two sources).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At samples/client/petstore/java/resttemplate-springBoot4-jackson3-jspecify/src/main/java/org/openapitools/client/model/RequiredAndNullable.java, line 17:

<comment>`java.util.Arrays` is imported twice (and is unused in the file body). The template's generic import block and the per-array-var import block each emit `import java.util.Arrays;`, producing lines 17 and 24. Remove the redundant duplicate import in the generated model (the root cause is the template emitting the same import from two sources).</comment>

<file context>
@@ -0,0 +1,328 @@
+package org.openapitools.client.model;
+
+import java.util.Objects;
+import java.util.Arrays;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
</file context>

USE_ABSTRACTION_FOR_FILES, true
),
USE_ABSTRACTION_FOR_FILES, true,
"annotationLibrary", "swagger2"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: testJspecify uses the bare string key "annotationLibrary" while testJspecify_openapiNullable (added in this same PR) uses the ANNOTATION_LIBRARY constant for the identical setting. Import and use the ANNOTATION_LIBRARY constant from DocumentationProviderFeatures to keep the two tests consistent and avoid typos in the magic string.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java, line 4720:

<comment>testJspecify uses the bare string key `"annotationLibrary"` while testJspecify_openapiNullable (added in this same PR) uses the `ANNOTATION_LIBRARY` constant for the identical setting. Import and use the `ANNOTATION_LIBRARY` constant from `DocumentationProviderFeatures` to keep the two tests consistent and avoid typos in the magic string.</comment>

<file context>
@@ -4697,27 +4697,28 @@ public void testRestClientMultipartFormParamsGuardAgainstEmptyLists() {
-                        USE_ABSTRACTION_FOR_FILES, true
-                ),
+                        USE_ABSTRACTION_FOR_FILES, true,
+                        "annotationLibrary", "swagger2"
+                        ),
                 codegenConfigurator ->
</file context>

@jpfinne
jpfinne marked this pull request as draft August 16, 2026 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] [Java] [spring] Properties that are both required and nullable are marked NotNull

1 participant