From 0986b7509c6009d277171ae1ac1686d42c76e035 Mon Sep 17 00:00:00 2001 From: Romain Date: Tue, 24 Sep 2024 07:46:50 +0200 Subject: [PATCH] feat(java client): Generalize generateClientAsBean (#19229) Add usage of generateClientAsBean annotation in RestClient and Webclient templates and include it in documentation. Issue: #19229 --- docs/generators/java-microprofile.md | 2 +- docs/generators/java.md | 2 +- .../codegen/languages/JavaClientCodegen.java | 2 +- .../libraries/restclient/ApiClient.mustache | 7 +- .../Java/libraries/restclient/api.mustache | 6 ++ .../libraries/webclient/ApiClient.mustache | 6 ++ .../Java/libraries/webclient/api.mustache | 6 ++ .../codegen/java/JavaClientCodegenTest.java | 68 +++++++++++++++++++ .../org/openapitools/client/ApiClient.java | 1 - .../org/openapitools/client/ApiClient.java | 1 - .../org/openapitools/client/ApiClient.java | 1 - .../org/openapitools/client/ApiClient.java | 1 - .../org/openapitools/client/ApiClient.java | 1 - .../org/openapitools/client/ApiClient.java | 1 - 14 files changed, 95 insertions(+), 10 deletions(-) diff --git a/docs/generators/java-microprofile.md b/docs/generators/java-microprofile.md index b9778bbfe802..e95b02856dca 100644 --- a/docs/generators/java-microprofile.md +++ b/docs/generators/java-microprofile.md @@ -51,7 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null| |failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false| |generateBuilders|Whether to generate builders for models| |false| -|generateClientAsBean|For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false| +|generateClientAsBean|For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false| |generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false| |gradleProperties|Append additional Gradle properties to the gradle.properties file| |null| |groupId|groupId in generated pom.xml| |org.openapitools| diff --git a/docs/generators/java.md b/docs/generators/java.md index bb371ceeca74..20f423e76865 100644 --- a/docs/generators/java.md +++ b/docs/generators/java.md @@ -51,7 +51,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |errorObjectType|Error Object type. (This option is for okhttp-gson only)| |null| |failOnUnknownProperties|Fail Jackson de-serialization on unknown properties| |false| |generateBuilders|Whether to generate builders for models| |false| -|generateClientAsBean|For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false| +|generateClientAsBean|For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).| |false| |generateConstructorWithAllArgs|whether to generate a constructor for all arguments| |false| |gradleProperties|Append additional Gradle properties to the gradle.properties file| |null| |groupId|groupId in generated pom.xml| |org.openapitools| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java index 8239da1fd6bd..dd63271ba288 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaClientCodegen.java @@ -239,7 +239,7 @@ public JavaClientCodegen() { cliOptions.add(CliOption.newString(MICROPROFILE_REST_CLIENT_VERSION, "Version of MicroProfile Rest Client API.")); cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_SINGLE_REQUEST_PARAMETER, "Setting this property to true will generate functions with a single argument containing all API endpoint parameters instead of one argument per parameter. ONLY jersey2, jersey3, okhttp-gson, microprofile, Spring RestClient support this option.")); cliOptions.add(CliOption.newBoolean(WEBCLIENT_BLOCKING_OPERATIONS, "Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync", this.webclientBlockingOperations)); - cliOptions.add(CliOption.newBoolean(GENERATE_CLIENT_AS_BEAN, "For resttemplate, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).", this.generateClientAsBean)); + cliOptions.add(CliOption.newBoolean(GENERATE_CLIENT_AS_BEAN, "For resttemplate, restclient and webclient, configure whether to create `ApiClient.java` and Apis clients as bean (with `@Component` annotation).", this.generateClientAsBean)); cliOptions.add(CliOption.newBoolean(SUPPORT_URL_QUERY, "Generate toUrlQueryString in POJO (default to true). Available on `native`, `apache-httpclient` libraries.")); cliOptions.add(CliOption.newBoolean(USE_ENUM_CASE_INSENSITIVE, "Use `equalsIgnoreCase` when String for enum comparison", useEnumCaseInsensitive)); cliOptions.add(CliOption.newBoolean(FAIL_ON_UNKNOWN_PROPERTIES, "Fail Jackson de-serialization on unknown properties", this.failOnUnknownProperties)); diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache index 8af468cfb4cf..a613409323c7 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/restclient/ApiClient.mustache @@ -23,6 +23,9 @@ import org.springframework.http.converter.json.MappingJackson2HttpMessageConvert {{#withXml}} import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; {{/withXml}} +{{#generateClientAsBean}} +import org.springframework.stereotype.Component; +{{/generateClientAsBean}} import org.springframework.util.CollectionUtils; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; @@ -58,8 +61,10 @@ import {{invokerPackage}}.auth.ApiKeyAuth; {{#hasOAuthMethods}} import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} - {{>generatedAnnotation}} +{{#generateClientAsBean}} +@Component("{{invokerPackage}}.ApiClient") +{{/generateClientAsBean}} public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/restclient/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/restclient/api.mustache index 6d8f7780c4b6..933d827da927 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/restclient/api.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/restclient/api.mustache @@ -17,6 +17,9 @@ import {{javaxPackage}}.validation.Valid; {{/useBeanValidation}} import org.springframework.beans.factory.annotation.Autowired; +{{#generateClientAsBean}} +import org.springframework.stereotype.Component; +{{/generateClientAsBean}} import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.core.ParameterizedTypeReference; @@ -30,6 +33,9 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; {{>generatedAnnotation}} +{{#generateClientAsBean}} +@Component("{{package}}.{{classname}}") +{{/generateClientAsBean}} {{#operations}} public class {{classname}} { private ApiClient apiClient; diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache index ce696128e6db..7720e7434de8 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/webclient/ApiClient.mustache @@ -37,6 +37,9 @@ import org.springframework.web.reactive.function.client.ClientResponse; import org.springframework.web.reactive.function.BodyInserter; import org.springframework.web.reactive.function.BodyInserters; import org.springframework.web.reactive.function.client.ExchangeStrategies; +{{#generateClientAsBean}} +import org.springframework.stereotype.Component; +{{/generateClientAsBean}} import reactor.core.publisher.Mono; import reactor.core.publisher.Flux; import java.util.Optional; @@ -76,6 +79,9 @@ import {{invokerPackage}}.auth.OAuth; {{/hasOAuthMethods}} {{>generatedAnnotation}} +{{#generateClientAsBean}} +@Component("{{invokerPackage}}.ApiClient") +{{/generateClientAsBean}} public class ApiClient{{#jsr310}} extends JavaTimeFormatter{{/jsr310}} { public enum CollectionFormat { CSV(","), TSV("\t"), SSV(" "), PIPES("|"), MULTI(null); diff --git a/modules/openapi-generator/src/main/resources/Java/libraries/webclient/api.mustache b/modules/openapi-generator/src/main/resources/Java/libraries/webclient/api.mustache index b71837f55c4e..0851040f0b12 100644 --- a/modules/openapi-generator/src/main/resources/Java/libraries/webclient/api.mustache +++ b/modules/openapi-generator/src/main/resources/Java/libraries/webclient/api.mustache @@ -17,6 +17,9 @@ import {{javaxPackage}}.validation.Valid; {{/useBeanValidation}} import org.springframework.beans.factory.annotation.Autowired; +{{#generateClientAsBean}} +import org.springframework.stereotype.Component; +{{/generateClientAsBean}} import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.core.ParameterizedTypeReference; @@ -32,6 +35,9 @@ import reactor.core.publisher.Mono; import reactor.core.publisher.Flux; {{>generatedAnnotation}} +{{#generateClientAsBean}} +@Component("{{package}}.{{classname}}") +{{/generateClientAsBean}} {{#operations}} public class {{classname}} { private ApiClient apiClient; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java index abab35febc4b..7ab23e1a353e 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaClientCodegenTest.java @@ -2080,6 +2080,74 @@ public void shouldNotAddAdditionalModelAnnotationsToAbstractOpenApiSchema_issue1 TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/api/PetApi.java"), "@Component"); } + @Test public void testRestClientWithGeneratedClientAsBeanDisabled() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") + .addAdditionalProperty(JavaClientCodegen.GENERATE_CLIENT_AS_BEAN, false) + .setLibrary(RESTCLIENT) + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + validateJavaSourceFiles(files); + TestUtils.assertFileNotContains(output.resolve("src/main/java/xyz/abcdef/ApiClient.java"), "@Component"); + TestUtils.assertFileNotContains(output.resolve("src/main/java/xyz/abcdef/api/PetApi.java"), "@Component"); + } + + @Test public void testRestClientWithGeneratedClientAsBeanEnabled() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") + .addAdditionalProperty(JavaClientCodegen.GENERATE_CLIENT_AS_BEAN, true) + .setLibrary(RESTCLIENT) + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + validateJavaSourceFiles(files); + TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/ApiClient.java"), "@Component"); + TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/api/PetApi.java"), "@Component"); + } + + @Test public void testWebClientWithGeneratedClientAsBeanDisabled() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") + .addAdditionalProperty(JavaClientCodegen.GENERATE_CLIENT_AS_BEAN, false) + .setLibrary(WEBCLIENT ) + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + validateJavaSourceFiles(files); + TestUtils.assertFileNotContains(output.resolve("src/main/java/xyz/abcdef/ApiClient.java"), "@Component"); + TestUtils.assertFileNotContains(output.resolve("src/main/java/xyz/abcdef/api/PetApi.java"), "@Component"); + } + + @Test public void testWebClientWithGeneratedClientAsBeanEnabled() { + final Path output = newTempFolder(); + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .addAdditionalProperty(CodegenConstants.API_PACKAGE, "xyz.abcdef.api") + .addAdditionalProperty(JavaClientCodegen.GENERATE_CLIENT_AS_BEAN, true) + .setLibrary(WEBCLIENT ) + .setInputSpec("src/test/resources/3_0/petstore.yaml") + .setOutputDir(output.toString().replace("\\", "/")); + + List files = new DefaultGenerator().opts(configurator.toClientOptInput()).generate(); + + validateJavaSourceFiles(files); + TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/ApiClient.java"), "@Component"); + TestUtils.assertFileContains(output.resolve("src/main/java/xyz/abcdef/api/PetApi.java"), "@Component"); + } + @Test public void testRestTemplateWithUseBeanValidationEnabled() { final Path output = newTempFolder(); final CodegenConfigurator configurator = new CodegenConfigurator() diff --git a/samples/client/echo_api/java/restclient/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/echo_api/java/restclient/src/main/java/org/openapitools/client/ApiClient.java index cadf8f35e864..8dac2c2c9b95 100644 --- a/samples/client/echo_api/java/restclient/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/echo_api/java/restclient/src/main/java/org/openapitools/client/ApiClient.java @@ -55,7 +55,6 @@ import org.openapitools.client.auth.HttpBasicAuth; import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat { diff --git a/samples/client/others/java/restclient-useAbstractionForFiles/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/others/java/restclient-useAbstractionForFiles/src/main/java/org/openapitools/client/ApiClient.java index 490ab1033dfa..7dc7f17c7479 100644 --- a/samples/client/others/java/restclient-useAbstractionForFiles/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/others/java/restclient-useAbstractionForFiles/src/main/java/org/openapitools/client/ApiClient.java @@ -55,7 +55,6 @@ import org.openapitools.client.auth.HttpBasicAuth; import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat { diff --git a/samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java index c42a51c9a78e..19d0d2fde69b 100644 --- a/samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/restclient-nullable-arrays/src/main/java/org/openapitools/client/ApiClient.java @@ -55,7 +55,6 @@ import org.openapitools.client.auth.HttpBasicAuth; import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat { diff --git a/samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java index 51ae07b26f24..074e4fedd8ba 100644 --- a/samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/restclient-swagger2/src/main/java/org/openapitools/client/ApiClient.java @@ -56,7 +56,6 @@ import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; import org.openapitools.client.auth.OAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat { diff --git a/samples/client/petstore/java/restclient-useSingleRequestParameter/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/restclient-useSingleRequestParameter/src/main/java/org/openapitools/client/ApiClient.java index 51ae07b26f24..074e4fedd8ba 100644 --- a/samples/client/petstore/java/restclient-useSingleRequestParameter/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/restclient-useSingleRequestParameter/src/main/java/org/openapitools/client/ApiClient.java @@ -56,7 +56,6 @@ import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; import org.openapitools.client.auth.OAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat { diff --git a/samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java b/samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java index 51ae07b26f24..074e4fedd8ba 100644 --- a/samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java +++ b/samples/client/petstore/java/restclient/src/main/java/org/openapitools/client/ApiClient.java @@ -56,7 +56,6 @@ import org.openapitools.client.auth.HttpBearerAuth; import org.openapitools.client.auth.ApiKeyAuth; import org.openapitools.client.auth.OAuth; - @jakarta.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen", comments = "Generator version: 7.9.0-SNAPSHOT") public class ApiClient extends JavaTimeFormatter { public enum CollectionFormat {