From 2801c0cb88839ca9756e4f528f86ad5a9cc54239 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 27 Nov 2020 23:30:46 +0800 Subject: [PATCH] [Java][Play] Fix compilation issues when using the supportAsync option (#7864) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix async in java play generator * add async operation option * Remove the return null and replace with a return at the right place. Co-authored-by: Jean-François Côté --- docs/generators/java-play-framework.md | 1 + .../languages/JavaPlayFrameworkCodegen.java | 12 ++++ .../newApiInterface.mustache | 3 +- .../responseToResult.mustache | 21 ++++-- .../PetApiControllerImpInterface.java | 53 +++++++++----- .../StoreApiControllerImpInterface.java | 18 +++-- .../UserApiControllerImpInterface.java | 71 +++++++++++++------ 7 files changed, 132 insertions(+), 47 deletions(-) diff --git a/docs/generators/java-play-framework.md b/docs/generators/java-play-framework.md index 98cccb0cbdf..1caf6202b9d 100644 --- a/docs/generators/java-play-framework.md +++ b/docs/generators/java-play-framework.md @@ -52,6 +52,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl |sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true| |sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |true| |sourceFolder|source folder for generated code| |/app| +|supportAsync|Support Async operations| |false| |title|server title name or client service name| |openapi-java-playframework| |useBeanValidation|Use BeanValidation API annotations| |true| |useInterfaces|Makes the controllerImp implements an interface to facilitate automatic completion when updating from version x to y of your spec| |true| diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java index 38c06150c56..c81f020190a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaPlayFrameworkCodegen.java @@ -44,6 +44,7 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea public static final String HANDLE_EXCEPTIONS = "handleExceptions"; public static final String WRAP_CALLS = "wrapCalls"; public static final String USE_SWAGGER_UI = "useSwaggerUI"; + public static final String SUPPORT_ASYNC = "supportAsync"; protected String title = "openapi-java-playframework"; protected String configPackage = "org.openapitools.configuration"; @@ -54,6 +55,7 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea protected boolean handleExceptions = true; protected boolean wrapCalls = true; protected boolean useSwaggerUI = true; + protected boolean supportAsync = false; public JavaPlayFrameworkCodegen() { super(); @@ -94,6 +96,7 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea cliOptions.add(createBooleanCliWithDefault(HANDLE_EXCEPTIONS, "Add a 'throw exception' to each controller function. Add also a custom error handler where you can put your custom logic", handleExceptions)); cliOptions.add(createBooleanCliWithDefault(WRAP_CALLS, "Add a wrapper to each controller function to handle things like metrics, response modification, etc..", wrapCalls)); cliOptions.add(createBooleanCliWithDefault(USE_SWAGGER_UI, "Add a route to /api which show your documentation in swagger-ui. Will also import needed dependencies", useSwaggerUI)); + cliOptions.add(createBooleanCliWithDefault(SUPPORT_ASYNC, "Support Async operations", supportAsync)); } @Override @@ -167,6 +170,11 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea } writePropertyBack(USE_SWAGGER_UI, useSwaggerUI); + if (additionalProperties.containsKey(SUPPORT_ASYNC)) { + this.setSupportAsync(convertPropertyToBoolean(SUPPORT_ASYNC)); + } + writePropertyBack(SUPPORT_ASYNC, supportAsync); + //We don't use annotation anymore importMapping.remove("ApiModelProperty"); importMapping.remove("ApiModel"); @@ -287,6 +295,10 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea this.useSwaggerUI = useSwaggerUI; } + public void setSupportAsync(boolean supportAsync) { + this.supportAsync = supportAsync; + } + @Override public Map postProcessOperationsWithModels(Map objs, List allModels) { Map operations = (Map) objs.get("operations"); diff --git a/modules/openapi-generator/src/main/resources/JavaPlayFramework/newApiInterface.mustache b/modules/openapi-generator/src/main/resources/JavaPlayFramework/newApiInterface.mustache index f8ab89e0d38..f6c22df60d2 100644 --- a/modules/openapi-generator/src/main/resources/JavaPlayFramework/newApiInterface.mustache +++ b/modules/openapi-generator/src/main/resources/JavaPlayFramework/newApiInterface.mustache @@ -17,6 +17,7 @@ import openapitools.OpenAPIUtils; import static play.mvc.Results.ok; import play.api.libs.Files.TemporaryFile; {{#supportAsync}} +import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletableFuture; {{/supportAsync}} @@ -42,4 +43,4 @@ public abstract class {{classname}}ControllerImpInterface { {{/operation}} } -{{/operations}} \ No newline at end of file +{{/operations}} diff --git a/modules/openapi-generator/src/main/resources/JavaPlayFramework/responseToResult.mustache b/modules/openapi-generator/src/main/resources/JavaPlayFramework/responseToResult.mustache index 557f7988e2c..7d5a43be4cb 100644 --- a/modules/openapi-generator/src/main/resources/JavaPlayFramework/responseToResult.mustache +++ b/modules/openapi-generator/src/main/resources/JavaPlayFramework/responseToResult.mustache @@ -1,7 +1,8 @@ {{^controllerOnly}} {{^returnType}} {{#supportAsync}} -return CompletableFuture.supplyAsync(() -> { +CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { {{/supportAsync}} {{/returnType}} {{#returnType}}{{#supportAsync}}CompletionStage<{{>returnTypesNoVoid}}> stage = {{/supportAsync}}{{^supportAsync}}{{>returnTypesNoVoid}} obj = {{/supportAsync}}{{/returnType}}{{^returnType}}{{#supportAsync}} {{/supportAsync}}{{/returnType}}{{^useInterfaces}}imp.{{/useInterfaces}}{{operationId}}(request{{#hasParams}}, {{/hasParams}}{{#allParams}}{{paramName}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}{{#supportAsync}}.thenApply(obj -> { {{/supportAsync}}{{/returnType}}{{^supportAsync}};{{/supportAsync}}{{#supportAsync}}{{^returnType}};{{/returnType}}{{/supportAsync}} @@ -53,7 +54,7 @@ return CompletableFuture.supplyAsync(() -> { {{/returnType}} {{#returnType}} {{#supportAsync}} -stage.thenApply(obj -> { +return stage.thenApply(obj -> { {{/supportAsync}} {{^isResponseFile}} {{#supportAsync}} {{/supportAsync}}JsonNode result = mapper.valueToTree(obj); @@ -64,12 +65,24 @@ stage.thenApply(obj -> { {{/isResponseFile}} {{/returnType}} {{^returnType}} -{{#supportAsync}} {{/supportAsync}}return ok(); +{{#supportAsync}} + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; +{{/supportAsync}} +{{^supportAsync}} +return ok(); +{{/supportAsync}} {{/returnType}} +{{#returnType}} {{#supportAsync}} }); {{/supportAsync}} +{{/returnType}} {{/controllerOnly}} {{#controllerOnly}} return ok(); -{{/controllerOnly}} \ No newline at end of file +{{/controllerOnly}} diff --git a/samples/server/petstore/java-play-framework-async/app/controllers/PetApiControllerImpInterface.java b/samples/server/petstore/java-play-framework-async/app/controllers/PetApiControllerImpInterface.java index 5c1864e46b9..b4c2ce413bf 100644 --- a/samples/server/petstore/java-play-framework-async/app/controllers/PetApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework-async/app/controllers/PetApiControllerImpInterface.java @@ -17,6 +17,7 @@ import com.fasterxml.jackson.databind.JsonNode; import openapitools.OpenAPIUtils; import static play.mvc.Results.ok; import play.api.libs.Files.TemporaryFile; +import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletableFuture; @@ -28,20 +29,30 @@ public abstract class PetApiControllerImpInterface { private ObjectMapper mapper = new ObjectMapper(); public CompletionStage addPetHttp(Http.Request request, Pet body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { addPet(request, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void addPet(Http.Request request, Pet body) throws Exception; public CompletionStage deletePetHttp(Http.Request request, Long petId, String apiKey) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { deletePet(request, petId, apiKey); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } @@ -56,7 +67,7 @@ public abstract class PetApiControllerImpInterface { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -74,7 +85,7 @@ stage.thenApply(obj -> { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -90,7 +101,7 @@ stage.thenApply(obj -> { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -100,20 +111,30 @@ stage.thenApply(obj -> { public abstract CompletionStage getPetById(Http.Request request, Long petId) throws Exception; public CompletionStage updatePetHttp(Http.Request request, Pet body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { updatePet(request, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void updatePet(Http.Request request, Pet body) throws Exception; public CompletionStage updatePetWithFormHttp(Http.Request request, Long petId, String name, String status) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { updatePetWithForm(request, petId, name, status); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } @@ -126,7 +147,7 @@ stage.thenApply(obj -> { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); diff --git a/samples/server/petstore/java-play-framework-async/app/controllers/StoreApiControllerImpInterface.java b/samples/server/petstore/java-play-framework-async/app/controllers/StoreApiControllerImpInterface.java index 3c59e23a74e..7f3aa115d9a 100644 --- a/samples/server/petstore/java-play-framework-async/app/controllers/StoreApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework-async/app/controllers/StoreApiControllerImpInterface.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.JsonNode; import openapitools.OpenAPIUtils; import static play.mvc.Results.ok; import play.api.libs.Files.TemporaryFile; +import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletableFuture; @@ -27,10 +28,15 @@ public abstract class StoreApiControllerImpInterface { private ObjectMapper mapper = new ObjectMapper(); public CompletionStage deleteOrderHttp(Http.Request request, String orderId) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { deleteOrder(request, orderId); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } @@ -40,7 +46,7 @@ public abstract class StoreApiControllerImpInterface { CompletionStage> stage = getInventory(request).thenApply(obj -> { return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -56,7 +62,7 @@ stage.thenApply(obj -> { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -72,7 +78,7 @@ stage.thenApply(obj -> { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); diff --git a/samples/server/petstore/java-play-framework-async/app/controllers/UserApiControllerImpInterface.java b/samples/server/petstore/java-play-framework-async/app/controllers/UserApiControllerImpInterface.java index 62e6468f672..6544f446140 100644 --- a/samples/server/petstore/java-play-framework-async/app/controllers/UserApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework-async/app/controllers/UserApiControllerImpInterface.java @@ -16,6 +16,7 @@ import com.fasterxml.jackson.databind.JsonNode; import openapitools.OpenAPIUtils; import static play.mvc.Results.ok; import play.api.libs.Files.TemporaryFile; +import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletableFuture; @@ -27,40 +28,60 @@ public abstract class UserApiControllerImpInterface { private ObjectMapper mapper = new ObjectMapper(); public CompletionStage createUserHttp(Http.Request request, User body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { createUser(request, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void createUser(Http.Request request, User body) throws Exception; public CompletionStage createUsersWithArrayInputHttp(Http.Request request, List body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { createUsersWithArrayInput(request, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void createUsersWithArrayInput(Http.Request request, List body) throws Exception; public CompletionStage createUsersWithListInputHttp(Http.Request request, List body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { createUsersWithListInput(request, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void createUsersWithListInput(Http.Request request, List body) throws Exception; public CompletionStage deleteUserHttp(Http.Request request, String username) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { deleteUser(request, username); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } @@ -73,7 +94,7 @@ public abstract class UserApiControllerImpInterface { } return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -86,7 +107,7 @@ stage.thenApply(obj -> { CompletionStage stage = loginUser(request, username, password).thenApply(obj -> { return obj; }); -stage.thenApply(obj -> { +return stage.thenApply(obj -> { JsonNode result = mapper.valueToTree(obj); return ok(result); }); @@ -96,20 +117,30 @@ stage.thenApply(obj -> { public abstract CompletionStage loginUser(Http.Request request, @NotNull String username, @NotNull String password) throws Exception; public CompletionStage logoutUserHttp(Http.Request request) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { logoutUser(request); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; } public abstract void logoutUser(Http.Request request) throws Exception; public CompletionStage updateUserHttp(Http.Request request, String username, User body) throws Exception { - return CompletableFuture.supplyAsync(() -> { + CompletableFuture result = CompletableFuture.supplyAsync(() -> { + try { updateUser(request, username, body); - return ok(); -}); + } catch (Exception e) { + throw new CompletionException(e); + } + return ok(); + }); + return result; }