Skip to content

Commit f201f33

Browse files
authored
[BUG][JAVA] Add @nullable to resttemplate api method parameters (#24970)
* [BUG][JAVA] Add @nullable to resttemplate api method parameters Fixes #23656 by using nullableArgumentForApi in resttemplate api.mustache. This ensures optional and nullable operation parameters are annotated with @nullable when useJspecify is enabled, matching webclient and restclient. * Update resttemplate samples
1 parent ab9ebb5 commit f201f33

33 files changed

Lines changed: 350 additions & 354 deletions

File tree

‎modules/openapi-generator/src/main/resources/Java/libraries/resttemplate/api.mustache‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public class {{classname}} extends BaseApi {
7676
{{#isDeprecated}}
7777
@Deprecated
7878
{{/isDeprecated}}
79-
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 {
79+
public {{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{>nullableArgumentForApi}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
8080
{{#returnType}}
8181
return {{operationId}}WithHttpInfo({{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}).getBody();
8282
{{/returnType}}
@@ -107,7 +107,7 @@ public class {{classname}} extends BaseApi {
107107
{{#isDeprecated}}
108108
@Deprecated
109109
{{/isDeprecated}}
110-
public ResponseEntity<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#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 {
110+
public ResponseEntity<{{#returnType}}{{#isResponseFile}}{{#useAbstractionForFiles}}org.springframework.core.io.Resource{{/useAbstractionForFiles}}{{^useAbstractionForFiles}}{{{.}}}{{/useAbstractionForFiles}}{{/isResponseFile}}{{^isResponseFile}}{{{.}}}{{/isResponseFile}}{{/returnType}}{{^returnType}}Void{{/returnType}}> {{operationId}}WithHttpInfo({{#allParams}}{{>nullableArgumentForApi}} {{paramName}}{{^-last}}, {{/-last}}{{/allParams}}) throws RestClientException {
111111
Object localVarPostBody = {{#bodyParam}}{{paramName}}{{/bodyParam}}{{^bodyParam}}null{{/bodyParam}};
112112
{{#allParams}}{{#required}}
113113
// verify the required parameter '{{paramName}}' is set

‎modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java‎

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4850,15 +4850,13 @@ public void testJspecify(String library, int springBootVersion, boolean hasJspec
48504850
"private @Nullable VirusScanEnum virusScan",
48514851
"FileContent.Builder virusScan(@Nullable VirusScanEnum virusScan)"
48524852
);
4853-
if (!RESTTEMPLATE.equals(library)) {
4854-
JavaFileAssert.assertThat(files.get("FooApi.java"))
4855-
.fileContains("fooDtParamGet(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)");
4856-
JavaFileAssert.assertThat(files.get("FooApi.java"))
4857-
.fileContains(
4858-
"import org.jspecify.annotations.Nullable;",
4859-
"(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)"
4860-
);
4861-
}
4853+
JavaFileAssert.assertThat(files.get("FooApi.java"))
4854+
.fileContains("fooDtParamGet(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)");
4855+
JavaFileAssert.assertThat(files.get("FooApi.java"))
4856+
.fileContains(
4857+
"import org.jspecify.annotations.Nullable;",
4858+
"(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)"
4859+
);
48624860
JavaFileAssert.assertThat(files.get("api/package-info.java"))
48634861
.fileContains("@org.jspecify.annotations.NullMarked");
48644862
JavaFileAssert.assertThat(files.get("model/package-info.java"))
@@ -4918,15 +4916,13 @@ public void testJspecify_openapiNullable(String library, int springBootVersion,
49184916
"public Foo(@JsonProperty(JSON_PROPERTY_DT) java.time.@Nullable Instant dt, @JsonProperty(JSON_PROPERTY_NULLABLE_DT) java.time.@Nullable Instant nullableDt, @JsonProperty(JSON_PROPERTY_BINARY) @Nullable File binary, @JsonProperty(JSON_PROPERTY_NULLABLE_BINARY) @Nullable File nullableBinary, @JsonProperty(JSON_PROPERTY_LIST_OF_DT) @Nullable List<java.time.Instant> listOfDt, @JsonProperty(JSON_PROPERTY_LIST_MIN_INTEMS) @Nullable List<java.time.Instant> listMinIntems, @JsonProperty(JSON_PROPERTY_NULLABLE_LIST_MIN_INTEMS) @Nullable List<java.time.Instant> nullableListMinIntems, @JsonProperty(JSON_PROPERTY_REQUIRED_DT) java.time.Instant requiredDt, @JsonProperty(JSON_PROPERTY_NUMBER) java.math.@Nullable BigDecimal number, @JsonProperty(JSON_PROPERTY_NULLABLE_NUMBER) java.math.@Nullable BigDecimal nullableNumber, @JsonProperty(JSON_PROPERTY_COLOR) @Nullable String color, @JsonProperty(JSON_PROPERTY_REQUIRED_COLOR) String requiredColor, @JsonProperty(JSON_PROPERTY_NULLABLE_COLOR) @Nullable String nullableColor) {"
49194917
);
49204918
}
4921-
if (!RESTTEMPLATE.equals(library)) {
4922-
JavaFileAssert.assertThat(files.get("FooApi.java"))
4923-
.fileContains("fooDtParamGet(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)");
4924-
JavaFileAssert.assertThat(files.get("FooApi.java"))
4925-
.fileContains(
4926-
"import org.jspecify.annotations.Nullable;",
4927-
"(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)"
4928-
);
4929-
}
4919+
JavaFileAssert.assertThat(files.get("FooApi.java"))
4920+
.fileContains("fooDtParamGet(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)");
4921+
JavaFileAssert.assertThat(files.get("FooApi.java"))
4922+
.fileContains(
4923+
"import org.jspecify.annotations.Nullable;",
4924+
"(java.time.@Nullable Instant dtParam, java.time.@Nullable Instant dtQuery, java.time.@Nullable Instant dtCookie, @Nullable String color)"
4925+
);
49304926
JavaFileAssert.assertThat(files.get("api/package-info.java"))
49314927
.fileContains("@org.jspecify.annotations.NullMarked");
49324928
JavaFileAssert.assertThat(files.get("model/package-info.java"))

‎samples/client/echo_api/java/resttemplate/src/main/java/org/openapitools/client/api/BodyApi.java‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public ResponseEntity<File> testBinaryGifWithHttpInfo() throws RestClientExcepti
8787
* @return String
8888
* @throws RestClientException if an error occurs while attempting to invoke the API
8989
*/
90-
public String testBodyApplicationOctetstreamBinary(File body) throws RestClientException {
90+
public String testBodyApplicationOctetstreamBinary(@javax.annotation.Nullable File body) throws RestClientException {
9191
return testBodyApplicationOctetstreamBinaryWithHttpInfo(body).getBody();
9292
}
9393

@@ -99,7 +99,7 @@ public String testBodyApplicationOctetstreamBinary(File body) throws RestClientE
9999
* @return ResponseEntity&lt;String&gt;
100100
* @throws RestClientException if an error occurs while attempting to invoke the API
101101
*/
102-
public ResponseEntity<String> testBodyApplicationOctetstreamBinaryWithHttpInfo(File body) throws RestClientException {
102+
public ResponseEntity<String> testBodyApplicationOctetstreamBinaryWithHttpInfo(@javax.annotation.Nullable File body) throws RestClientException {
103103
Object localVarPostBody = body;
104104

105105

@@ -130,7 +130,7 @@ public ResponseEntity<String> testBodyApplicationOctetstreamBinaryWithHttpInfo(F
130130
* @return String
131131
* @throws RestClientException if an error occurs while attempting to invoke the API
132132
*/
133-
public String testBodyMultipartFormdataArrayOfBinary(List<File> files) throws RestClientException {
133+
public String testBodyMultipartFormdataArrayOfBinary(@javax.annotation.Nonnull List<File> files) throws RestClientException {
134134
return testBodyMultipartFormdataArrayOfBinaryWithHttpInfo(files).getBody();
135135
}
136136

@@ -142,7 +142,7 @@ public String testBodyMultipartFormdataArrayOfBinary(List<File> files) throws Re
142142
* @return ResponseEntity&lt;String&gt;
143143
* @throws RestClientException if an error occurs while attempting to invoke the API
144144
*/
145-
public ResponseEntity<String> testBodyMultipartFormdataArrayOfBinaryWithHttpInfo(List<File> files) throws RestClientException {
145+
public ResponseEntity<String> testBodyMultipartFormdataArrayOfBinaryWithHttpInfo(@javax.annotation.Nonnull List<File> files) throws RestClientException {
146146
Object localVarPostBody = null;
147147

148148
// verify the required parameter 'files' is set
@@ -181,7 +181,7 @@ public ResponseEntity<String> testBodyMultipartFormdataArrayOfBinaryWithHttpInfo
181181
* @return String
182182
* @throws RestClientException if an error occurs while attempting to invoke the API
183183
*/
184-
public String testBodyMultipartFormdataSingleBinary(File myFile) throws RestClientException {
184+
public String testBodyMultipartFormdataSingleBinary(@javax.annotation.Nullable File myFile) throws RestClientException {
185185
return testBodyMultipartFormdataSingleBinaryWithHttpInfo(myFile).getBody();
186186
}
187187

@@ -193,7 +193,7 @@ public String testBodyMultipartFormdataSingleBinary(File myFile) throws RestClie
193193
* @return ResponseEntity&lt;String&gt;
194194
* @throws RestClientException if an error occurs while attempting to invoke the API
195195
*/
196-
public ResponseEntity<String> testBodyMultipartFormdataSingleBinaryWithHttpInfo(File myFile) throws RestClientException {
196+
public ResponseEntity<String> testBodyMultipartFormdataSingleBinaryWithHttpInfo(@javax.annotation.Nullable File myFile) throws RestClientException {
197197
Object localVarPostBody = null;
198198

199199

@@ -227,7 +227,7 @@ public ResponseEntity<String> testBodyMultipartFormdataSingleBinaryWithHttpInfo(
227227
* @return Pet
228228
* @throws RestClientException if an error occurs while attempting to invoke the API
229229
*/
230-
public Pet testEchoBodyAllOfPet(Pet pet) throws RestClientException {
230+
public Pet testEchoBodyAllOfPet(@javax.annotation.Nullable Pet pet) throws RestClientException {
231231
return testEchoBodyAllOfPetWithHttpInfo(pet).getBody();
232232
}
233233

@@ -239,7 +239,7 @@ public Pet testEchoBodyAllOfPet(Pet pet) throws RestClientException {
239239
* @return ResponseEntity&lt;Pet&gt;
240240
* @throws RestClientException if an error occurs while attempting to invoke the API
241241
*/
242-
public ResponseEntity<Pet> testEchoBodyAllOfPetWithHttpInfo(Pet pet) throws RestClientException {
242+
public ResponseEntity<Pet> testEchoBodyAllOfPetWithHttpInfo(@javax.annotation.Nullable Pet pet) throws RestClientException {
243243
Object localVarPostBody = pet;
244244

245245

@@ -270,7 +270,7 @@ public ResponseEntity<Pet> testEchoBodyAllOfPetWithHttpInfo(Pet pet) throws Rest
270270
* @return String
271271
* @throws RestClientException if an error occurs while attempting to invoke the API
272272
*/
273-
public String testEchoBodyFreeFormObjectResponseString(Object body) throws RestClientException {
273+
public String testEchoBodyFreeFormObjectResponseString(@javax.annotation.Nullable Object body) throws RestClientException {
274274
return testEchoBodyFreeFormObjectResponseStringWithHttpInfo(body).getBody();
275275
}
276276

@@ -282,7 +282,7 @@ public String testEchoBodyFreeFormObjectResponseString(Object body) throws RestC
282282
* @return ResponseEntity&lt;String&gt;
283283
* @throws RestClientException if an error occurs while attempting to invoke the API
284284
*/
285-
public ResponseEntity<String> testEchoBodyFreeFormObjectResponseStringWithHttpInfo(Object body) throws RestClientException {
285+
public ResponseEntity<String> testEchoBodyFreeFormObjectResponseStringWithHttpInfo(@javax.annotation.Nullable Object body) throws RestClientException {
286286
Object localVarPostBody = body;
287287

288288

@@ -313,7 +313,7 @@ public ResponseEntity<String> testEchoBodyFreeFormObjectResponseStringWithHttpIn
313313
* @return Pet
314314
* @throws RestClientException if an error occurs while attempting to invoke the API
315315
*/
316-
public Pet testEchoBodyPet(Pet pet) throws RestClientException {
316+
public Pet testEchoBodyPet(@javax.annotation.Nullable Pet pet) throws RestClientException {
317317
return testEchoBodyPetWithHttpInfo(pet).getBody();
318318
}
319319

@@ -325,7 +325,7 @@ public Pet testEchoBodyPet(Pet pet) throws RestClientException {
325325
* @return ResponseEntity&lt;Pet&gt;
326326
* @throws RestClientException if an error occurs while attempting to invoke the API
327327
*/
328-
public ResponseEntity<Pet> testEchoBodyPetWithHttpInfo(Pet pet) throws RestClientException {
328+
public ResponseEntity<Pet> testEchoBodyPetWithHttpInfo(@javax.annotation.Nullable Pet pet) throws RestClientException {
329329
Object localVarPostBody = pet;
330330

331331

@@ -356,7 +356,7 @@ public ResponseEntity<Pet> testEchoBodyPetWithHttpInfo(Pet pet) throws RestClien
356356
* @return String
357357
* @throws RestClientException if an error occurs while attempting to invoke the API
358358
*/
359-
public String testEchoBodyPetResponseString(Pet pet) throws RestClientException {
359+
public String testEchoBodyPetResponseString(@javax.annotation.Nullable Pet pet) throws RestClientException {
360360
return testEchoBodyPetResponseStringWithHttpInfo(pet).getBody();
361361
}
362362

@@ -368,7 +368,7 @@ public String testEchoBodyPetResponseString(Pet pet) throws RestClientException
368368
* @return ResponseEntity&lt;String&gt;
369369
* @throws RestClientException if an error occurs while attempting to invoke the API
370370
*/
371-
public ResponseEntity<String> testEchoBodyPetResponseStringWithHttpInfo(Pet pet) throws RestClientException {
371+
public ResponseEntity<String> testEchoBodyPetResponseStringWithHttpInfo(@javax.annotation.Nullable Pet pet) throws RestClientException {
372372
Object localVarPostBody = pet;
373373

374374

@@ -399,7 +399,7 @@ public ResponseEntity<String> testEchoBodyPetResponseStringWithHttpInfo(Pet pet)
399399
* @return StringEnumRef
400400
* @throws RestClientException if an error occurs while attempting to invoke the API
401401
*/
402-
public StringEnumRef testEchoBodyStringEnum(String body) throws RestClientException {
402+
public StringEnumRef testEchoBodyStringEnum(@javax.annotation.Nullable String body) throws RestClientException {
403403
return testEchoBodyStringEnumWithHttpInfo(body).getBody();
404404
}
405405

@@ -411,7 +411,7 @@ public StringEnumRef testEchoBodyStringEnum(String body) throws RestClientExcept
411411
* @return ResponseEntity&lt;StringEnumRef&gt;
412412
* @throws RestClientException if an error occurs while attempting to invoke the API
413413
*/
414-
public ResponseEntity<StringEnumRef> testEchoBodyStringEnumWithHttpInfo(String body) throws RestClientException {
414+
public ResponseEntity<StringEnumRef> testEchoBodyStringEnumWithHttpInfo(@javax.annotation.Nullable String body) throws RestClientException {
415415
Object localVarPostBody = body;
416416

417417

@@ -442,7 +442,7 @@ public ResponseEntity<StringEnumRef> testEchoBodyStringEnumWithHttpInfo(String b
442442
* @return String
443443
* @throws RestClientException if an error occurs while attempting to invoke the API
444444
*/
445-
public String testEchoBodyTagResponseString(Tag tag) throws RestClientException {
445+
public String testEchoBodyTagResponseString(@javax.annotation.Nullable Tag tag) throws RestClientException {
446446
return testEchoBodyTagResponseStringWithHttpInfo(tag).getBody();
447447
}
448448

@@ -454,7 +454,7 @@ public String testEchoBodyTagResponseString(Tag tag) throws RestClientException
454454
* @return ResponseEntity&lt;String&gt;
455455
* @throws RestClientException if an error occurs while attempting to invoke the API
456456
*/
457-
public ResponseEntity<String> testEchoBodyTagResponseStringWithHttpInfo(Tag tag) throws RestClientException {
457+
public ResponseEntity<String> testEchoBodyTagResponseStringWithHttpInfo(@javax.annotation.Nullable Tag tag) throws RestClientException {
458458
Object localVarPostBody = tag;
459459

460460

0 commit comments

Comments
 (0)