Skip to content

Commit 9afa74a

Browse files
authored
[spring] Add an option "additionalNotNullAnnotations" to include additional NotNull annotations (#23096)
* add option additionalNotNullAnnotations * update samples, docs * add tests for option * fix github workflow * fix path * remove
1 parent 536016b commit 9afa74a

204 files changed

Lines changed: 1024 additions & 1014 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/samples-spring-jdk17.yaml

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,32 @@ name: Samples Java Spring (JDK17)
33
on:
44
push:
55
paths:
6-
- samples/openapi3/client/petstore/spring-cloud-3-with-optional
7-
- samples/openapi3/client/petstore/spring-cloud-4-with-optional
8-
- samples/client/petstore/spring-http-interface-springboot-4
9-
- samples/openapi3/server/petstore/springboot-3
10-
- samples/openapi3/server/petstore/springboot-4
11-
- samples/server/petstore/springboot-api-response-examples
12-
- samples/server/petstore/springboot-lombok-data
13-
- samples/server/petstore/springboot-lombok-tostring
14-
- samples/server/petstore/springboot-file-delegate-optional
15-
- samples/server/petstore/springboot-petstore-with-api-response-examples
16-
- samples/server/petstore/spring-boot-oneof-sealed
17-
- samples/openapi3/server/petstore/spring-boot-oneof-interface
6+
- samples/openapi3/client/petstore/spring-cloud-3-with-optional/**
7+
- samples/openapi3/client/petstore/spring-cloud-4-with-optional/**
8+
- samples/client/petstore/spring-http-interface-springboot-4/**
9+
- samples/openapi3/server/petstore/springboot-3/**
10+
- samples/openapi3/server/petstore/springboot-4/**
11+
- samples/server/petstore/springboot-api-response-examples/**
12+
- samples/server/petstore/springboot-lombok-data/**
13+
- samples/server/petstore/springboot-lombok-tostring/**
14+
- samples/server/petstore/springboot-file-delegate-optional/**
15+
- samples/server/petstore/springboot-petstore-with-api-response-examples/**
16+
- samples/openapi3/server/petstore/spring-boot-oneof-sealed/**
17+
- samples/openapi3/server/petstore/spring-boot-oneof-interface/**
1818
pull_request:
1919
paths:
20-
- samples/openapi3/client/petstore/spring-cloud-3-with-optional
21-
- samples/openapi3/client/petstore/spring-cloud-4-with-optional
22-
- samples/client/petstore/spring-http-interface-springboot-4
23-
- samples/openapi3/server/petstore/springboot-3
24-
- samples/openapi3/server/petstore/springboot-4
25-
- samples/server/petstore/springboot-api-response-examples
26-
- samples/server/petstore/springboot-lombok-data
27-
- samples/server/petstore/springboot-lombok-tostring
28-
- samples/server/petstore/springboot-file-delegate-optional
29-
- samples/server/petstore/springboot-petstore-with-api-response-examples
30-
- samples/server/petstore/spring-boot-oneof-sealed
31-
- samples/openapi3/server/petstore/spring-boot-oneof-interface
20+
- samples/openapi3/client/petstore/spring-cloud-3-with-optional/**
21+
- samples/openapi3/client/petstore/spring-cloud-4-with-optional/**
22+
- samples/client/petstore/spring-http-interface-springboot-4/**
23+
- samples/openapi3/server/petstore/springboot-3/**
24+
- samples/openapi3/server/petstore/springboot-4/**
25+
- samples/server/petstore/springboot-api-response-examples/**
26+
- samples/server/petstore/springboot-lombok-data/**
27+
- samples/server/petstore/springboot-lombok-tostring/**
28+
- samples/server/petstore/springboot-file-delegate-optional/**
29+
- samples/server/petstore/springboot-petstore-with-api-response-examples/**
30+
- samples/openapi3/server/petstore/spring-boot-oneof-sealed/**
31+
- samples/openapi3/server/petstore/spring-boot-oneof-interface/**
3232
jobs:
3333
build:
3434
name: Build Java Spring (JDK17)
@@ -49,7 +49,7 @@ jobs:
4949
- samples/server/petstore/springboot-lombok-tostring
5050
- samples/server/petstore/springboot-file-delegate-optional
5151
- samples/server/petstore/springboot-petstore-with-api-response-examples
52-
- samples/server/petstore/spring-boot-oneof-sealed
52+
- samples/openapi3/server/petstore/spring-boot-oneof-sealed
5353
- samples/openapi3/server/petstore/spring-boot-oneof-interface
5454
steps:
5555
- uses: actions/checkout@v5

bin/configs/spring-boot-x-implements-skip.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ outputDir: samples/server/petstore/springboot-x-implements-skip
33
inputSpec: modules/openapi-generator/src/test/resources/3_0/spring/petstore-with-fake-endpoints-models-for-testing-x-implements.yaml
44
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
55
additionalProperties:
6+
additionalNotNullAnnotations: true
67
documentationProvider: springfox
78
artifactId: springboot
89
snapshotVersion: "true"
@@ -12,4 +13,4 @@ additionalProperties:
1213
xImplementsSkip: [ com.custompackage.InterfaceToSkip ]
1314
schemaImplements:
1415
Foo: [ com.custompackage.WithBar, com.custompackage.WithDefaultMethod ]
15-
Animal: com.custompackage.WithColor
16+
Animal: com.custompackage.WithColor

docs/generators/java-camel.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2020
| ------ | ----------- | ------ | ------- |
2121
|additionalEnumTypeAnnotations|Additional annotations for enum type(class level annotations)| |null|
2222
|additionalModelTypeAnnotations|Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
23+
|additionalNotNullAnnotations|Add @NotNull to path variables (required by default) and requestBody.| |false|
2324
|additionalOneOfTypeAnnotations|Additional annotations for oneOf interfaces(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
2425
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
2526
|annotationLibrary|Select the complementary documentation annotation library.|<dl><dt>**none**</dt><dd>Do not annotate Model and Api with complementary annotations.</dd><dt>**swagger1**</dt><dd>Annotate Model and Api using the Swagger Annotations 1.x library.</dd><dt>**swagger2**</dt><dd>Annotate Model and Api using the Swagger Annotations 2.x library.</dd></dl>|swagger2|

docs/generators/spring.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
2020
| ------ | ----------- | ------ | ------- |
2121
|additionalEnumTypeAnnotations|Additional annotations for enum type(class level annotations)| |null|
2222
|additionalModelTypeAnnotations|Additional annotations for model type(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
23+
|additionalNotNullAnnotations|Add @NotNull to path variables (required by default) and requestBody.| |false|
2324
|additionalOneOfTypeAnnotations|Additional annotations for oneOf interfaces(class level annotations). List separated by semicolon(;) or new line (Linux or Windows)| |null|
2425
|allowUnicodeIdentifiers|boolean, toggles whether unicode identifiers are allowed in names or not, default is false| |false|
2526
|annotationLibrary|Select the complementary documentation annotation library.|<dl><dt>**none**</dt><dd>Do not annotate Model and Api with complementary annotations.</dd><dt>**swagger1**</dt><dd>Annotate Model and Api using the Swagger Annotations 1.x library.</dd><dt>**swagger2**</dt><dd>Annotate Model and Api using the Swagger Annotations 2.x library.</dd></dl>|swagger2|

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public class SpringCodegen extends AbstractJavaCodegen
108108
public static final String JACKSON2_PACKAGE = "com.fasterxml.jackson";
109109
public static final String JACKSON3_PACKAGE = "tools.jackson";
110110
public static final String JACKSON_PACKAGE = "jacksonPackage";
111+
public static final String ADDITIONAL_NOT_NULL_ANNOTATIONS = "additionalNotNullAnnotations";
111112

112113
@Getter
113114
public enum RequestMappingMode {
@@ -180,6 +181,8 @@ public enum RequestMappingMode {
180181
protected boolean useDeductionForOneOfInterfaces = false;
181182
@Getter @Setter
182183
protected boolean useJackson3 = false;
184+
@Getter @Setter
185+
protected boolean additionalNotNullAnnotations = false;
183186

184187
public SpringCodegen() {
185188
super();
@@ -269,7 +272,6 @@ public SpringCodegen() {
269272
cliOptions.add(CliOption.newString(X_IMPLEMENTS_SKIP, "Ability to choose interfaces that should NOT be implemented in the models despite their presence in vendor extension `x-implements`. Takes a list of fully qualified interface names. Example: yaml `xImplementsSkip: [com.some.pack.WithPhotoUrls]` skips implementing the interface `com.some.pack.WithPhotoUrls` in any schema", "empty list"));
270273
cliOptions.add(CliOption.newString(SCHEMA_IMPLEMENTS, "Ability to supply interfaces per schema that should be implemented (serves similar purpose as vendor extension `x-implements`, but is fully decoupled from the api spec). Example: yaml `schemaImplements: {Pet: com.some.pack.WithId, Category: [com.some.pack.CategoryInterface], Dog: [com.some.pack.Canine, com.some.pack.OtherInterface]}` implements interfaces in schemas `Pet` (interface `com.some.pack.WithId`), `Category` (interface `com.some.pack.CategoryInterface`), `Dog`(interfaces `com.some.pack.Canine`, `com.some.pack.OtherInterface`)", "empty map"));
271274

272-
273275
CliOption requestMappingOpt = new CliOption(REQUEST_MAPPING_OPTION,
274276
"Where to generate the class level @RequestMapping annotation.")
275277
.defaultValue(requestMappingMode.name());
@@ -325,6 +327,10 @@ public SpringCodegen() {
325327
library.setEnum(supportedLibraries);
326328
cliOptions.add(library);
327329

330+
cliOptions.add(CliOption.newBoolean(ADDITIONAL_NOT_NULL_ANNOTATIONS,
331+
"Add @NotNull to path variables (required by default) and requestBody.",
332+
additionalNotNullAnnotations));
333+
328334
}
329335

330336
@Override
@@ -532,6 +538,7 @@ public void processOpts() {
532538
}
533539
convertPropertyToStringAndWriteBack(RESOURCE_FOLDER, this::setResourceFolder);
534540

541+
convertPropertyToBooleanAndWriteBack(ADDITIONAL_NOT_NULL_ANNOTATIONS, this::setAdditionalNotNullAnnotations);
535542

536543
// override parent one
537544
importMapping.put("JsonDeserialize", (useJackson3 ? JACKSON3_PACKAGE : JACKSON2_PACKAGE) + ".databind.annotation.JsonDeserialize");
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{{^useOptional}}{{#required}}@NotNull {{/required}}{{>beanValidationCore}}{{/useOptional}}{{#useOptional}}{{#required}}{{>beanValidationCore}}{{/required}}{{/useOptional}}
1+
{{^useOptional}}{{#additionalNotNullAnnotations}}{{#required}}@NotNull {{/required}}{{/additionalNotNullAnnotations}}{{>beanValidationCore}}{{/useOptional}}{{#useOptional}}{{#required}}{{>beanValidationCore}}{{/required}}{{/useOptional}}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{{! PathParam is always required }}@NotNull {{>beanValidationCore}}
1+
{{! PathParam is always required }}{{#additionalNotNullAnnotations}}@NotNull {{/additionalNotNullAnnotations}}{{>beanValidationCore}}

samples/client/petstore/spring-cloud-date-time/src/main/java/org/openapitools/api/DefaultApi.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public interface DefaultApi {
5050
value = DefaultApi.PATH_GET
5151
)
5252
ResponseEntity<Void> get(
53-
@NotNull @ApiParam(value = "A date path parameter", required = true, defaultValue = "1972-01-01") @PathVariable("date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
53+
@ApiParam(value = "A date path parameter", required = true, defaultValue = "1972-01-01") @PathVariable("date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
5454
@NotNull @ApiParam(value = "A date-time query parameter", required = true, defaultValue = "1973-12-19T03:39:57-08:00") @Valid @RequestParam(value = "dateTime", required = true, defaultValue = "1973-12-19T03:39:57-08:00") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime dateTime,
5555
@NotNull @ApiParam(value = "A date header parameter", required = true, defaultValue = "1974-01-01") @RequestHeader(value = "X-Order-Date", required = true, defaultValue = "1974-01-01") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate xOrderDate,
5656
@ApiParam(value = "A date cookie parameter", defaultValue = "1975-01-01") @CookieValue(name = "loginDate", required = false, defaultValue = "1975-01-01") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate loginDate
@@ -80,7 +80,7 @@ ResponseEntity<Void> get(
8080
consumes = "application/x-www-form-urlencoded"
8181
)
8282
ResponseEntity<Void> updatePetWithForm(
83-
@NotNull @ApiParam(value = "A date path parameter", required = true, defaultValue = "1970-01-01") @PathVariable("date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
83+
@ApiParam(value = "A date path parameter", required = true, defaultValue = "1970-01-01") @PathVariable("date") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date,
8484
@ApiParam(value = "Updated last visit timestamp", defaultValue = "1971-12-19T03:39:57-08:00") @Valid @RequestParam(value = "visitDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) OffsetDateTime visitDate
8585
);
8686

samples/client/petstore/spring-cloud-deprecated/src/main/java/org/openapitools/api/PetApi.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public interface PetApi {
6363
consumes = "application/json"
6464
)
6565
ResponseEntity<Void> addPet(
66-
@Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @NotNull @Valid @RequestBody Pet pet
66+
@Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody Pet pet
6767
);
6868

6969

@@ -93,7 +93,7 @@ ResponseEntity<Void> addPet(
9393
value = PetApi.PATH_DELETE_PET
9494
)
9595
ResponseEntity<Void> deletePet(
96-
@NotNull @Parameter(name = "petId", description = "Pet id to delete", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
96+
@Parameter(name = "petId", description = "Pet id to delete", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
9797
@Parameter(name = "api_key", description = "", in = ParameterIn.HEADER) @RequestHeader(value = "api_key", required = false) @Nullable String apiKey
9898
);
9999

@@ -204,7 +204,7 @@ ResponseEntity<List<Pet>> findPetsByTags(
204204
produces = { "application/json", "application/xml" }
205205
)
206206
ResponseEntity<Pet> getPetById(
207-
@NotNull @Parameter(name = "petId", deprecated = true, description = "ID of pet to return", required = true, in = ParameterIn.PATH) @PathVariable("petId") @Deprecated Long petId
207+
@Parameter(name = "petId", deprecated = true, description = "ID of pet to return", required = true, in = ParameterIn.PATH) @PathVariable("petId") @Deprecated Long petId
208208
);
209209

210210

@@ -238,7 +238,7 @@ ResponseEntity<Pet> getPetById(
238238
consumes = "application/json"
239239
)
240240
ResponseEntity<Void> updatePet(
241-
@Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @NotNull @Valid @RequestBody Pet pet
241+
@Parameter(name = "Pet", description = "Pet object that needs to be added to the store", required = true) @Valid @RequestBody Pet pet
242242
);
243243

244244

@@ -270,7 +270,7 @@ ResponseEntity<Void> updatePet(
270270
consumes = "application/x-www-form-urlencoded"
271271
)
272272
ResponseEntity<Void> updatePetWithForm(
273-
@NotNull @Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
273+
@Parameter(name = "petId", description = "ID of pet that needs to be updated", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
274274
@Parameter(name = "name", description = "Updated name of the pet") @Valid @RequestParam(value = "name", required = false) String name,
275275
@Parameter(name = "status", description = "Updated status of the pet") @Valid @RequestParam(value = "status", required = false) String status
276276
);
@@ -307,7 +307,7 @@ ResponseEntity<Void> updatePetWithForm(
307307
consumes = "multipart/form-data"
308308
)
309309
ResponseEntity<ModelApiResponse> uploadFile(
310-
@NotNull @Parameter(name = "petId", description = "ID of pet to update", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
310+
@Parameter(name = "petId", description = "ID of pet to update", required = true, in = ParameterIn.PATH) @PathVariable("petId") Long petId,
311311
@Parameter(name = "additionalMetadata", description = "Additional data to pass to server") @Valid @RequestParam(value = "additionalMetadata", required = false) String additionalMetadata,
312312
@Parameter(name = "file", description = "file to upload") @RequestPart(value = "file", required = false) MultipartFile file
313313
);

samples/client/petstore/spring-cloud-deprecated/src/main/java/org/openapitools/api/StoreApi.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public interface StoreApi {
6060
value = StoreApi.PATH_DELETE_ORDER
6161
)
6262
ResponseEntity<Void> deleteOrder(
63-
@NotNull @Parameter(name = "orderId", description = "ID of the order that needs to be deleted", required = true, in = ParameterIn.PATH) @PathVariable("orderId") String orderId
63+
@Parameter(name = "orderId", description = "ID of the order that needs to be deleted", required = true, in = ParameterIn.PATH) @PathVariable("orderId") String orderId
6464
);
6565

6666

@@ -125,7 +125,7 @@ ResponseEntity<Map<String, Integer>> getInventory(
125125
produces = { "application/json", "application/xml" }
126126
)
127127
ResponseEntity<Order> getOrderById(
128-
@NotNull @Min(value = 1L) @Max(value = 5L) @Parameter(name = "orderId", description = "ID of pet that needs to be fetched", required = true, in = ParameterIn.PATH) @PathVariable("orderId") Long orderId
128+
@Min(value = 1L) @Max(value = 5L) @Parameter(name = "orderId", description = "ID of pet that needs to be fetched", required = true, in = ParameterIn.PATH) @PathVariable("orderId") Long orderId
129129
);
130130

131131

@@ -158,7 +158,7 @@ ResponseEntity<Order> getOrderById(
158158
consumes = "application/json"
159159
)
160160
ResponseEntity<Order> placeOrder(
161-
@Parameter(name = "Order", description = "order placed for purchasing the pet", required = true) @NotNull @Valid @RequestBody Order order
161+
@Parameter(name = "Order", description = "order placed for purchasing the pet", required = true) @Valid @RequestBody Order order
162162
);
163163

164164
}

0 commit comments

Comments
 (0)