Skip to content

Commit e5202f2

Browse files
authored
fix(jaxrs): correct add/remove methods for JsonNullable<List<T>> fields (#23258)
* fix(jaxrs): correct add/remove methods for JsonNullable<List<T>> fields #23251 Signed-off-by: TheNevim <puk.dominik212@gmail.com> * fix(jaxrs): add test for generation of add/remove methods for JsonNullable<List<T>> fields #23251 Signed-off-by: TheNevim <puk.dominik212@gmail.com> --------- Signed-off-by: TheNevim <puk.dominik212@gmail.com>
1 parent f6b457a commit e5202f2

3 files changed

Lines changed: 131 additions & 1 deletion

File tree

modules/openapi-generator/src/main/resources/JavaJaxRS/spec/pojo.mustache

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,36 +173,84 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
173173

174174
{{#isArray}}
175175
public {{classname}} add{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
176+
{{#vendorExtensions.x-is-jackson-optional-nullable}}
177+
if (this.{{name}} == null || !this.{{name}}.isPresent() || this.{{name}}.get() == null) {
178+
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}});
179+
}
180+
try {
181+
this.{{name}}.get().add({{name}}Item);
182+
} catch (java.util.NoSuchElementException e) {
183+
// this can never happen, as we make sure above that the value is present
184+
}
185+
return this;
186+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
187+
{{^vendorExtensions.x-is-jackson-optional-nullable}}
176188
if (this.{{name}} == null) {
177189
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new {{#uniqueItems}}LinkedHashSet{{/uniqueItems}}{{^uniqueItems}}ArrayList{{/uniqueItems}}<>(){{/defaultValue}};
178190
}
179191

180192
this.{{name}}.add({{name}}Item);
181193
return this;
194+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
182195
}
183196

184197
public {{classname}} remove{{nameInPascalCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
198+
{{#vendorExtensions.x-is-jackson-optional-nullable}}
199+
if ({{name}}Item != null && this.{{name}} != null && this.{{name}}.isPresent()) {
200+
try {
201+
this.{{name}}.get().remove({{name}}Item);
202+
} catch (java.util.NoSuchElementException e) {
203+
// this can never happen, as we make sure above that the value is present
204+
}
205+
}
206+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
207+
{{^vendorExtensions.x-is-jackson-optional-nullable}}
185208
if ({{name}}Item != null && this.{{name}} != null) {
186209
this.{{name}}.remove({{name}}Item);
187210
}
211+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
188212

189213
return this;
190214
}
191215
{{/isArray}}
192216
{{#isMap}}
193217
public {{classname}} put{{nameInPascalCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
218+
{{#vendorExtensions.x-is-jackson-optional-nullable}}
219+
if (this.{{name}} == null || !this.{{name}}.isPresent() || this.{{name}}.get() == null) {
220+
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}});
221+
}
222+
try {
223+
this.{{name}}.get().put(key, {{name}}Item);
224+
} catch (java.util.NoSuchElementException e) {
225+
// this can never happen, as we make sure above that the value is present
226+
}
227+
return this;
228+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
229+
{{^vendorExtensions.x-is-jackson-optional-nullable}}
194230
if (this.{{name}} == null) {
195231
this.{{name}} = {{{defaultValue}}}{{^defaultValue}}new HashMap<>(){{/defaultValue}};
196232
}
197233

198234
this.{{name}}.put(key, {{name}}Item);
199235
return this;
236+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
200237
}
201238

202239
public {{classname}} remove{{nameInPascalCase}}Item(String key) {
240+
{{#vendorExtensions.x-is-jackson-optional-nullable}}
241+
if (this.{{name}} != null && this.{{name}}.isPresent()) {
242+
try {
243+
this.{{name}}.get().remove(key);
244+
} catch (java.util.NoSuchElementException e) {
245+
// this can never happen, as we make sure above that the value is present
246+
}
247+
}
248+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
249+
{{^vendorExtensions.x-is-jackson-optional-nullable}}
203250
if (this.{{name}} != null) {
204251
this.{{name}}.remove(key);
205252
}
253+
{{/vendorExtensions.x-is-jackson-optional-nullable}}
206254

207255
return this;
208256
}
@@ -283,4 +331,4 @@ public class {{classname}} {{#parent}}extends {{{.}}}{{/parent}} {{#vendorExtens
283331
}
284332
{{/vars}}
285333
}{{/additionalProperties}}{{/generateBuilders}}
286-
}
334+
}

modules/openapi-generator/src/test/java/org/openapitools/codegen/java/jaxrs/JavaJAXRSSpecServerCodegenTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,5 +1236,43 @@ public void disableGenerateJsonCreator() throws Exception {
12361236

12371237
assertFileNotContains(files.get("RequiredProperties.java").toPath(), "@JsonCreator");
12381238
}
1239+
1240+
@Test
1241+
public void testGenerateJsonNullableListFieldsHelperMethodReferences_issue23251() throws Exception {
1242+
Map<String, Object> properties = new HashMap<>();
1243+
properties.put(OPENAPI_NULLABLE, "true");
1244+
1245+
File output = Files.createTempDirectory("test").toFile();
1246+
1247+
final CodegenConfigurator configurator = new CodegenConfigurator()
1248+
.setGeneratorName("jaxrs-spec")
1249+
.setAdditionalProperties(properties)
1250+
.setInputSpec("src/test/resources/bugs/issue_23251.yaml")
1251+
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
1252+
1253+
final ClientOptInput clientOptInput = configurator.toClientOptInput();
1254+
DefaultGenerator generator = new DefaultGenerator();
1255+
List<File> files = generator.opts(clientOptInput).generate();
1256+
1257+
validateJavaSourceFiles(files);
1258+
1259+
TestUtils.ensureContainsFile(files, output, "src/gen/java/org/openapitools/model/BugResponse.java");
1260+
1261+
// Assert that the generated model contains JsonNullable fields
1262+
assertFileContains(output.toPath().resolve("src/gen/java/org/openapitools/model/BugResponse.java"),
1263+
"private JsonNullable<String> nullableField = JsonNullable.<String>undefined();",
1264+
"private JsonNullable<List<String>> nullableList = JsonNullable.<List<String>>undefined();",
1265+
"private JsonNullable<List<@Valid NestedResponse>> nullableObjectList = JsonNullable.<List<@Valid NestedResponse>>undefined();"
1266+
);
1267+
1268+
// Assert that the generated model contains correct add and remove helper methods reference for JsonNullable fields
1269+
assertFileContains(output.toPath().resolve("src/gen/java/org/openapitools/model/BugResponse.java"),
1270+
"this.nullableList.get().add(nullableListItem);",
1271+
"this.nullableList.get().remove(nullableListItem);",
1272+
"this.nullableObjectList.get().add(nullableObjectListItem);",
1273+
"this.nullableObjectList.get().remove(nullableObjectListItem);");
1274+
1275+
output.deleteOnExit();
1276+
}
12391277

12401278
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
openapi: 3.0.2
2+
info:
3+
title: Reproduce
4+
version: 1.0.0
5+
paths:
6+
/test:
7+
get:
8+
summary: test
9+
operationId: test
10+
responses:
11+
200:
12+
description: Test
13+
content:
14+
application/json:
15+
schema:
16+
$ref: '#/components/schemas/BugResponse'
17+
components:
18+
schemas:
19+
BugResponse:
20+
type: object
21+
properties:
22+
nullableField:
23+
type: string
24+
nullable: true
25+
x-is-jackson-optional-nullable: true
26+
nullableList:
27+
type: array
28+
items:
29+
type: string
30+
nullable: true
31+
x-is-jackson-optional-nullable: true
32+
nullableObjectList:
33+
type: array
34+
items:
35+
$ref: '#/components/schemas/NestedResponse'
36+
nullable: true
37+
x-is-jackson-optional-nullable: true
38+
NestedResponse:
39+
type: object
40+
properties:
41+
nestedField:
42+
type: string
43+
nullable: true
44+
x-is-jackson-optional-nullable: true

0 commit comments

Comments
 (0)