Skip to content

[JAVA] add JSpecify @Nullable in builder and singleRequestParameter - #24648

Open
jpfinne wants to merge 38 commits into
OpenAPITools:masterfrom
jpfinne:feature/jspecify_java_builder
Open

[JAVA] add JSpecify @Nullable in builder and singleRequestParameter#24648
jpfinne wants to merge 38 commits into
OpenAPITools:masterfrom
jpfinne:feature/jspecify_java_builder

Conversation

@jpfinne

@jpfinne jpfinne commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

When useJspecify=true, add the @Nullable annotation to the java builders.
Add @Nullable annotation to singleRequestParameters for restclient and webclient libraries.

Regenerate jspecify samples with more options to improve coverage.

  generateBuilders: true
  generateConstructorWithAllArgs: true
  useSingleRequestParameter: true

Tags added to jspecify sample -> multiple generate api classes.
Add sample for restClient+jspecify+openapiNullable

The builders are not modified when useJspecify=false (it can be done in a # PR)

For simplicity, this PR does NOT cover:

  • resttemplate api
  • ApiClient with multiple jspecify warning due to package being @NullMarked

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

Adds org.jspecify.annotations.Nullable to Java builder parameters and the public toIndentedString when useJspecify is enabled. Regenerates Java samples with tag-split APIs, and adds a Spring Boot 4 restclient sample with openApiNullable to CI.

  • New Features

    • Annotate builder parameters via new Java/nullableArgument_builder.mustache; public toIndentedString(Object) annotated (private helpers stay unannotated).
    • Centralized @Nullable import via Java/nullable-import.mustache.
    • Regenerated jspecify samples with tags (APIs split into FooApi, FileApi, UploadApi) and enabled generateBuilders, all-args constructors, useSingleRequestParameter, and useTags across native-jackson3-jspecify, restclient, resttemplate, and webclient.
    • Added restclient-springBoot4-jackson3-jspecify-openapiNullable sample; included in the JDK17 workflow.
  • Bug Fixes

    • More robust @Nullable handling: support trailing-space detection in AbstractJavaCodegen and refine spacing in nullable_var_annotations.mustache; fixed extra space in webclient single-request toIndentedString.
    • Updated tests for builder annotations, tag-based API splits, and simplified Spring jspecifyLibraries data provider.

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

Review in cubic

jpfinne added 25 commits May 11, 2026 14:26
…ure/jspecify_java_builder

# Conflicts:
#	modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java
#	samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/model/Foo.java
#	samples/openapi3/server/petstore/springboot-4-jspecify/src/main/java/org/openapitools/api/FooApi.java
#	samples/openapi3/server/petstore/springboot-4-jspecify/src/main/java/org/openapitools/model/Foo.java
@jpfinne jpfinne changed the title [JAVA] add JSpecify @Nullable annotation to builder [JAVA] add JSpecify @Nullable annotation to builder and toIndentedString() Aug 8, 2026
@jpfinne
jpfinne marked this pull request as ready for review August 8, 2026 16:56

@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.

2 issues found and verified against the latest diff

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="modules/openapi-generator/src/main/resources/Java/nullable_var_annotations.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/nullable_var_annotations.mustache:1">
P2: `useJspecify` request-wrapper fields, constructors, accessors, and record components lose `@Nullable` when `useSingleRequestParameter` is enabled, since this lambda suppresses it without a following `jSpecifyDatatype`. Render those declarations via the nullable datatype/argument partial (or preserve the annotation in direct-use contexts).</violation>
</file>

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

<violation number="1" location="samples/client/petstore/java/restclient-springBoot4-jackson3-jspecify-openapiNullable/src/main/java/org/openapitools/client/model/Foo.java:29">
P3: The generated import block contains three duplicated imports (java.util.Arrays, org.openapitools.jackson.nullable.JsonNullable, com.fasterxml.jackson.annotation.JsonIgnore). Legal but untidy generated output; this sample adds two more duplicates than the sibling jspecify sample, so the new openapiNullable template path is emitting redundant imports. Remove the duplicates.</violation>
</file>

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

Re-trigger cubic

Comment thread modules/openapi-generator/src/main/resources/Java/libraries/native/pojo.mustache Outdated
@@ -1 +1 @@
{{#lambda.jSpecifyNullable}}{{#required}}{{#isNullable}}@{{javaxPackage}}.annotation.Nullable{{/isNullable}}{{^useJspecify}}{{^isNullable}}@{{javaxPackage}}.annotation.Nonnull{{/isNullable}}{{/useJspecify}}{{/required}}{{^required}}@{{javaxPackage}}.annotation.Nullable{{/required}}{{/lambda.jSpecifyNullable}} No newline at end of file
{{^useJspecify}}{{#required}}{{#isNullable}}@{{javaxPackage}}.annotation.Nullable{{/isNullable}}{{^isNullable}}@{{javaxPackage}}.annotation.Nonnull{{/isNullable}}{{/required}}{{^required}}@{{javaxPackage}}.annotation.Nullable{{/required}}{{/useJspecify}}{{#useJspecify}}{{#lambda.jSpecifyNullable}}{{^required}}@{{javaxPackage}}.annotation.Nullable {{/required}}{{/lambda.jSpecifyNullable}}{{/useJspecify}} No newline at end of file

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: useJspecify request-wrapper fields, constructors, accessors, and record components lose @Nullable when useSingleRequestParameter is enabled, since this lambda suppresses it without a following jSpecifyDatatype. Render those declarations via the nullable datatype/argument partial (or preserve the annotation in direct-use contexts).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/nullable_var_annotations.mustache, line 1:

<comment>`useJspecify` request-wrapper fields, constructors, accessors, and record components lose `@Nullable` when `useSingleRequestParameter` is enabled, since this lambda suppresses it without a following `jSpecifyDatatype`. Render those declarations via the nullable datatype/argument partial (or preserve the annotation in direct-use contexts).</comment>

<file context>
@@ -1 +1 @@
-{{#lambda.jSpecifyNullable}}{{#required}}{{#isNullable}}@{{javaxPackage}}.annotation.Nullable{{/isNullable}}{{^useJspecify}}{{^isNullable}}@{{javaxPackage}}.annotation.Nonnull{{/isNullable}}{{/useJspecify}}{{/required}}{{^required}}@{{javaxPackage}}.annotation.Nullable{{/required}}{{/lambda.jSpecifyNullable}}
\ No newline at end of file
+{{^useJspecify}}{{#required}}{{#isNullable}}@{{javaxPackage}}.annotation.Nullable{{/isNullable}}{{^isNullable}}@{{javaxPackage}}.annotation.Nonnull{{/isNullable}}{{/required}}{{^required}}@{{javaxPackage}}.annotation.Nullable{{/required}}{{/useJspecify}}{{#useJspecify}}{{#lambda.jSpecifyNullable}}{{^required}}@{{javaxPackage}}.annotation.Nullable {{/required}}{{/lambda.jSpecifyNullable}}{{/useJspecify}}
\ No newline at end of file
</file context>

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.

The unit tests and generated samples show that nullable_var_annotations work for jspecify and leave non jspecify untouched

@@ -0,0 +1,729 @@
/*

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 generated import block contains three duplicated imports (java.util.Arrays, org.openapitools.jackson.nullable.JsonNullable, com.fasterxml.jackson.annotation.JsonIgnore). Legal but untidy generated output; this sample adds two more duplicates than the sibling jspecify sample, so the new openapiNullable template path is emitting redundant imports. Remove the duplicates.

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

<comment>The generated import block contains three duplicated imports (java.util.Arrays, org.openapitools.jackson.nullable.JsonNullable, com.fasterxml.jackson.annotation.JsonIgnore). Legal but untidy generated output; this sample adds two more duplicates than the sibling jspecify sample, so the new openapiNullable template path is emitting redundant imports. Remove the duplicates.</comment>

<file context>
@@ -0,0 +1,729 @@
+import java.util.Arrays;
+import java.util.List;
+import org.jspecify.annotations.Nullable;
+import org.openapitools.jackson.nullable.JsonNullable;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.openapitools.jackson.nullable.JsonNullable;
</file context>

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.

The issue already existed. So no regression

@jpfinne
jpfinne marked this pull request as draft August 8, 2026 18:01
@jpfinne jpfinne changed the title [JAVA] add JSpecify @Nullable annotation to builder and toIndentedString() [JAVA] add JSpecify @Nullable annotation to builder Aug 8, 2026
Regenerate samples with more tags, useSingleRequestParameter...
Comment thread bin/utils/test_file_list.yaml
@jpfinne
jpfinne marked this pull request as ready for review August 9, 2026 11:17

@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.

2 issues found across 127 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:154">
P2: A response header such as `filename=../outside` escapes the generated download directory and writes response content to an unintended filesystem location. Sanitize to a basename (or normalize and reject paths outside `tempDir`) in the native template, then regenerate samples.</violation>
</file>

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

<violation number="1" location="samples/client/petstore/java/native-jackson3-jspecify/src/main/java/org/openapitools/client/api/UploadApi.java:262">
P1: Calling the documented nullable optional upload parameter with `null` throws before a request is sent because it is unconditionally converted to a binary multipart part. Guard the file part (and apply the same generation change in the native template) so an omitted file produces an empty multipart request.</violation>
</file>

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

Re-trigger cubic


MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
boolean hasFiles = false;
multiPartBuilder.addBinaryBody("file", _file);

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.

P1: Calling the documented nullable optional upload parameter with null throws before a request is sent because it is unconditionally converted to a binary multipart part. Guard the file part (and apply the same generation change in the native template) so an omitted file produces an empty multipart request.

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/UploadApi.java, line 262:

<comment>Calling the documented nullable optional upload parameter with `null` throws before a request is sent because it is unconditionally converted to a binary multipart part. Guard the file part (and apply the same generation change in the native template) so an omitted file produces an empty multipart request.</comment>

<file context>
@@ -0,0 +1,306 @@
+
+    MultipartEntityBuilder multiPartBuilder = MultipartEntityBuilder.create();
+    boolean hasFiles = false;
+    multiPartBuilder.addBinaryBody("file", _file);
+    hasFiles = true;
+    HttpEntity entity = multiPartBuilder.build();
</file context>

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: A response header such as filename=../outside escapes the generated download directory and writes response content to an unintended filesystem location. Sanitize to a basename (or normalize and reject paths outside tempDir) in the native template, then regenerate samples.

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 154:

<comment>A response header such as `filename=../outside` escapes the generated download directory and writes response content to an unintended filesystem location. Sanitize to a basename (or normalize and reject paths outside `tempDir`) in the native template, then regenerate samples.</comment>

<file context>
@@ -0,0 +1,269 @@
+    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>

@jpfinne
jpfinne marked this pull request as draft August 9, 2026 12:37
@jpfinne jpfinne changed the title [JAVA] add JSpecify @Nullable annotation to builder [JAVA] add more JSpecify @Nullable (builder, resttemplate api) Aug 9, 2026
@jpfinne
jpfinne marked this pull request as ready for review August 9, 2026 18:02

@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.

1 issue found across 157 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="modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache:79">
P2: Optional abstracted file parameters remain non-null under `@NullMarked` although generated form handling accepts null; apply nullable/nonnull annotations to the `useAbstractionForFiles` branches too.</violation>
</file>

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

Re-trigger cubic

@Deprecated
{{/isDeprecated}}
public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {

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: Optional abstracted file parameters remain non-null under @NullMarked although generated form handling accepts null; apply nullable/nonnull annotations to the useAbstractionForFiles branches too.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache, line 79:

<comment>Optional abstracted file parameters remain non-null under `@NullMarked` although generated form handling accepts null; apply nullable/nonnull annotations to the `useAbstractionForFiles` branches too.</comment>

<file context>
@@ -76,7 +76,7 @@ public class {{classname}} extends BaseApi {
     @Deprecated
     {{/isDeprecated}}
-    public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
+    public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
         {{#returnType}}
         return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody();
</file context>

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.

resttemplate is not covered in this PR

Comment thread modules/openapi-generator/src/main/resources/Java/nullable-import.mustache Outdated
@jpfinne jpfinne changed the title [JAVA] add more JSpecify @Nullable (builder, resttemplate api) [JAVA] add JSpecify @Nullable in builder Aug 9, 2026
@jpfinne jpfinne changed the title [JAVA] add JSpecify @Nullable in builder [JAVA] add JSpecify @Nullable in builder and singleRequestParameter Aug 9, 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.

2 issues found across 6 files (changes from recent commits).

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="modules/openapi-generator/src/main/resources/Java/libraries/restclient/single_request_parameter.mustache">

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/restclient/single_request_parameter.mustache:5">
P2: Optional or nullable file parameters in `useJspecify=true,useAbstractionForFiles=true` request wrappers remain unannotated because the file branch bypasses `nullableArgument`. Apply the same nullable/type-use handling to the `Resource` and `Collection<Resource>` branches so builders meet the JSpecify contract for every parameter type.</violation>
</file>

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

<violation number="1" location="modules/openapi-generator/src/main/resources/Java/libraries/webclient/single_request_parameter.mustache:6">
P2: Optional file parameters with `useAbstractionForFiles=true` still generate unannotated `Resource` request members, so this JSpecify request-parameter path loses nullable metadata. Route the literal Resource types through equivalent `jSpecifyNullable`/`jSpecifyDatatype` handling (while retaining existing non-JSpecify annotations).</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic


{{^staticRequest}}
public record {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullable_var_annotations}} {{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullable_var_annotations}} {{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){}
public record {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){}

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: Optional or nullable file parameters in useJspecify=true,useAbstractionForFiles=true request wrappers remain unannotated because the file branch bypasses nullableArgument. Apply the same nullable/type-use handling to the Resource and Collection<Resource> branches so builders meet the JSpecify contract for every parameter type.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/restclient/single_request_parameter.mustache, line 5:

<comment>Optional or nullable file parameters in `useJspecify=true,useAbstractionForFiles=true` request wrappers remain unannotated because the file branch bypasses `nullableArgument`. Apply the same nullable/type-use handling to the `Resource` and `Collection<Resource>` branches so builders meet the JSpecify contract for every parameter type.</comment>

<file context>
@@ -2,27 +2,27 @@
 
     {{^staticRequest}}
-    public record {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullable_var_annotations}} {{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullable_var_annotations}} {{{dataType}}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){}
+    public record {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request({{#allParams}}{{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){}
     {{/staticRequest}}
     {{#staticRequest}}
</file context>

public {{#staticRequest}}static {{/staticRequest}}class {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request {
{{#allParams}}
private {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullable_var_annotations}} {{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullable_var_annotations}} {{{dataType}}}{{/isFile}} {{paramName}};
private {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}};

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: Optional file parameters with useAbstractionForFiles=true still generate unannotated Resource request members, so this JSpecify request-parameter path loses nullable metadata. Route the literal Resource types through equivalent jSpecifyNullable/jSpecifyDatatype handling (while retaining existing non-JSpecify annotations).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At modules/openapi-generator/src/main/resources/Java/libraries/webclient/single_request_parameter.mustache, line 6:

<comment>Optional file parameters with `useAbstractionForFiles=true` still generate unannotated `Resource` request members, so this JSpecify request-parameter path loses nullable metadata. Route the literal Resource types through equivalent `jSpecifyNullable`/`jSpecifyDatatype` handling (while retaining existing non-JSpecify annotations).</comment>

<file context>
@@ -3,22 +3,22 @@
     public {{#staticRequest}}static {{/staticRequest}}class {{#lambda.titlecase}}{{operationId}}{{/lambda.titlecase}}Request {
     {{#allParams}}
-        private {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullable_var_annotations}} {{{dataType}}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullable_var_annotations}} {{{dataType}}}{{/isFile}} {{paramName}};
+        private {{#isFile}}{{#useAbstractionForFiles}}{{#collectionFormat}}java.util.Collection<org.springframework.core.io.Resource>{{/collectionFormat}}{{^collectionFormat}}org.springframework.core.io.Resource{{/collectionFormat}}{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{>nullableArgument}}{{/useAbstractionForFiles}}{{/isFile}}{{^isFile}}{{>nullableArgument}}{{/isFile}} {{paramName}};
     {{/allParams}}
 
</file context>

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.

1 participant