From 7bcbc64154a6bb65a7b0b1c869ad7857089e2c4f Mon Sep 17 00:00:00 2001 From: fkischewski99 <56124748+fkischewski99@users.noreply.github.com> Date: Tue, 6 May 2025 21:09:57 +0200 Subject: [PATCH 1/2] Add initialize empty collection parameter (#1129) * Add initialize empty collection parameter * Fixed wrong spec name and wrong import in initialize-empty-collection test --------- Co-authored-by: Sebastian Brune Co-authored-by: Frederik Kischewski --- .../generator/deployment/CodegenConfig.java | 1 + .../deployment/CommonItemConfig.java | 6 + .../codegen/OpenApiGeneratorCodeGenBase.java | 6 + .../OpenApiClientGeneratorWrapper.java | 5 + .../libraries/microprofile/pojo.qute | 2 +- .../initialize-empty-collections/pom.xml | 89 ++++++ ...rkus-simple-openapi-empty-collections.yaml | 282 ++++++++++++++++++ ...arkus-simple-openapi-null-collections.yaml | 282 ++++++++++++++++++ .../src/main/resources/application.properties | 5 + ...nitialiseEmptyCollectionWhenFalseTest.java | 35 +++ ...InitialiseEmptyCollectionWhenTrueTest.java | 40 +++ client/integration-tests/pom.xml | 1 + docs/modules/ROOT/pages/client.adoc | 5 + .../initialize-empty-collections.adoc | 9 + .../includes/quarkus-openapi-generator.adoc | 42 +++ ...i-generator_quarkus.openapi-generator.adoc | 42 +++ 16 files changed, 851 insertions(+), 1 deletion(-) create mode 100644 client/integration-tests/initialize-empty-collections/pom.xml create mode 100644 client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-empty-collections.yaml create mode 100644 client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-null-collections.yaml create mode 100644 client/integration-tests/initialize-empty-collections/src/main/resources/application.properties create mode 100644 client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenFalseTest.java create mode 100644 client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenTrueTest.java create mode 100644 docs/modules/ROOT/pages/includes/initialize-empty-collections.adoc diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java index d926ac2f5..6927b2275 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CodegenConfig.java @@ -69,6 +69,7 @@ enum ConfigName { PART_FILENAME_VALUE("part-filename-value"), USE_FIELD_NAME_IN_PART_FILENAME("use-field-name-in-part-filename"), ADDITIONAL_PROPERTIES_AS_ATTRIBUTE("additional-properties-as-attribute"), + INITIALIZE_EMPTY_COLLECTIONS("initialize-empty-collections"), ADDITIONAL_REQUEST_ARGS("additional-request-args"), REMOVE_OPERATION_ID_PREFIX("remove-operation-id-prefix"), REMOVE_OPERATION_ID_PREFIX_DELIMITER("remove-operation-id-prefix-delimiter"), diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java index f0fffc0a6..218ef12e5 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/CommonItemConfig.java @@ -183,4 +183,10 @@ public interface CommonItemConfig { */ @WithName("additional-properties-as-attribute") Optional additionalPropertiesAsAttribute(); + + /** + * Initialise collections as empty instead of null + */ + @WithName("initialize-empty-collections") + Optional initializeEmptyCollections(); } diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java index 22bcad244..34ad096ec 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/codegen/OpenApiGeneratorCodeGenBase.java @@ -335,6 +335,12 @@ protected void generate(OpenApiGeneratorOptions options) { .ifPresent(generator::withMutinyReturnTypes); generator.withAdditionalPropertiesAsAttribute(additionalPropertiesAsAttribute); + + Boolean initialiseEmptyCollection = getValues(smallRyeConfig, openApiFilePath, + CodegenConfig.ConfigName.INITIALIZE_EMPTY_COLLECTIONS, Boolean.class) + .orElse(Boolean.FALSE); + generator.withInitializeEmptyCollections(initialiseEmptyCollection); + GlobalSettings.setProperty( OpenApiClientGeneratorWrapper.SUPPORTS_ADDITIONAL_PROPERTIES_AS_ATTRIBUTE, additionalPropertiesAsAttribute.toString()); diff --git a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java index 9c1525bc1..3b1320afb 100644 --- a/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java +++ b/client/deployment/src/main/java/io/quarkiverse/openapi/generator/deployment/wrapper/OpenApiClientGeneratorWrapper.java @@ -89,6 +89,7 @@ private void setDefaults() { // Set default values directly here this.configurator.addAdditionalProperty("additionalApiTypeAnnotations", new String[0]); this.configurator.addAdditionalProperty("additionalPropertiesAsAttribute", FALSE); + this.configurator.addAdditionalProperty("initializeEmptyCollections", FALSE); this.configurator.addAdditionalProperty("additionalEnumTypeUnexpectedMember", FALSE); this.configurator.addAdditionalProperty("additionalEnumTypeUnexpectedMemberName", ""); this.configurator.addAdditionalProperty("additionalEnumTypeUnexpectedMemberStringValue", ""); @@ -368,6 +369,10 @@ public void withAdditionalPropertiesAsAttribute(final Boolean enable) { this.configurator.addAdditionalProperty("additionalPropertiesAsAttribute", Optional.ofNullable(enable).orElse(FALSE)); } + public void withInitializeEmptyCollections(final Boolean enable) { + this.configurator.addAdditionalProperty("initializeEmptyCollections", Optional.ofNullable(enable).orElse(FALSE)); + } + public static String transformToSafeConfigKey(String input) { return input.replaceAll("[^a-zA-Z0-9\\-_]", "_"); } diff --git a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute index cb995e110..ef43ddd2b 100644 --- a/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute +++ b/client/deployment/src/main/resources/templates/libraries/microprofile/pojo.qute @@ -39,7 +39,7 @@ public class {m.classname} {#if m.parent}extends {m.parent}{/if}{#if serializabl {/if} {#if v.hasValidation || v.required}{#include beanValidation.qute p=v/}{/if} {#if v.isContainer} - private {v.datatypeWithEnum} {v.name}{#if v.required && v.defaultValue} = {v.defaultValue}{/if}; + private {v.datatypeWithEnum} {v.name}{#if v.required && v.defaultValue} = {v.defaultValue}{#else if v.isArray && initializeEmptyCollections} = new {#if v.uniqueItems}LinkedHashSet{/if}{#if !v.uniqueItems}ArrayList{/if}<>(){#else if v.isMap && initializeEmptyCollections} = new HashMap<>(){/if}; {#else} private {v.datatypeWithEnum} {v.name}{#if v.defaultValue} = {v.defaultValue}{/if}; {/if} diff --git a/client/integration-tests/initialize-empty-collections/pom.xml b/client/integration-tests/initialize-empty-collections/pom.xml new file mode 100644 index 000000000..5e96d575f --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/pom.xml @@ -0,0 +1,89 @@ + + + + quarkus-openapi-generator-integration-tests + io.quarkiverse.openapi.generator + 3.0.0-SNAPSHOT + + 4.0.0 + + quarkus-openapi-generator-it-initialize-empty-collections + Quarkus - OpenAPI Generator - Integration Tests - Client - Initialize Empty Collections + + + + io.quarkiverse.openapi.generator + quarkus-openapi-generator + + + org.assertj + assertj-core + test + + + io.quarkus + quarkus-junit5 + test + + + + + + io.quarkus + quarkus-maven-plugin + true + + + + build + generate-code + generate-code-tests + + + + + + + + + native-image + + + native + + + + + + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + native + + + + + \ No newline at end of file diff --git a/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-empty-collections.yaml b/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-empty-collections.yaml new file mode 100644 index 000000000..559d04451 --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-empty-collections.yaml @@ -0,0 +1,282 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - Reactive Greeting Resource + operationId: hello + responses: + "200": + description: OK + content: + text/plain: + schema: + type: string + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + Type: + type: object + properties: + tags: + uniqueItems: true + type: array + items: + type: string + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-null-collections.yaml b/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-null-collections.yaml new file mode 100644 index 000000000..559d04451 --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/src/main/openapi/quarkus-simple-openapi-null-collections.yaml @@ -0,0 +1,282 @@ +--- +openapi: 3.0.3 +info: + title: greeting-flow API + version: "1.0" +paths: + /: + post: + requestBody: + content: + '*/*': + schema: + $ref: '#/components/schemas/CloudEvent' + responses: + "200": + description: OK + content: + application/json: + schema: + $ref: '#/components/schemas/Response' + /hello: + get: + tags: + - Reactive Greeting Resource + operationId: hello + responses: + "200": + description: OK + content: + text/plain: + schema: + type: string + /messaging/topics: + get: + tags: + - Quarkus Topics Information Resource + responses: + "200": + description: OK +components: + schemas: + Type: + type: object + properties: + tags: + uniqueItems: true + type: array + items: + type: string + CloudEvent: + type: object + properties: + specVersion: + $ref: '#/components/schemas/SpecVersion' + id: + type: string + type: + type: string + source: + format: uri + type: string + dataContentType: + type: string + dataSchema: + format: uri + type: string + subject: + type: string + time: + format: date-time + type: string + attributeNames: + uniqueItems: true + type: array + items: + type: string + extensionNames: + uniqueItems: true + type: array + items: + type: string + data: + $ref: '#/components/schemas/CloudEventData' + CloudEventData: + type: object + EntityTag: + type: object + properties: + value: + type: string + weak: + type: boolean + Family: + enum: + - INFORMATIONAL + - SUCCESSFUL + - REDIRECTION + - CLIENT_ERROR + - SERVER_ERROR + - OTHER + type: string + Link: + type: object + properties: + uri: + format: uri + type: string + uriBuilder: + $ref: '#/components/schemas/UriBuilder' + rel: + type: string + rels: + type: array + items: + type: string + title: + type: string + type: + type: string + params: + type: object + additionalProperties: + type: string + Locale: + type: object + properties: + language: + type: string + script: + type: string + country: + type: string + variant: + type: string + extensionKeys: + uniqueItems: true + type: array + items: + format: byte + type: string + unicodeLocaleAttributes: + uniqueItems: true + type: array + items: + type: string + unicodeLocaleKeys: + uniqueItems: true + type: array + items: + type: string + iSO3Language: + type: string + iSO3Country: + type: string + displayLanguage: + type: string + displayScript: + type: string + displayCountry: + type: string + displayVariant: + type: string + displayName: + type: string + MediaType: + type: object + properties: + type: + type: string + subtype: + type: string + parameters: + type: object + additionalProperties: + type: string + wildcardType: + type: boolean + wildcardSubtype: + type: boolean + MultivaluedMapStringObject: + type: object + additionalProperties: + type: array + items: + type: object + MultivaluedMapStringString: + type: object + additionalProperties: + type: array + items: + type: string + NewCookie: + type: object + properties: + name: + type: string + value: + type: string + version: + format: int32 + type: integer + path: + type: string + domain: + type: string + comment: + type: string + maxAge: + format: int32 + type: integer + expiry: + format: date + type: string + secure: + type: boolean + httpOnly: + type: boolean + Response: + type: object + properties: + status: + format: int32 + type: integer + statusInfo: + $ref: '#/components/schemas/StatusType' + entity: + type: object + mediaType: + $ref: '#/components/schemas/MediaType' + language: + $ref: '#/components/schemas/Locale' + length: + format: int32 + type: integer + allowedMethods: + uniqueItems: true + type: array + items: + type: string + cookies: + type: object + additionalProperties: + $ref: '#/components/schemas/NewCookie' + entityTag: + $ref: '#/components/schemas/EntityTag' + date: + format: date + type: string + lastModified: + format: date + type: string + location: + format: uri + type: string + links: + uniqueItems: true + type: array + items: + $ref: '#/components/schemas/Link' + metadata: + $ref: '#/components/schemas/MultivaluedMapStringObject' + headers: + $ref: '#/components/schemas/MultivaluedMapStringObject' + stringHeaders: + $ref: '#/components/schemas/MultivaluedMapStringString' + SpecVersion: + enum: + - V03 + - V1 + type: string + StatusType: + type: object + properties: + statusCode: + format: int32 + type: integer + family: + $ref: '#/components/schemas/Family' + reasonPhrase: + type: string + UriBuilder: + type: object diff --git a/client/integration-tests/initialize-empty-collections/src/main/resources/application.properties b/client/integration-tests/initialize-empty-collections/src/main/resources/application.properties new file mode 100644 index 000000000..fb4e9b409 --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/src/main/resources/application.properties @@ -0,0 +1,5 @@ +# with initialise empty collections = TRUE +quarkus.openapi-generator.codegen.spec.quarkus_simple_openapi_empty_collections_yaml.initialize-empty-collections=true +# with initialise empty collections = TRUE +quarkus.openapi-generator.codegen.spec.quarkus_simple_openapi_null_collections_yaml.initialize-empty-collections=false +quarkus.keycloak.devservices.enabled=false \ No newline at end of file diff --git a/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenFalseTest.java b/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenFalseTest.java new file mode 100644 index 000000000..86bc197c3 --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenFalseTest.java @@ -0,0 +1,35 @@ +package io.quarkiverse.openapi.generator.initialiseEmptyCollections; + +import jakarta.inject.Inject; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openapi.quarkus.quarkus_simple_openapi_null_collections_yaml.model.CloudEvent; +import org.openapi.quarkus.quarkus_simple_openapi_null_collections_yaml.model.Link; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusInitialiseEmptyCollectionWhenFalseTest { + + @Inject + ObjectMapper objectMapper; + + @Test + void when_initialize_empty_collections_is_false_then_should_not_initialize_collections() { + var cloudEvent = new CloudEvent(); + Assertions.assertThat(cloudEvent.getAttributeNames()).isNull(); + var link = new Link(); + Assertions.assertThat(link.getRels()).isNull(); + } + + @Test + void when_initialize_empty_collections_is_false_then_jackson_should_map_collections_correctly() + throws JsonProcessingException { + Assertions.assertThat(objectMapper.writeValueAsString(new Link())) + .isEqualTo("{}"); + } +} diff --git a/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenTrueTest.java b/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenTrueTest.java new file mode 100644 index 000000000..ba98762f5 --- /dev/null +++ b/client/integration-tests/initialize-empty-collections/src/test/java/io/quarkiverse/openapi/generator/initialiseEmptyCollections/QuarkusInitialiseEmptyCollectionWhenTrueTest.java @@ -0,0 +1,40 @@ +package io.quarkiverse.openapi.generator.initialiseEmptyCollections; + +import java.util.ArrayList; +import java.util.LinkedHashSet; + +import jakarta.inject.Inject; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.Test; +import org.openapi.quarkus.quarkus_simple_openapi_empty_collections_yaml.model.CloudEvent; +import org.openapi.quarkus.quarkus_simple_openapi_empty_collections_yaml.model.Link; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import io.quarkus.test.junit.QuarkusTest; + +@QuarkusTest +public class QuarkusInitialiseEmptyCollectionWhenTrueTest { + + @Inject + ObjectMapper objectMapper; + + @Test + void when_initialize_empty_collections_is_true_then_should_initialize_collections() { + var cloudEvent = new CloudEvent(); + Assertions.assertThat(cloudEvent.getAttributeNames()).isNotNull().isEmpty(); + Assertions.assertThat(cloudEvent.getAttributeNames()).isInstanceOf(LinkedHashSet.class); + var link = new Link(); + Assertions.assertThat(link.getRels()).isNotNull().isEmpty(); + Assertions.assertThat(link.getRels()).isInstanceOf(ArrayList.class); + } + + @Test + void when_initialize_empty_collections_is_true_then_jackson_should_map_collections_correctly() + throws JsonProcessingException { + Assertions.assertThat(objectMapper.writeValueAsString(new Link())) + .isEqualTo("{\"rels\":[],\"params\":{}}"); + } +} diff --git a/client/integration-tests/pom.xml b/client/integration-tests/pom.xml index 073765eb0..d961efc90 100644 --- a/client/integration-tests/pom.xml +++ b/client/integration-tests/pom.xml @@ -27,6 +27,7 @@ generation-input generation-tests include + initialize-empty-collections multipart-request mutiny mutiny-return-response diff --git a/docs/modules/ROOT/pages/client.adoc b/docs/modules/ROOT/pages/client.adoc index 9745df213..605a1b1a5 100644 --- a/docs/modules/ROOT/pages/client.adoc +++ b/docs/modules/ROOT/pages/client.adoc @@ -199,6 +199,11 @@ to true: quarkus.openapi-generator.codegen.spec.my_openapi_yaml.serializable-model=true ---- +[[initialize-empty-collections]] +== Initialize Empty Collections + +include::./includes/initialize-empty-collections.adoc[leveloffset=+1, opts=optional] + [[equals-hashcode]] == Equals and hashcode diff --git a/docs/modules/ROOT/pages/includes/initialize-empty-collections.adoc b/docs/modules/ROOT/pages/includes/initialize-empty-collections.adoc new file mode 100644 index 000000000..dd34d6568 --- /dev/null +++ b/docs/modules/ROOT/pages/includes/initialize-empty-collections.adoc @@ -0,0 +1,9 @@ +In the default configuration, the generated RestClient is designed to set container types (e.g., lists, maps, or other collections) to null when no data is provided by the API. + +However, if you prefer container types to default to empty values instead (e.g., an empty list or map), you can override the default behavior by setting the following property in your configuration: + +[source,properties] +quarkus.openapi-generator.codegen.spec.my_openapi_yaml.initialize-empty-collections=true + +When this property is set to true, the generator will ensure that container types are initialized with empty values instead of null, allowing you to avoid null-checks and directly work with populated collections. +This feature is particularly useful when you expect the generated code to follow a defensive programming approach, or when dealing with APIs that always expect empty containers instead of null values. \ No newline at end of file diff --git a/docs/modules/ROOT/pages/includes/quarkus-openapi-generator.adoc b/docs/modules/ROOT/pages/includes/quarkus-openapi-generator.adoc index 5886094b1..41d33043d 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-openapi-generator.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-openapi-generator.adoc @@ -475,6 +475,27 @@ endif::add-copy-button-to-env-var[] |string | +a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-initialize-empty-collections]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-initialize-empty-collections[`quarkus.openapi-generator.codegen.initialize-empty-collections`]## +ifdef::add-copy-button-to-config-props[] +config_property_copy_button:+++quarkus.openapi-generator.codegen.initialize-empty-collections+++[] +endif::add-copy-button-to-config-props[] + + +[.description] +-- +Initialise collections as empty instead of null + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_INITIALIZE_EMPTY_COLLECTIONS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_INITIALIZE_EMPTY_COLLECTIONS+++` +endif::add-copy-button-to-env-var[] +-- +|string +| + a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-verbose]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-verbose[`quarkus.openapi-generator.codegen.verbose`]## ifdef::add-copy-button-to-config-props[] config_property_copy_button:+++quarkus.openapi-generator.codegen.verbose+++[] @@ -1090,6 +1111,27 @@ endif::add-copy-button-to-env-var[] |string | +a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-initialize-empty-collections]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-initialize-empty-collections[`quarkus.openapi-generator.codegen.spec."spec-item".initialize-empty-collections`]## +ifdef::add-copy-button-to-config-props[] +config_property_copy_button:+++quarkus.openapi-generator.codegen.spec."spec-item".initialize-empty-collections+++[] +endif::add-copy-button-to-config-props[] + + +[.description] +-- +Initialise collections as empty instead of null + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_SPEC__SPEC_ITEM__INITIALIZE_EMPTY_COLLECTIONS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_SPEC__SPEC_ITEM__INITIALIZE_EMPTY_COLLECTIONS+++` +endif::add-copy-button-to-env-var[] +-- +|string +| + a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-base-package]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-base-package[`quarkus.openapi-generator.codegen.spec."spec-item".base-package`]## ifdef::add-copy-button-to-config-props[] config_property_copy_button:+++quarkus.openapi-generator.codegen.spec."spec-item".base-package+++[] diff --git a/docs/modules/ROOT/pages/includes/quarkus-openapi-generator_quarkus.openapi-generator.adoc b/docs/modules/ROOT/pages/includes/quarkus-openapi-generator_quarkus.openapi-generator.adoc index 5886094b1..41d33043d 100644 --- a/docs/modules/ROOT/pages/includes/quarkus-openapi-generator_quarkus.openapi-generator.adoc +++ b/docs/modules/ROOT/pages/includes/quarkus-openapi-generator_quarkus.openapi-generator.adoc @@ -475,6 +475,27 @@ endif::add-copy-button-to-env-var[] |string | +a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-initialize-empty-collections]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-initialize-empty-collections[`quarkus.openapi-generator.codegen.initialize-empty-collections`]## +ifdef::add-copy-button-to-config-props[] +config_property_copy_button:+++quarkus.openapi-generator.codegen.initialize-empty-collections+++[] +endif::add-copy-button-to-config-props[] + + +[.description] +-- +Initialise collections as empty instead of null + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_INITIALIZE_EMPTY_COLLECTIONS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_INITIALIZE_EMPTY_COLLECTIONS+++` +endif::add-copy-button-to-env-var[] +-- +|string +| + a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-verbose]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-verbose[`quarkus.openapi-generator.codegen.verbose`]## ifdef::add-copy-button-to-config-props[] config_property_copy_button:+++quarkus.openapi-generator.codegen.verbose+++[] @@ -1090,6 +1111,27 @@ endif::add-copy-button-to-env-var[] |string | +a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-initialize-empty-collections]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-initialize-empty-collections[`quarkus.openapi-generator.codegen.spec."spec-item".initialize-empty-collections`]## +ifdef::add-copy-button-to-config-props[] +config_property_copy_button:+++quarkus.openapi-generator.codegen.spec."spec-item".initialize-empty-collections+++[] +endif::add-copy-button-to-config-props[] + + +[.description] +-- +Initialise collections as empty instead of null + + +ifdef::add-copy-button-to-env-var[] +Environment variable: env_var_with_copy_button:+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_SPEC__SPEC_ITEM__INITIALIZE_EMPTY_COLLECTIONS+++[] +endif::add-copy-button-to-env-var[] +ifndef::add-copy-button-to-env-var[] +Environment variable: `+++QUARKUS_OPENAPI_GENERATOR_CODEGEN_SPEC__SPEC_ITEM__INITIALIZE_EMPTY_COLLECTIONS+++` +endif::add-copy-button-to-env-var[] +-- +|string +| + a|icon:lock[title=Fixed at build time] [[quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-base-package]] [.property-path]##link:#quarkus-openapi-generator_quarkus-openapi-generator-codegen-spec-spec-item-base-package[`quarkus.openapi-generator.codegen.spec."spec-item".base-package`]## ifdef::add-copy-button-to-config-props[] config_property_copy_button:+++quarkus.openapi-generator.codegen.spec."spec-item".base-package+++[] From 20a771866d5a027abe5ac1b09d0db6103801d879 Mon Sep 17 00:00:00 2001 From: Helber Belmiro Date: Tue, 13 May 2025 09:04:24 -0300 Subject: [PATCH 2/2] Update client/integration-tests/initialize-empty-collections/pom.xml Co-authored-by: Frederik Kischewski <56124748+fkischewski99@users.noreply.github.com> --- client/integration-tests/initialize-empty-collections/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/integration-tests/initialize-empty-collections/pom.xml b/client/integration-tests/initialize-empty-collections/pom.xml index 5e96d575f..e74929b38 100644 --- a/client/integration-tests/initialize-empty-collections/pom.xml +++ b/client/integration-tests/initialize-empty-collections/pom.xml @@ -3,7 +3,7 @@ quarkus-openapi-generator-integration-tests io.quarkiverse.openapi.generator - 3.0.0-SNAPSHOT + 3.0.0-lts-SNAPSHOT 4.0.0