From 2524e8fb0abeb81ec16adc1f92e197275539f2d2 Mon Sep 17 00:00:00 2001 From: Oleh Kurpiak Date: Tue, 6 Dec 2022 07:30:47 +0200 Subject: [PATCH] [Java][WebClient] global blocking operations config (#14076) * [Java][WebClient] global blocking operations config * update samples --- docs/generators/java.md | 1 + .../codegen/languages/JavaClientCodegen.java | 18 ++++++++++++ .../codegen/java/JavaClientCodegenTest.java | 29 +++++++++++++++++++ ...ith-fake-endpoints-models-for-testing.yaml | 1 + .../java/apache-httpclient/api/openapi.yaml | 1 + .../petstore/java/feign/api/openapi.yaml | 1 + .../java/native-async/api/openapi.yaml | 1 + .../petstore/java/native/api/openapi.yaml | 1 + .../petstore/java/webclient/api/openapi.yaml | 1 + .../src/main/resources/META-INF/openapi.yml | 1 + .../src/main/resources/META-INF/openapi.yml | 1 + 11 files changed, 56 insertions(+) diff --git a/docs/generators/java.md b/docs/generators/java.md index 63e46d8ed383..43a723d2ed5c 100644 --- a/docs/generators/java.md +++ b/docs/generators/java.md @@ -90,6 +90,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |useRxJava2|Whether to use the RxJava2 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false| |useRxJava3|Whether to use the RxJava3 adapter with the retrofit2 library. IMPORTANT: This option has been deprecated.| |false| |useSingleRequestParameter|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 support this option.| |false| +|webclientBlockingOperations|Making all WebClient operations blocking(sync). Note that if on operation 'x-webclient-blocking: false' then such operation won't be sync| |false| |withXml|whether to include support for application/xml content type and include XML annotations in the model (works with libraries that provide support for JSON and XML)| |false| ## SUPPORTED VENDOR EXTENSIONS 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 fe59a2216c10..fba5de02c161 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 @@ -91,6 +91,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen public static final String MICROPROFILE_REST_CLIENT_DEFAULT_ROOT_PACKAGE = "javax"; public static final String MICROPROFILE_DEFAULT = "default"; public static final String MICROPROFILE_KUMULUZEE = "kumuluzee"; + public static final String WEBCLIENT_BLOCKING_OPERATIONS = "webclientBlockingOperations"; public static final String SERIALIZATION_LIBRARY_GSON = "gson"; public static final String SERIALIZATION_LIBRARY_JACKSON = "jackson"; @@ -126,6 +127,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen protected String rootJavaEEPackage; protected Map mpRestClientVersions = new HashMap<>(); protected boolean useSingleRequestParameter = false; + protected boolean webclientBlockingOperations = false; private static class MpRestClientVersion { public final String rootPackage; @@ -204,6 +206,7 @@ public JavaClientCodegen() { cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC + " Only jersey2, jersey3, native, okhttp-gson support this option.")); 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 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)); supportedLibraries.put(JERSEY1, "HTTP client: Jersey client 1.19.x. JSON processing: Jackson 2.9.x. Enable gzip request encoding using '-DuseGzipFeature=true'. IMPORTANT NOTE: jersey 1.x is no longer actively maintained so please upgrade to 'jersey3' or other HTTP libraries instead."); supportedLibraries.put(JERSEY2, "HTTP client: Jersey client 2.25.1. JSON processing: Jackson 2.9.x"); @@ -413,6 +416,9 @@ public void processOpts() { this.setErrorObjectType(additionalProperties.get(ERROR_OBJECT_TYPE).toString()); } additionalProperties.put(ERROR_OBJECT_TYPE, errorObjectType); + if (additionalProperties.containsKey(WEBCLIENT_BLOCKING_OPERATIONS)) { + this.webclientBlockingOperations = Boolean.parseBoolean(additionalProperties.get(WEBCLIENT_BLOCKING_OPERATIONS).toString()); + } final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/"); final String apiFolder = (sourceFolder + '/' + apiPackage).replace(".", "/"); @@ -817,6 +823,18 @@ public int compare(CodegenParameter one, CodegenParameter another) { objs = AbstractJavaJAXRSServerCodegen.jaxrsPostProcessOperations(objs); } + if (WEBCLIENT.equals(getLibrary())) { + OperationMap operations = objs.getOperations(); + if (operations != null) { + List ops = operations.getOperation(); + for (CodegenOperation operation : ops) { + if (!operation.vendorExtensions.containsKey(VendorExtension.X_WEBCLIENT_BLOCKING.getName()) && webclientBlockingOperations) { + operation.vendorExtensions.put(VendorExtension.X_WEBCLIENT_BLOCKING.getName(), true); + } + } + } + } + return objs; } 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 81bdccd09a61..9efb39220365 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 @@ -993,6 +993,35 @@ public void testWebClientFormMultipart() throws IOException { ); } + @Test + public void shouldGenerateBlockingAndNoBlockingOperationsForWebClient() throws IOException { + Map properties = new HashMap<>(); + properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api"); + properties.put(JavaClientCodegen.WEBCLIENT_BLOCKING_OPERATIONS, true); + + File output = Files.createTempDirectory("test").toFile(); + output.deleteOnExit(); + + final CodegenConfigurator configurator = new CodegenConfigurator() + .setGeneratorName("java") + .setLibrary(JavaClientCodegen.WEBCLIENT) + .setAdditionalProperties(properties) + .setInputSpec("src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml") + .setOutputDir(output.getAbsolutePath().replace("\\", "/")); + + DefaultGenerator generator = new DefaultGenerator(); + Map files = generator.opts(configurator.toClientOptInput()).generate().stream() + .collect(Collectors.toMap(File::getName, Function.identity())); + + JavaFileAssert.assertThat(files.get("StoreApi.java")) + .assertMethod("getInventory").hasReturnType("Mono>") //explicit 'x-webclient-blocking: false' which overrides global config + .toFileAssert() + .assertMethod("placeOrder").hasReturnType("Order"); // use global config + + JavaFileAssert.assertThat(files.get("PetApi.java")) + .assertMethod("findPetsByStatus").hasReturnType("List"); // explicit 'x-webclient-blocking: true' which overrides global config + } + @Test public void testAllowModelWithNoProperties() throws Exception { File output = Files.createTempDirectory("test").toFile(); diff --git a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml index 2401e56127f4..6ec5b66e0e65 100644 --- a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml +++ b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml @@ -318,6 +318,7 @@ paths: summary: Returns pet inventories by status description: Returns a map of status codes to quantities operationId: getInventory + x-webclient-blocking: false responses: '200': description: successful operation diff --git a/samples/client/petstore/java/apache-httpclient/api/openapi.yaml b/samples/client/petstore/java/apache-httpclient/api/openapi.yaml index f9cbedf1e42f..2828944e5542 100644 --- a/samples/client/petstore/java/apache-httpclient/api/openapi.yaml +++ b/samples/client/petstore/java/apache-httpclient/api/openapi.yaml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/client/petstore/java/feign/api/openapi.yaml b/samples/client/petstore/java/feign/api/openapi.yaml index f9cbedf1e42f..2828944e5542 100644 --- a/samples/client/petstore/java/feign/api/openapi.yaml +++ b/samples/client/petstore/java/feign/api/openapi.yaml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/client/petstore/java/native-async/api/openapi.yaml b/samples/client/petstore/java/native-async/api/openapi.yaml index f9cbedf1e42f..2828944e5542 100644 --- a/samples/client/petstore/java/native-async/api/openapi.yaml +++ b/samples/client/petstore/java/native-async/api/openapi.yaml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/client/petstore/java/native/api/openapi.yaml b/samples/client/petstore/java/native/api/openapi.yaml index f9cbedf1e42f..2828944e5542 100644 --- a/samples/client/petstore/java/native/api/openapi.yaml +++ b/samples/client/petstore/java/native/api/openapi.yaml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/client/petstore/java/webclient/api/openapi.yaml b/samples/client/petstore/java/webclient/api/openapi.yaml index f9cbedf1e42f..2828944e5542 100644 --- a/samples/client/petstore/java/webclient/api/openapi.yaml +++ b/samples/client/petstore/java/webclient/api/openapi.yaml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/server/petstore/java-helidon-server/mp/src/main/resources/META-INF/openapi.yml b/samples/server/petstore/java-helidon-server/mp/src/main/resources/META-INF/openapi.yml index 7a9042f14f1c..6667e32d34cb 100644 --- a/samples/server/petstore/java-helidon-server/mp/src/main/resources/META-INF/openapi.yml +++ b/samples/server/petstore/java-helidon-server/mp/src/main/resources/META-INF/openapi.yml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: diff --git a/samples/server/petstore/java-helidon-server/se/src/main/resources/META-INF/openapi.yml b/samples/server/petstore/java-helidon-server/se/src/main/resources/META-INF/openapi.yml index 7a9042f14f1c..6667e32d34cb 100644 --- a/samples/server/petstore/java-helidon-server/se/src/main/resources/META-INF/openapi.yml +++ b/samples/server/petstore/java-helidon-server/se/src/main/resources/META-INF/openapi.yml @@ -358,6 +358,7 @@ paths: summary: Returns pet inventories by status tags: - store + x-webclient-blocking: false x-accepts: application/json /store/order: post: