From 282b22744c29034281f479a6e476d93e732ad2ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20C=C3=B4t=C3=A9?= Date: Sat, 25 Mar 2017 02:36:01 -0400 Subject: [PATCH] [Java][PlayFramework] Added some CLI Options + many fixes (#5180) * First commit of the Java Play Framework server generator. It is highly based on Spring so there might me a couple of things that don't make sense (like options or parameters) for the Play Framework. * Fix suggestions in the PR discussion + add .bat and .sh file as requested. * Updated Readme.md file * Remove unused mustache file + fix baseName vs paramName in all the mustache files. * Fix the compilation error when we have a body which is a list or map. Doesn't fix the problem with the annotation itself. * Fix the problem with the Http.MultipartFormData.FilePart * - Add "wrapCalls" and "useSwaggerUI" CLI Options and updated what handleException does to follow Play Framework lifecycle more closely - Updated all mustache files accordingly - Updated the sample - Updates Play Framework version to the latest 2.5.13 --- .../languages/JavaPlayFrameworkCodegen.java | 40 +++++++++++++-- .../JavaPlayFramework/apiCall.mustache | 13 ++--- .../JavaPlayFramework/application.mustache | 6 ++- .../JavaPlayFramework/build.mustache | 4 +- .../JavaPlayFramework/errorHandler.mustache | 49 +++++++++++++++++++ .../JavaPlayFramework/newApi.mustache | 2 +- .../newApiController.mustache | 8 +-- .../newApiInterface.mustache | 2 +- .../JavaPlayFramework/plugins.mustache | 2 +- .../JavaPlayFramework/routes.mustache | 2 + .../JavaPlayFrameworkOptionsTest.java | 4 ++ .../JavaPlayFrameworkOptionsProvider.java | 4 ++ .../app/controllers/PetApiController.java | 16 +++--- .../app/controllers/PetApiControllerImp.java | 16 +++--- .../PetApiControllerImpInterface.java | 16 +++--- .../app/controllers/StoreApiController.java | 8 +-- .../controllers/StoreApiControllerImp.java | 8 +-- .../StoreApiControllerImpInterface.java | 8 +-- .../app/controllers/UserApiController.java | 16 +++--- .../app/controllers/UserApiControllerImp.java | 16 +++--- .../UserApiControllerImpInterface.java | 16 +++--- .../app/swagger/ApiCall.java | 13 ++--- .../app/swagger/ErrorHandler.java | 49 +++++++++++++++++++ .../java-play-framework/conf/application.conf | 4 +- .../java-play-framework/project/plugins.sbt | 2 +- 25 files changed, 230 insertions(+), 94 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/JavaPlayFramework/errorHandler.mustache create mode 100644 samples/server/petstore/java-play-framework/app/swagger/ErrorHandler.java diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPlayFrameworkCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPlayFrameworkCodegen.java index c8043f5b86..67ed428add 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPlayFrameworkCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/JavaPlayFrameworkCodegen.java @@ -19,6 +19,8 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea public static final String CONTROLLER_ONLY = "controllerOnly"; public static final String USE_INTERFACES = "useInterfaces"; public static final String HANDLE_EXCEPTIONS = "handleExceptions"; + public static final String WRAP_CALLS = "wrapCalls"; + public static final String USE_SWAGGER_UI = "useSwaggerUI"; protected String title = "swagger-petstore"; protected String configPackage = "io.swagger.configuration"; @@ -27,6 +29,8 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea protected boolean useInterfaces = true; protected boolean useBeanValidation = true; protected boolean handleExceptions = true; + protected boolean wrapCalls = true; + protected boolean useSwaggerUI = true; public JavaPlayFrameworkCodegen() { super(); @@ -56,7 +60,9 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea cliOptions.add(createBooleanCliWithDefault(CONTROLLER_ONLY, "Whether to generate only API interface stubs without the server files.", controllerOnly)); cliOptions.add(createBooleanCliWithDefault(USE_BEANVALIDATION, "Use BeanValidation API annotations", useBeanValidation)); cliOptions.add(createBooleanCliWithDefault(USE_INTERFACES, "Makes the controllerImp implements an interface to facilitate automatic completion when updating from version x to y of your spec", useInterfaces)); - cliOptions.add(createBooleanCliWithDefault(HANDLE_EXCEPTIONS, "Add a wrapper to each controller to handle exceptions that pop in the controller", handleExceptions)); + 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)); } @Override @@ -120,6 +126,18 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea writePropertyBack(HANDLE_EXCEPTIONS, handleExceptions); } + if (additionalProperties.containsKey(WRAP_CALLS)) { + this.setWrapCalls(convertPropertyToBoolean(WRAP_CALLS)); + } else { + writePropertyBack(WRAP_CALLS, wrapCalls); + } + + if (additionalProperties.containsKey(USE_SWAGGER_UI)) { + this.setUseSwaggerUI(convertPropertyToBoolean(USE_SWAGGER_UI)); + } else { + writePropertyBack(USE_SWAGGER_UI, useSwaggerUI); + } + //We don't use annotation anymore importMapping.remove("ApiModelProperty"); importMapping.remove("ApiModel"); @@ -128,7 +146,6 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea supportingFiles.add(new SupportingFile("README.mustache", "", "README")); supportingFiles.add(new SupportingFile("LICENSE.mustache", "", "LICENSE")); supportingFiles.add(new SupportingFile("build.mustache", "", "build.sbt")); - supportingFiles.add(new SupportingFile("swagger.mustache", "public", "swagger.json")); //Project folder supportingFiles.add(new SupportingFile("buildproperties.mustache", "project", "build.properties")); @@ -142,11 +159,18 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea //App/Utils folder supportingFiles.add(new SupportingFile("swaggerUtils.mustache", "app/swagger", "SwaggerUtils.java")); if (this.handleExceptions) { + supportingFiles.add(new SupportingFile("errorHandler.mustache", "app/swagger", "ErrorHandler.java")); + } + + if(this.wrapCalls) { supportingFiles.add(new SupportingFile("apiCall.mustache", "app/swagger", "ApiCall.java")); } - //App/Controllers - supportingFiles.add(new SupportingFile("apiDocController.mustache", "app/controllers", "ApiDocController.java")); + if(this.useSwaggerUI) { + //App/Controllers + supportingFiles.add(new SupportingFile("swagger.mustache", "public", "swagger.json")); + supportingFiles.add(new SupportingFile("apiDocController.mustache", "app/controllers", "ApiDocController.java")); + } //We remove the default api.mustache that is used apiTemplateFiles.remove("api.mustache"); @@ -210,6 +234,14 @@ public class JavaPlayFrameworkCodegen extends AbstractJavaCodegen implements Bea this.handleExceptions = handleExceptions; } + public void setWrapCalls(boolean wrapCalls) { + this.wrapCalls = wrapCalls; + } + + public void setUseSwaggerUI(boolean useSwaggerUI) { + this.useSwaggerUI = useSwaggerUI; + } + @Override public Map postProcessOperations(Map objs) { Map operations = (Map) objs.get("operations"); diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/apiCall.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/apiCall.mustache index 51492a54de..2ca308045b 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/apiCall.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/apiCall.mustache @@ -13,18 +13,15 @@ public class ApiCall extends Action { @Inject private ApiCall() {} - public CompletionStage call(Http.Context ctx) { + public CompletionStage call(Http.Context ctx) { try { //TODO: Do stuff you want to handle with each API call (metrics, logging, etc..) return delegate.call(ctx); } catch (Throwable t) { - //TODO: handle error the way you want - return CompletableFuture.completedFuture(handleExceptions(t)); + //TODO: log the error in your metric + + //We rethrow this error so it will be caught in the ErrorHandler + throw t; } } - - private Result handleExceptions(Throwable t) { - //TODO: Handle exception that need special response (return a special apimodel, etc..) - return ok(); - } } \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/application.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/application.mustache index c69d0c9154..2cfab81ea4 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/application.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/application.mustache @@ -15,6 +15,10 @@ # HOCON will fall back to substituting environment variable: #mykey = ${JAVA_HOME} +{{#handleExceptions}} +play.http.errorHandler="swagger.ErrorHandler" +{{/handleExceptions}} + ## Akka # https://www.playframework.com/documentation/latest/ScalaAkka#Configuration # https://www.playframework.com/documentation/latest/JavaAkka#Configuration @@ -35,8 +39,6 @@ akka { #log-config-on-start = true } -api.version="1.0" - ## Secret key # http://www.playframework.com/documentation/latest/ApplicationSecret # ~~~~~ diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/build.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/build.mustache index e3fb024daa..8d345a9347 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/build.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/build.mustache @@ -9,8 +9,8 @@ scalaVersion := "2.11.7" libraryDependencies ++= Seq( javaJdbc, cache, -javaWs, -"org.webjars" % "swagger-ui" % "2.2.10-1"{{#useBeanValidation}}, +javaWs{{#useSwaggerUI}}, +"org.webjars" % "swagger-ui" % "2.2.10-1"{{/useSwaggerUI}}{{#useBeanValidation}}, "javax.validation" % "validation-api" % "1.1.0.Final" {{/useBeanValidation}} ) diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/errorHandler.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/errorHandler.mustache new file mode 100644 index 0000000000..2c813411a5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/errorHandler.mustache @@ -0,0 +1,49 @@ +package swagger; + + +import play.*; +import play.api.OptionalSourceMapper; +import play.api.UsefulException; +import play.api.routing.Router; +import play.http.DefaultHttpErrorHandler; +import play.mvc.Http.*; +import play.mvc.*; + +import javax.inject.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import static play.mvc.Results.*; + +@Singleton +public class ErrorHandler extends DefaultHttpErrorHandler { + + @Inject + public ErrorHandler(Configuration configuration, Environment environment, OptionalSourceMapper sourceMapper, Provider routes) { + super(configuration, environment, sourceMapper, routes); + } + + @Override + protected CompletionStage onDevServerError(RequestHeader request, UsefulException exception) { + return CompletableFuture.completedFuture( + handleExceptions(exception) + ); + } + + @Override + protected CompletionStage onProdServerError(RequestHeader request, UsefulException exception) { + return CompletableFuture.completedFuture( + handleExceptions(exception) + ); + } + + @Override + protected void logServerError(RequestHeader request, UsefulException usefulException) { + //Since the error is already handled, we don't want to print anything on the console + //But if you want to have the error printed in the console, just delete this override + } + + private Result handleExceptions(Throwable t) { + //TODO: Handle exception that need special response (return a special apimodel, notFound(), etc..) + return ok(); + } +} diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApi.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApi.mustache index d95580df00..79696c93f5 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApi.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApi.mustache @@ -14,7 +14,7 @@ import javax.validation.constraints.*; {{#operations}} public class {{classname}}ControllerImp {{#useInterfaces}}implements {{classname}}ControllerImpInterface{{/useInterfaces}} { {{#operation}} - public {{>returnTypes}} {{operationId}}({{#allParams}}{{>pathParams}}{{>queryParams}}{{>bodyParams}}{{>formParams}}{{>headerParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { + public {{>returnTypes}} {{operationId}}({{#allParams}}{{>pathParams}}{{>queryParams}}{{>bodyParams}}{{>formParams}}{{>headerParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {{#handleExceptions}}throws Exception{{/handleExceptions}} { //Do your magic!!! {{#returnType}}return new {{>returnTypesNoVoidNoAbstract}}();{{/returnType}} } diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiController.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiController.mustache index 61e64c6868..b209947327 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiController.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiController.mustache @@ -19,9 +19,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import javax.validation.constraints.*; {{/useBeanValidation}} -{{#handleExceptions}} +{{#wrapCalls}} import swagger.SwaggerUtils.ApiAction; -{{/handleExceptions}} +{{/wrapCalls}} {{>generatedAnnotation}} {{#operations}} @@ -38,8 +38,8 @@ public class {{classname}}Controller extends Controller { {{#operation}} - {{#handleExceptions}}@ApiAction{{/handleExceptions}} - public Result {{operationId}}({{#pathParams}}{{>pathParams}}{{#hasMore}},{{/hasMore}}{{/pathParams}}) {{#bodyParams}}throws IOException{{/bodyParams}} { + {{#wrapCalls}}@ApiAction{{/wrapCalls}} + public Result {{operationId}}({{#pathParams}}{{>pathParams}}{{#hasMore}},{{/hasMore}}{{/pathParams}}) {{^handleExceptions}}{{#bodyParams}}throws IOException{{/bodyParams}}{{/handleExceptions}}{{#handleExceptions}}throws Exception{{/handleExceptions}} { {{#bodyParams}} {{#collectionFormat}} //TODO: Maybe implement this in the future if we can support collection in the body params: see bug in swagger-play: https://github.com/swagger-api/swagger-play/issues/130 diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiInterface.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiInterface.mustache index 367c16f358..3780094381 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiInterface.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/newApiInterface.mustache @@ -15,7 +15,7 @@ import javax.validation.constraints.*; {{#operations}} public interface {{classname}}ControllerImpInterface { {{#operation}} - {{>returnTypes}} {{operationId}}({{#allParams}}{{>pathParams}}{{>queryParams}}{{>bodyParams}}{{>formParams}}{{>headerParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}); + {{>returnTypes}} {{operationId}}({{#allParams}}{{>pathParams}}{{>queryParams}}{{>bodyParams}}{{>formParams}}{{>headerParams}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) {{#handleExceptions}}throws Exception{{/handleExceptions}}; {{/operation}} } diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/plugins.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/plugins.mustache index ca73a99c72..ea1f1061fb 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/plugins.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/plugins.mustache @@ -1,2 +1,2 @@ // The Play plugin -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.10") +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.13") diff --git a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/routes.mustache b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/routes.mustache index d6723e75ce..9932b65885 100644 --- a/modules/swagger-codegen/src/main/resources/JavaPlayFramework/routes.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaPlayFramework/routes.mustache @@ -2,7 +2,9 @@ # This file defines all application routes (Higher priority routes first) # ~~~~ +{{#useSwaggerUI}} GET /api controllers.ApiDocController.api +{{/useSwaggerUI}} {{#apiInfo}} {{#apis}} diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/javaPlayFramework/JavaPlayFrameworkOptionsTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/javaPlayFramework/JavaPlayFrameworkOptionsTest.java index 6866074ba9..fba16839e2 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/javaPlayFramework/JavaPlayFrameworkOptionsTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/javaPlayFramework/JavaPlayFrameworkOptionsTest.java @@ -61,6 +61,10 @@ public class JavaPlayFrameworkOptionsTest extends JavaClientOptionsTest { times = 1; clientCodegen.setHandleExceptions(Boolean.valueOf(JavaPlayFrameworkOptionsProvider.HANDLE_EXCEPTIONS)); times = 1; + clientCodegen.setWrapCalls(Boolean.valueOf(JavaPlayFrameworkOptionsProvider.WRAP_CALLS)); + times = 1; + clientCodegen.setUseSwaggerUI(Boolean.valueOf(JavaPlayFrameworkOptionsProvider.USE_SWAGGER_UI)); + times = 1; }}; } } diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaPlayFrameworkOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaPlayFrameworkOptionsProvider.java index 5ca000025c..eae8343fbb 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaPlayFrameworkOptionsProvider.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/JavaPlayFrameworkOptionsProvider.java @@ -13,6 +13,8 @@ public class JavaPlayFrameworkOptionsProvider extends JavaOptionsProvider { public static final String USE_BEANVALIDATION = "true"; public static final String USE_INTERFACES = "true"; public static final String HANDLE_EXCEPTIONS = "true"; + public static final String WRAP_CALLS = "true"; + public static final String USE_SWAGGER_UI = "true"; @Override public String getLanguage() { @@ -29,6 +31,8 @@ public class JavaPlayFrameworkOptionsProvider extends JavaOptionsProvider { options.put(JavaPlayFrameworkCodegen.USE_BEANVALIDATION, USE_BEANVALIDATION); options.put(JavaPlayFrameworkCodegen.USE_INTERFACES, USE_INTERFACES); options.put(JavaPlayFrameworkCodegen.HANDLE_EXCEPTIONS, HANDLE_EXCEPTIONS); + options.put(JavaPlayFrameworkCodegen.WRAP_CALLS, WRAP_CALLS); + options.put(JavaPlayFrameworkCodegen.USE_SWAGGER_UI, USE_SWAGGER_UI); return options; } diff --git a/samples/server/petstore/java-play-framework/app/controllers/PetApiController.java b/samples/server/petstore/java-play-framework/app/controllers/PetApiController.java index 357f3f1bbb..4676ab98ca 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/PetApiController.java +++ b/samples/server/petstore/java-play-framework/app/controllers/PetApiController.java @@ -33,7 +33,7 @@ public class PetApiController extends Controller { @ApiAction - public Result addPet() throws IOException { + public Result addPet() throws Exception { JsonNode nodebody = request().body().asJson(); Pet body; if (nodebody != null) { @@ -48,7 +48,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result deletePet(Long petId) { + public Result deletePet(Long petId) throws Exception { String valueapiKey = request().getHeader("api_key"); String apiKey; if (valueapiKey != null) { @@ -63,7 +63,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result findPetsByStatus() { + public Result findPetsByStatus() throws Exception { //TODO: Maybe implement this in the future if we can support collection in the body params: see bug in swagger-play: https://github.com/swagger-api/swagger-play/issues/130 //TODO: Tt seems it is not detected that it's a list based on the collectionFormat field? //WIP when both bugs will be fixed @@ -79,7 +79,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result findPetsByTags() { + public Result findPetsByTags() throws Exception { //TODO: Maybe implement this in the future if we can support collection in the body params: see bug in swagger-play: https://github.com/swagger-api/swagger-play/issues/130 //TODO: Tt seems it is not detected that it's a list based on the collectionFormat field? //WIP when both bugs will be fixed @@ -95,7 +95,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result getPetById(Long petId) { + public Result getPetById(Long petId) throws Exception { Pet obj = imp.getPetById(petId); JsonNode result = mapper.valueToTree(obj); return ok(result); @@ -103,7 +103,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result updatePet() throws IOException { + public Result updatePet() throws Exception { JsonNode nodebody = request().body().asJson(); Pet body; if (nodebody != null) { @@ -118,7 +118,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result updatePetWithForm(String petId) { + public Result updatePetWithForm(String petId) throws Exception { String valuename = ((String[]) request().body().asMultipartFormData().asFormUrlEncoded().get("name"))[0]; String name; if (valuename != null) { @@ -141,7 +141,7 @@ public class PetApiController extends Controller { } @ApiAction - public Result uploadFile(Long petId) { + public Result uploadFile(Long petId) throws Exception { String valueadditionalMetadata = ((String[]) request().body().asMultipartFormData().asFormUrlEncoded().get("additionalMetadata"))[0]; String additionalMetadata; if (valueadditionalMetadata != null) { diff --git a/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImp.java b/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImp.java index f3f1b829b7..9433941bc3 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImp.java +++ b/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImp.java @@ -10,42 +10,42 @@ import java.util.HashMap; import javax.validation.constraints.*; public class PetApiControllerImp implements PetApiControllerImpInterface { - public void addPet(Pet body) { + public void addPet(Pet body) throws Exception { //Do your magic!!! } - public void deletePet(Long petId, String apiKey) { + public void deletePet(Long petId, String apiKey) throws Exception { //Do your magic!!! } - public List findPetsByStatus( List status) { + public List findPetsByStatus( List status) throws Exception { //Do your magic!!! return new ArrayList(); } - public List findPetsByTags( List tags) { + public List findPetsByTags( List tags) throws Exception { //Do your magic!!! return new ArrayList(); } - public Pet getPetById(Long petId) { + public Pet getPetById(Long petId) throws Exception { //Do your magic!!! return new Pet(); } - public void updatePet(Pet body) { + public void updatePet(Pet body) throws Exception { //Do your magic!!! } - public void updatePetWithForm(String petId, String name, String status) { + public void updatePetWithForm(String petId, String name, String status) throws Exception { //Do your magic!!! } - public void uploadFile(Long petId, String additionalMetadata, Http.MultipartFormData.FilePart file) { + public void uploadFile(Long petId, String additionalMetadata, Http.MultipartFormData.FilePart file) throws Exception { //Do your magic!!! } diff --git a/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImpInterface.java b/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImpInterface.java index 00f0964f10..c7c65c48ec 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework/app/controllers/PetApiControllerImpInterface.java @@ -11,20 +11,20 @@ import java.util.HashMap; import javax.validation.constraints.*; public interface PetApiControllerImpInterface { - void addPet(Pet body); + void addPet(Pet body) throws Exception; - void deletePet(Long petId, String apiKey); + void deletePet(Long petId, String apiKey) throws Exception; - List findPetsByStatus( List status); + List findPetsByStatus( List status) throws Exception; - List findPetsByTags( List tags); + List findPetsByTags( List tags) throws Exception; - Pet getPetById(Long petId); + Pet getPetById(Long petId) throws Exception; - void updatePet(Pet body); + void updatePet(Pet body) throws Exception; - void updatePetWithForm(String petId, String name, String status); + void updatePetWithForm(String petId, String name, String status) throws Exception; - void uploadFile(Long petId, String additionalMetadata, Http.MultipartFormData.FilePart file); + void uploadFile(Long petId, String additionalMetadata, Http.MultipartFormData.FilePart file) throws Exception; } diff --git a/samples/server/petstore/java-play-framework/app/controllers/StoreApiController.java b/samples/server/petstore/java-play-framework/app/controllers/StoreApiController.java index ec44ea87d1..ecaf7ff406 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/StoreApiController.java +++ b/samples/server/petstore/java-play-framework/app/controllers/StoreApiController.java @@ -33,14 +33,14 @@ public class StoreApiController extends Controller { @ApiAction - public Result deleteOrder(String orderId) { + public Result deleteOrder(String orderId) throws Exception { imp.deleteOrder(orderId); return ok(); } @ApiAction - public Result getInventory() { + public Result getInventory() throws Exception { Map obj = imp.getInventory(); JsonNode result = mapper.valueToTree(obj); return ok(result); @@ -48,7 +48,7 @@ public class StoreApiController extends Controller { } @ApiAction - public Result getOrderById(String orderId) { + public Result getOrderById(String orderId) throws Exception { Order obj = imp.getOrderById(orderId); JsonNode result = mapper.valueToTree(obj); return ok(result); @@ -56,7 +56,7 @@ public class StoreApiController extends Controller { } @ApiAction - public Result placeOrder() throws IOException { + public Result placeOrder() throws Exception { JsonNode nodebody = request().body().asJson(); Order body; if (nodebody != null) { diff --git a/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImp.java b/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImp.java index 6ff8ca7b8f..e276e9c592 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImp.java +++ b/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImp.java @@ -10,22 +10,22 @@ import java.util.HashMap; import javax.validation.constraints.*; public class StoreApiControllerImp implements StoreApiControllerImpInterface { - public void deleteOrder(String orderId) { + public void deleteOrder(String orderId) throws Exception { //Do your magic!!! } - public Map getInventory() { + public Map getInventory() throws Exception { //Do your magic!!! return new HashMap(); } - public Order getOrderById(String orderId) { + public Order getOrderById(String orderId) throws Exception { //Do your magic!!! return new Order(); } - public Order placeOrder(Order body) { + public Order placeOrder(Order body) throws Exception { //Do your magic!!! return new Order(); } diff --git a/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImpInterface.java b/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImpInterface.java index 9640da22e6..707dfae1f0 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework/app/controllers/StoreApiControllerImpInterface.java @@ -11,12 +11,12 @@ import java.util.HashMap; import javax.validation.constraints.*; public interface StoreApiControllerImpInterface { - void deleteOrder(String orderId); + void deleteOrder(String orderId) throws Exception; - Map getInventory(); + Map getInventory() throws Exception; - Order getOrderById(String orderId); + Order getOrderById(String orderId) throws Exception; - Order placeOrder(Order body); + Order placeOrder(Order body) throws Exception; } diff --git a/samples/server/petstore/java-play-framework/app/controllers/UserApiController.java b/samples/server/petstore/java-play-framework/app/controllers/UserApiController.java index 7db5c2f2bf..69ebd3bc45 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/UserApiController.java +++ b/samples/server/petstore/java-play-framework/app/controllers/UserApiController.java @@ -33,7 +33,7 @@ public class UserApiController extends Controller { @ApiAction - public Result createUser() throws IOException { + public Result createUser() throws Exception { JsonNode nodebody = request().body().asJson(); User body; if (nodebody != null) { @@ -48,7 +48,7 @@ public class UserApiController extends Controller { } @ApiAction - public Result createUsersWithArrayInput() throws IOException { + public Result createUsersWithArrayInput() throws Exception { JsonNode nodebody = request().body().asJson(); List body; if (nodebody != null) { @@ -63,7 +63,7 @@ public class UserApiController extends Controller { } @ApiAction - public Result createUsersWithListInput() throws IOException { + public Result createUsersWithListInput() throws Exception { JsonNode nodebody = request().body().asJson(); List body; if (nodebody != null) { @@ -78,14 +78,14 @@ public class UserApiController extends Controller { } @ApiAction - public Result deleteUser(String username) { + public Result deleteUser(String username) throws Exception { imp.deleteUser(username); return ok(); } @ApiAction - public Result getUserByName(String username) { + public Result getUserByName(String username) throws Exception { User obj = imp.getUserByName(username); JsonNode result = mapper.valueToTree(obj); return ok(result); @@ -93,7 +93,7 @@ public class UserApiController extends Controller { } @ApiAction - public Result loginUser() { + public Result loginUser() throws Exception { String valueusername = request().getQueryString("username"); String username; if (valueusername != null) { @@ -117,14 +117,14 @@ public class UserApiController extends Controller { } @ApiAction - public Result logoutUser() { + public Result logoutUser() throws Exception { imp.logoutUser(); return ok(); } @ApiAction - public Result updateUser(String username) throws IOException { + public Result updateUser(String username) throws Exception { JsonNode nodebody = request().body().asJson(); User body; if (nodebody != null) { diff --git a/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImp.java b/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImp.java index 74c0739c4f..d4cdd55295 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImp.java +++ b/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImp.java @@ -10,42 +10,42 @@ import java.util.HashMap; import javax.validation.constraints.*; public class UserApiControllerImp implements UserApiControllerImpInterface { - public void createUser(User body) { + public void createUser(User body) throws Exception { //Do your magic!!! } - public void createUsersWithArrayInput(List body) { + public void createUsersWithArrayInput(List body) throws Exception { //Do your magic!!! } - public void createUsersWithListInput(List body) { + public void createUsersWithListInput(List body) throws Exception { //Do your magic!!! } - public void deleteUser(String username) { + public void deleteUser(String username) throws Exception { //Do your magic!!! } - public User getUserByName(String username) { + public User getUserByName(String username) throws Exception { //Do your magic!!! return new User(); } - public String loginUser( String username, String password) { + public String loginUser( String username, String password) throws Exception { //Do your magic!!! return new String(); } - public void logoutUser() { + public void logoutUser() throws Exception { //Do your magic!!! } - public void updateUser(String username, User body) { + public void updateUser(String username, User body) throws Exception { //Do your magic!!! } diff --git a/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImpInterface.java b/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImpInterface.java index 7d5af6fe41..1a18e789ee 100644 --- a/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImpInterface.java +++ b/samples/server/petstore/java-play-framework/app/controllers/UserApiControllerImpInterface.java @@ -11,20 +11,20 @@ import java.util.HashMap; import javax.validation.constraints.*; public interface UserApiControllerImpInterface { - void createUser(User body); + void createUser(User body) throws Exception; - void createUsersWithArrayInput(List body); + void createUsersWithArrayInput(List body) throws Exception; - void createUsersWithListInput(List body); + void createUsersWithListInput(List body) throws Exception; - void deleteUser(String username); + void deleteUser(String username) throws Exception; - User getUserByName(String username); + User getUserByName(String username) throws Exception; - String loginUser( String username, String password); + String loginUser( String username, String password) throws Exception; - void logoutUser(); + void logoutUser() throws Exception; - void updateUser(String username, User body); + void updateUser(String username, User body) throws Exception; } diff --git a/samples/server/petstore/java-play-framework/app/swagger/ApiCall.java b/samples/server/petstore/java-play-framework/app/swagger/ApiCall.java index 51492a54de..2ca308045b 100644 --- a/samples/server/petstore/java-play-framework/app/swagger/ApiCall.java +++ b/samples/server/petstore/java-play-framework/app/swagger/ApiCall.java @@ -13,18 +13,15 @@ public class ApiCall extends Action { @Inject private ApiCall() {} - public CompletionStage call(Http.Context ctx) { + public CompletionStage call(Http.Context ctx) { try { //TODO: Do stuff you want to handle with each API call (metrics, logging, etc..) return delegate.call(ctx); } catch (Throwable t) { - //TODO: handle error the way you want - return CompletableFuture.completedFuture(handleExceptions(t)); + //TODO: log the error in your metric + + //We rethrow this error so it will be caught in the ErrorHandler + throw t; } } - - private Result handleExceptions(Throwable t) { - //TODO: Handle exception that need special response (return a special apimodel, etc..) - return ok(); - } } \ No newline at end of file diff --git a/samples/server/petstore/java-play-framework/app/swagger/ErrorHandler.java b/samples/server/petstore/java-play-framework/app/swagger/ErrorHandler.java new file mode 100644 index 0000000000..2c813411a5 --- /dev/null +++ b/samples/server/petstore/java-play-framework/app/swagger/ErrorHandler.java @@ -0,0 +1,49 @@ +package swagger; + + +import play.*; +import play.api.OptionalSourceMapper; +import play.api.UsefulException; +import play.api.routing.Router; +import play.http.DefaultHttpErrorHandler; +import play.mvc.Http.*; +import play.mvc.*; + +import javax.inject.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionStage; +import static play.mvc.Results.*; + +@Singleton +public class ErrorHandler extends DefaultHttpErrorHandler { + + @Inject + public ErrorHandler(Configuration configuration, Environment environment, OptionalSourceMapper sourceMapper, Provider routes) { + super(configuration, environment, sourceMapper, routes); + } + + @Override + protected CompletionStage onDevServerError(RequestHeader request, UsefulException exception) { + return CompletableFuture.completedFuture( + handleExceptions(exception) + ); + } + + @Override + protected CompletionStage onProdServerError(RequestHeader request, UsefulException exception) { + return CompletableFuture.completedFuture( + handleExceptions(exception) + ); + } + + @Override + protected void logServerError(RequestHeader request, UsefulException usefulException) { + //Since the error is already handled, we don't want to print anything on the console + //But if you want to have the error printed in the console, just delete this override + } + + private Result handleExceptions(Throwable t) { + //TODO: Handle exception that need special response (return a special apimodel, notFound(), etc..) + return ok(); + } +} diff --git a/samples/server/petstore/java-play-framework/conf/application.conf b/samples/server/petstore/java-play-framework/conf/application.conf index c69d0c9154..ae2e5cbcd0 100644 --- a/samples/server/petstore/java-play-framework/conf/application.conf +++ b/samples/server/petstore/java-play-framework/conf/application.conf @@ -15,6 +15,8 @@ # HOCON will fall back to substituting environment variable: #mykey = ${JAVA_HOME} +play.http.errorHandler="swagger.ErrorHandler" + ## Akka # https://www.playframework.com/documentation/latest/ScalaAkka#Configuration # https://www.playframework.com/documentation/latest/JavaAkka#Configuration @@ -35,8 +37,6 @@ akka { #log-config-on-start = true } -api.version="1.0" - ## Secret key # http://www.playframework.com/documentation/latest/ApplicationSecret # ~~~~~ diff --git a/samples/server/petstore/java-play-framework/project/plugins.sbt b/samples/server/petstore/java-play-framework/project/plugins.sbt index ca73a99c72..ea1f1061fb 100644 --- a/samples/server/petstore/java-play-framework/project/plugins.sbt +++ b/samples/server/petstore/java-play-framework/project/plugins.sbt @@ -1,2 +1,2 @@ // The Play plugin -addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.10") +addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.13")