From 29b4098a8d24fa64a18437bfe314da88ee661391 Mon Sep 17 00:00:00 2001 From: Ian Chan Date: Sat, 19 Dec 2015 23:03:59 +1300 Subject: [PATCH 1/4] Spring-MVC config "j8-async": Uses async servlet & Java 8 interface default This template is mainly for Maven code-gen plugin use-case - when Swagger spec on existing project changes there is no need to manually copy/paste the new functions from the generated client. This will provide a default (empty) implementation to existing impl and user just need to override the stub implementation. Because it generates an interface instead of a concrete stub, an implementation will be needed to actuate a service end-point. And don't forget to put @Controller on the implementation! --- .../languages/SpringMVCServerCodegen.java | 14 +++- .../JavaSpringMVC/api-j8-async.mustache | 64 +++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100755 modules/swagger-codegen/src/main/resources/JavaSpringMVC/api-j8-async.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java index 446185bcd47e..23ffe6c0fc4b 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java @@ -18,12 +18,13 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen public static final String CONFIG_PACKAGE = "configPackage"; protected String title = "Petstore Server"; protected String configPackage = ""; + protected String templateFileName = "api.mustache"; public SpringMVCServerCodegen() { super(); outputFolder = "generated-code/javaSpringMVC"; modelTemplateFiles.put("model.mustache", ".java"); - apiTemplateFiles.put("api.mustache", ".java"); + apiTemplateFiles.put(templateFileName, ".java"); embeddedTemplateDir = templateDir = "JavaSpringMVC"; apiPackage = "io.swagger.api"; modelPackage = "io.swagger.model"; @@ -51,6 +52,11 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen ); cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code")); + + supportedLibraries.clear(); + supportedLibraries.put(DEFAULT_LIBRARY, "Default Spring MVC server stub."); + supportedLibraries.put("j8-async", "Use async servlet feature and Java 8's default interface. Generating interface with service " + + "declaration is useful when using Maven plugin. Just provide a implementation with @Controller to instantiate service."); } public CodegenType getTag() { @@ -168,6 +174,12 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen } } } + if("j8-async".equals(getLibrary())) { + apiTemplateFiles.remove(this.templateFileName); + this.templateFileName = "api-j8-async.mustache"; + apiTemplateFiles.put(this.templateFileName, ".java"); + } + return objs; } diff --git a/modules/swagger-codegen/src/main/resources/JavaSpringMVC/api-j8-async.mustache b/modules/swagger-codegen/src/main/resources/JavaSpringMVC/api-j8-async.mustache new file mode 100755 index 000000000000..b11e5c2db202 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpringMVC/api-j8-async.mustache @@ -0,0 +1,64 @@ +package {{apiPackage}}; + +import {{modelPackage}}.*; + +{{#imports}}import {{import}}; +{{/imports}} + +import java.util.concurrent.Callable; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.AuthorizationScope; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestPart; +import org.springframework.web.multipart.MultipartFile; + +import java.util.List; + +import static org.springframework.http.MediaType.*; + +@Controller +@RequestMapping(value = "/{{baseName}}", produces = {APPLICATION_JSON_VALUE}) +@Api(value = "/{{baseName}}", description = "the {{baseName}} API") +{{>generatedAnnotation}} +{{#operations}} +public interface {{classname}} { + {{#operation}} + + @ApiOperation(value = "{{{summary}}}", notes = "{{{notes}}}", response = {{{returnType}}}.class{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = { + {{#authMethods}}@Authorization(value = "{{name}}"{{#isOAuth}}, scopes = { + {{#scopes}}@AuthorizationScope(scope = "{{scope}}", description = "{{description}}"){{#hasMore}}, + {{/hasMore}}{{/scopes}} + }{{/isOAuth}}){{#hasMore}}, + {{/hasMore}}{{/authMethods}} + }{{/hasAuthMethods}}) + @ApiResponses(value = { {{#responses}} + @ApiResponse(code = {{{code}}}, message = "{{{message}}}"){{#hasMore}},{{/hasMore}}{{/responses}} }) + @RequestMapping(value = "{{path}}", + {{#hasProduces}}produces = { {{#produces}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}} + {{#hasConsumes}}consumes = { {{#consumes}}"{{mediaType}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}} + method = RequestMethod.{{httpMethod}}) + default CallablereturnTypes}}>> {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}}, + {{/hasMore}}{{/allParams}}) + throws NotFoundException { + // do some magic! + return () -> new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK); + } + + {{/operation}} +} +{{/operations}} From 638ee8883048b6348ec23fbaf3035b36c42e6a9d Mon Sep 17 00:00:00 2001 From: Ian Chan Date: Wed, 23 Dec 2015 10:29:47 +1300 Subject: [PATCH 2/4] Removed Jersey2 test from spring-mvc codegen The previous patch to allow sub options to spring-mvc had removed the invalid Jersey2 option from spring-mvc codegen, this patch also fixes the associated test. --- .../codegen/options/SpringMVCServerOptionsProvider.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringMVCServerOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringMVCServerOptionsProvider.java index 13a3600918d0..e52373c3c081 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringMVCServerOptionsProvider.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringMVCServerOptionsProvider.java @@ -1,5 +1,6 @@ package io.swagger.codegen.options; +import io.swagger.codegen.CodegenConstants; import io.swagger.codegen.languages.SpringMVCServerCodegen; import java.util.HashMap; @@ -7,6 +8,7 @@ import java.util.Map; public class SpringMVCServerOptionsProvider extends JavaOptionsProvider { public static final String CONFIG_PACKAGE_VALUE = "configPackage"; + public static final String LIBRARY_VALUE = "j8-async"; @Override public String getLanguage() { @@ -17,6 +19,7 @@ public class SpringMVCServerOptionsProvider extends JavaOptionsProvider { public Map createOptions() { Map options = new HashMap(super.createOptions()); options.put(SpringMVCServerCodegen.CONFIG_PACKAGE, CONFIG_PACKAGE_VALUE); + options.put(CodegenConstants.LIBRARY, LIBRARY_VALUE); return options; } From 916793b820e80849bf91aab54345ec1229b42759 Mon Sep 17 00:00:00 2001 From: Ian Chan Date: Fri, 25 Dec 2015 16:33:04 +1300 Subject: [PATCH 3/4] Added spring-mvc-petstore-j8-aysnc-server.sh executable. Added the executable and config file for spring-mvc's j8-async target. --- bin/all-petstore.sh | 1 + bin/spring-mvc-petstore-j8-async-server.sh | 31 ++++++++++++++++++++++ bin/spring-mvc-petstore-j8-async.json | 3 +++ 3 files changed, 35 insertions(+) create mode 100755 bin/spring-mvc-petstore-j8-async-server.sh create mode 100644 bin/spring-mvc-petstore-j8-async.json diff --git a/bin/all-petstore.sh b/bin/all-petstore.sh index f6156dbcee99..7db8c7ec9161 100755 --- a/bin/all-petstore.sh +++ b/bin/all-petstore.sh @@ -43,6 +43,7 @@ cd $APP_DIR ./bin/silex-petstore-server.sh ./bin/slim-petstore-server.sh ./bin/spring-mvc-petstore-server.sh +./bin/spring-mvc-petstore-j8-async-server.sh ./bin/swift-petstore.sh ./bin/tizen-petstore.sh ./bin/typescript-angular-petstore.sh diff --git a/bin/spring-mvc-petstore-j8-async-server.sh b/bin/spring-mvc-petstore-j8-async-server.sh new file mode 100755 index 000000000000..435c29ac0703 --- /dev/null +++ b/bin/spring-mvc-petstore-j8-async-server.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpringMVC -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l spring-mvc -o samples/server/petstore/spring-mvc -c bin/spring-mvc-petstore-j8-async.json" + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/spring-mvc-petstore-j8-async.json b/bin/spring-mvc-petstore-j8-async.json new file mode 100644 index 000000000000..c19430ec9ab1 --- /dev/null +++ b/bin/spring-mvc-petstore-j8-async.json @@ -0,0 +1,3 @@ +{ + "library": "j8-async" +} From 3103846f451d7fb9fa9ac6fcfa4007ef59f15d32 Mon Sep 17 00:00:00 2001 From: Ian Chan Date: Tue, 29 Dec 2015 13:40:46 +1300 Subject: [PATCH 4/4] Enforce Java 1.8 when generating spring-mvc with j8-async option The spring-mvc j8-async code is now located in it's own sample directory with Java 8 enforced via Maven plug-in. --- bin/spring-mvc-petstore-j8-async-server.sh | 2 +- .../languages/SpringMVCServerCodegen.java | 12 ++ .../JavaSpringMVC/pom-j8-async.mustache | 172 ++++++++++++++++++ 3 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpringMVC/pom-j8-async.mustache diff --git a/bin/spring-mvc-petstore-j8-async-server.sh b/bin/spring-mvc-petstore-j8-async-server.sh index 435c29ac0703..d43b0c432865 100755 --- a/bin/spring-mvc-petstore-j8-async-server.sh +++ b/bin/spring-mvc-petstore-j8-async-server.sh @@ -26,6 +26,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpringMVC -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l spring-mvc -o samples/server/petstore/spring-mvc -c bin/spring-mvc-petstore-j8-async.json" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpringMVC -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l spring-mvc -o samples/server/petstore/spring-mvc-j8-async -c bin/spring-mvc-petstore-j8-async.json" java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java index 23ffe6c0fc4b..b68c9dd98996 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringMVCServerCodegen.java @@ -178,6 +178,18 @@ public class SpringMVCServerCodegen extends JavaClientCodegen implements Codegen apiTemplateFiles.remove(this.templateFileName); this.templateFileName = "api-j8-async.mustache"; apiTemplateFiles.put(this.templateFileName, ".java"); + + int originalPomFileIdx = -1; + for (int i = 0; i < supportingFiles.size(); i++) { + if ("pom.xml".equals(supportingFiles.get(i).destinationFilename)) { + originalPomFileIdx = i; + break; + } + } + if (originalPomFileIdx > -1) { + supportingFiles.remove(originalPomFileIdx); + } + supportingFiles.add(new SupportingFile("pom-j8-async.mustache", "", "pom.xml")); } return objs; diff --git a/modules/swagger-codegen/src/main/resources/JavaSpringMVC/pom-j8-async.mustache b/modules/swagger-codegen/src/main/resources/JavaSpringMVC/pom-j8-async.mustache new file mode 100644 index 000000000000..566a4c83d8de --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpringMVC/pom-j8-async.mustache @@ -0,0 +1,172 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + src/main/java + + + org.apache.maven.plugins + maven-war-plugin + 2.1.1 + + + maven-failsafe-plugin + 2.6 + + + + integration-test + verify + + + + + + org.eclipse.jetty + jetty-maven-plugin + ${jetty-version} + + + {{^contextPath}}/{{/contextPath}}{{#contextPath}}{{contextPath}}{{/contextPath}} + + target/${project.artifactId}-${project.version} + 8079 + stopit + + 8002 + 60000 + + + + + start-jetty + pre-integration-test + + start + + + 0 + true + + + + stop-jetty + post-integration-test + + stop + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.3 + + 1.8 + 1.8 + + + + + + + io.swagger + swagger-jersey-jaxrs + ${swagger-core-version} + + + org.slf4j + slf4j-log4j12 + ${slf4j-version} + + + com.sun.jersey + jersey-core + ${jersey-version} + + + com.sun.jersey + jersey-json + ${jersey-version} + + + com.sun.jersey + jersey-servlet + ${jersey-version} + + + com.sun.jersey.contribs + jersey-multipart + ${jersey-version} + + + com.sun.jersey + jersey-server + ${jersey-version} + + + + + org.springframework + spring-core + ${spring-version} + + + org.springframework + spring-webmvc + ${spring-version} + + + org.springframework + spring-web + ${spring-version} + + + + + io.springfox + springfox-swagger2 + ${springfox-version} + + + io.springfox + springfox-swagger-ui + ${springfox-version} + + + + junit + junit + ${junit-version} + test + + + javax.servlet + servlet-api + ${servlet-api-version} + + + + + jcenter-snapshots + jcenter + http://oss.jfrog.org/artifactory/oss-snapshot-local/ + + + + 1.5.4 + 9.2.9.v20150224 + 1.13 + 1.6.3 + 1.6.1 + 4.8.1 + 2.5 + 2.0.4-SNAPSHOT + 4.0.9.RELEASE + + \ No newline at end of file