From a761682115d0667090c3f0b19d48fac65432ee65 Mon Sep 17 00:00:00 2001 From: cbornet Date: Tue, 5 Jul 2016 11:52:03 +0200 Subject: [PATCH 1/6] add a generator for spring cloud feign --- bin/spring-cloud-feign-petstore.sh | 34 +++ .../io/swagger/codegen/CodegenSecurity.java | 13 ++ .../io/swagger/codegen/DefaultCodegen.java | 17 ++ .../codegen/languages/SpringCodegen.java | 89 ++++++-- .../libraries/spring-cloud/README.mustache | 83 +++++++ .../libraries/spring-cloud/apiClient.mustache | 8 + .../apiKeyRequestInterceptor.mustache | 31 +++ .../spring-cloud/clientConfiguration.mustache | 105 +++++++++ .../libraries/spring-cloud/pom.mustache | 87 +++++++ .../options/SpringOptionsProvider.java | 2 + .../codegen/spring/SpringOptionsTest.java | 2 + .../spring-cloud/.swagger-codegen-ignore | 23 ++ samples/client/petstore/spring-cloud/LICENSE | 201 ++++++++++++++++ .../client/petstore/spring-cloud/README.md | 53 +++++ samples/client/petstore/spring-cloud/pom.xml | 76 +++++++ .../src/main/java/io/swagger/api/PetApi.java | 146 ++++++++++++ .../java/io/swagger/api/PetApiClient.java | 8 + .../main/java/io/swagger/api/StoreApi.java | 68 ++++++ .../java/io/swagger/api/StoreApiClient.java | 8 + .../src/main/java/io/swagger/api/UserApi.java | 107 +++++++++ .../java/io/swagger/api/UserApiClient.java | 8 + .../ApiKeyRequestInterceptor.java | 31 +++ .../configuration/ClientConfiguration.java | 49 ++++ .../main/java/io/swagger/model/Category.java | 93 ++++++++ .../io/swagger/model/ModelApiResponse.java | 113 +++++++++ .../src/main/java/io/swagger/model/Order.java | 196 ++++++++++++++++ .../src/main/java/io/swagger/model/Pet.java | 199 ++++++++++++++++ .../src/main/java/io/swagger/model/Tag.java | 93 ++++++++ .../src/main/java/io/swagger/model/User.java | 214 ++++++++++++++++++ 29 files changed, 2141 insertions(+), 16 deletions(-) create mode 100755 bin/spring-cloud-feign-petstore.sh create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/README.mustache create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache create mode 100644 samples/client/petstore/spring-cloud/.swagger-codegen-ignore create mode 100644 samples/client/petstore/spring-cloud/LICENSE create mode 100644 samples/client/petstore/spring-cloud/README.md create mode 100644 samples/client/petstore/spring-cloud/pom.xml create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApi.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApi.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ApiKeyRequestInterceptor.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Category.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/ModelApiResponse.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Order.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Pet.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Tag.java create mode 100644 samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/User.java diff --git a/bin/spring-cloud-feign-petstore.sh b/bin/spring-cloud-feign-petstore.sh new file mode 100755 index 00000000000..39f5bd03de1 --- /dev/null +++ b/bin/spring-cloud-feign-petstore.sh @@ -0,0 +1,34 @@ +#!/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/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -o samples/client/petstore/spring-cloud --library spring-cloud -DhideGenerationTimestamp=true" + +echo "Removing files and folders under samples/client/petstore/spring-cloud/src/main" +rm -rf samples/client/petstore/spring-cloud/src/main +find samples/client/petstore/spring-cloud -maxdepth 1 -type f ! -name "README.md" -exec rm {} + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenSecurity.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenSecurity.java index 2e33242c370..4e9dd098a4e 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenSecurity.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenSecurity.java @@ -13,6 +13,7 @@ public class CodegenSecurity { // Oauth specific public String flow, authorizationUrl, tokenUrl; public List> scopes; + public Boolean isCode, isPassword, isApplication, isImplicit; @Override public String toString() { @@ -50,6 +51,14 @@ public boolean equals(Object o) { return false; if (tokenUrl != null ? !tokenUrl.equals(that.tokenUrl) : that.tokenUrl != null) return false; + if (isCode != null ? !isCode.equals(that.isCode) : that.isCode != null) + return false; + if (isPassword != null ? !isPassword.equals(that.isPassword) : that.isPassword != null) + return false; + if (isApplication != null ? !isApplication.equals(that.isApplication) : that.isApplication != null) + return false; + if (isImplicit != null ? !isImplicit.equals(that.isImplicit) : that.isImplicit != null) + return false; return scopes != null ? scopes.equals(that.scopes) : that.scopes == null; } @@ -68,6 +77,10 @@ public int hashCode() { result = 31 * result + (flow != null ? flow.hashCode() : 0); result = 31 * result + (authorizationUrl != null ? authorizationUrl.hashCode() : 0); result = 31 * result + (tokenUrl != null ? tokenUrl.hashCode() : 0); + result = 31 * result + (isCode != null ? isCode.hashCode() : 0); + result = 31 * result + (isPassword != null ? isPassword.hashCode() : 0); + result = 31 * result + (isApplication != null ? isApplication.hashCode() : 0); + result = 31 * result + (isImplicit != null ? isImplicit.hashCode() : 0); result = 31 * result + (scopes != null ? scopes.hashCode() : 0); return result; } diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java index d2bb3aed879..1b6a3c015e8 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultCodegen.java @@ -2349,6 +2349,7 @@ public List fromSecurity(Map CodegenSecurity sec = CodegenModelFactory.newInstance(CodegenModelType.SECURITY); sec.name = entry.getKey(); sec.type = schemeDefinition.getType(); + sec.isCode = sec.isPassword = sec.isApplication = sec.isImplicit = false; if (schemeDefinition instanceof ApiKeyAuthDefinition) { final ApiKeyAuthDefinition apiKeyDefinition = (ApiKeyAuthDefinition) schemeDefinition; @@ -2365,6 +2366,22 @@ public List fromSecurity(Map sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false; sec.isOAuth = true; sec.flow = oauth2Definition.getFlow(); + switch(sec.flow) { + case "accessCode": + sec.isCode = true; + break; + case "password": + sec.isPassword = true; + break; + case "application": + sec.isApplication = true; + break; + case "implicit": + sec.isImplicit = true; + break; + default: + throw new RuntimeException("unknown oauth flow: " + sec.flow); + } sec.authorizationUrl = oauth2Definition.getAuthorizationUrl(); sec.tokenUrl = oauth2Definition.getTokenUrl(); if (oauth2Definition.getScopes() != null) { diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringCodegen.java index 9a4ee3256ea..fc777ad97f1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringCodegen.java @@ -11,13 +11,17 @@ public class SpringCodegen extends AbstractJavaCodegen { public static final String DEFAULT_LIBRARY = "spring-boot"; + public static final String TITLE = "title"; public static final String CONFIG_PACKAGE = "configPackage"; public static final String BASE_PACKAGE = "basePackage"; public static final String INTERFACE_ONLY = "interfaceOnly"; public static final String SINGLE_CONTENT_TYPES = "singleContentTypes"; public static final String JAVA_8 = "java8"; public static final String ASYNC = "async"; - protected String title = "Petstore Server"; + public static final String SPRING_MVC_LIBRARY = "spring-mvc"; + public static final String SPRING_CLOUD_LIBRARY = "spring-cloud"; + + protected String title = "swagger-petstore"; protected String configPackage = "io.swagger.configuration"; protected String basePackage = "io.swagger"; protected boolean interfaceOnly = false; @@ -33,12 +37,12 @@ public SpringCodegen() { apiPackage = "io.swagger.api"; modelPackage = "io.swagger.model"; invokerPackage = "io.swagger.api"; - artifactId = "swagger-spring-server"; + artifactId = "swagger-spring"; - additionalProperties.put("title", title); additionalProperties.put(CONFIG_PACKAGE, configPackage); additionalProperties.put(BASE_PACKAGE, basePackage); + cliOptions.add(new CliOption(TITLE, "server title name or client service name")); cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code")); cliOptions.add(new CliOption(BASE_PACKAGE, "base package for generated code")); cliOptions.add(CliOption.newBoolean(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files.")); @@ -47,7 +51,8 @@ public SpringCodegen() { cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers")); supportedLibraries.put(DEFAULT_LIBRARY, "Spring-boot Server application using the SpringFox integration."); - supportedLibraries.put("spring-mvc", "Spring-MVC Server application using the SpringFox integration."); + supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC Server application using the SpringFox integration."); + supportedLibraries.put(SPRING_CLOUD_LIBRARY, "Spring-Cloud-Feign client with Spring-Boot auto-configured settings."); setLibrary(DEFAULT_LIBRARY); CliOption library = new CliOption(CodegenConstants.LIBRARY, "library template (sub-template) to use"); @@ -82,6 +87,10 @@ public void processOpts() { modelDocTemplateFiles.remove("model_doc.mustache"); apiDocTemplateFiles.remove("api_doc.mustache"); + if (additionalProperties.containsKey(TITLE)) { + this.setTitle((String) additionalProperties.get(TITLE)); + } + if (additionalProperties.containsKey(CONFIG_PACKAGE)) { this.setConfigPackage((String) additionalProperties.get(CONFIG_PACKAGE)); } @@ -110,17 +119,6 @@ public void processOpts() { supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); if (!this.interfaceOnly) { - apiTemplateFiles.put("apiController.mustache", "Controller.java"); - supportingFiles.add(new SupportingFile("apiException.mustache", - (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiException.java")); - supportingFiles.add(new SupportingFile("apiOriginFilter.mustache", - (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiOriginFilter.java")); - supportingFiles.add(new SupportingFile("apiResponseMessage.mustache", - (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiResponseMessage.java")); - supportingFiles.add(new SupportingFile("notFoundException.mustache", - (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "NotFoundException.java")); - supportingFiles.add(new SupportingFile("swaggerDocumentationConfig.mustache", - (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "SwaggerDocumentationConfig.java")); if (library.equals(DEFAULT_LIBRARY)) { supportingFiles.add(new SupportingFile("homeController.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "HomeController.java")); @@ -129,7 +127,7 @@ public void processOpts() { supportingFiles.add(new SupportingFile("application.properties", ("src.main.resources").replace(".", java.io.File.separator), "application.properties")); } - if (library.equals("spring-mvc")) { + if (library.equals(SPRING_MVC_LIBRARY)) { supportingFiles.add(new SupportingFile("webApplication.mustache", (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "WebApplication.java")); supportingFiles.add(new SupportingFile("webMvcConfiguration.mustache", @@ -139,6 +137,31 @@ public void processOpts() { supportingFiles.add(new SupportingFile("application.properties", ("src.main.resources").replace(".", java.io.File.separator), "swagger.properties")); } + if (library.equals(SPRING_CLOUD_LIBRARY)) { + supportingFiles.add(new SupportingFile("apiKeyRequestInterceptor.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "ApiKeyRequestInterceptor.java")); + supportingFiles.add(new SupportingFile("clientConfiguration.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "ClientConfiguration.java")); + apiTemplateFiles.put("apiClient.mustache", "Client.java"); + if (!additionalProperties.containsKey(SINGLE_CONTENT_TYPES)) { + additionalProperties.put(SINGLE_CONTENT_TYPES, "true"); + this.setSingleContentTypes(true); + + } + + } else { + apiTemplateFiles.put("apiController.mustache", "Controller.java"); + supportingFiles.add(new SupportingFile("apiException.mustache", + (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiException.java")); + supportingFiles.add(new SupportingFile("apiResponseMessage.mustache", + (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiResponseMessage.java")); + supportingFiles.add(new SupportingFile("notFoundException.mustache", + (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "NotFoundException.java")); + supportingFiles.add(new SupportingFile("apiOriginFilter.mustache", + (sourceFolder + File.separator + apiPackage).replace(".", java.io.File.separator), "ApiOriginFilter.java")); + supportingFiles.add(new SupportingFile("swaggerDocumentationConfig.mustache", + (sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "SwaggerDocumentationConfig.java")); + } } if (this.java8) { @@ -182,6 +205,22 @@ public void preprocessSwagger(Swagger swagger) { swagger.setBasePath(""); } + if(!additionalProperties.containsKey(TITLE)) { + // From the title, compute a reasonable name for the package and the API + String title = swagger.getInfo().getTitle(); + + // Drop any API suffix + if (title != null) { + title = title.trim().replace(" ", "-"); + if (title.toUpperCase().endsWith("API")) { + title = title.substring(0, title.length() - 3); + } + + this.title = camelize(sanitizeName(title), true); + } + additionalProperties.put(TITLE, this.title); + } + String host = swagger.getHost(); String port = "8080"; if (host != null) { @@ -265,6 +304,19 @@ public Map postProcessOperations(Map objs) { return objs; } + @Override + public Map postProcessSupportingFileData(Map objs) { + if(library.equals(SPRING_CLOUD_LIBRARY)) { + List authMethods = (List) objs.get("authMethods"); + if (authMethods != null) { + for (CodegenSecurity authMethod : authMethods) { + authMethod.name = camelize(sanitizeName(authMethod.name), true); + } + } + } + return objs; + } + @Override public String toApiName(String name) { if (name.length() == 0) { @@ -274,6 +326,10 @@ public String toApiName(String name) { return camelize(name) + "Api"; } + public void setTitle(String title) { + this.title = title; + } + public void setConfigPackage(String configPackage) { this.configPackage = configPackage; } @@ -331,4 +387,5 @@ public Map postProcessModelsEnum(Map objs) { return objs; } + } diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/README.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/README.mustache new file mode 100644 index 00000000000..3130b070174 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/README.mustache @@ -0,0 +1,83 @@ +{{^interfaceOnly}} +# {{artifactId}} + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + {{{groupId}}} + {{{artifactId}}} + {{{artifactVersion}}} + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "{{{groupId}}}:{{{artifactId}}}:{{{artifactVersion}}}" +``` + +### Others + +At first generate the JAR by executing: + +mvn package + +Then manually install the following JARs: + +* target/{{{artifactId}}}-{{{artifactVersion}}}.jar +* target/lib/*.jar +{{/interfaceOnly}} +{{#interfaceOnly}} +# Swagger generated API stub + +Spring Framework stub + + +## Overview +This code was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. +By using the [OpenAPI-Spec](https://github.com/swagger-api/swagger-core), you can easily generate an API stub. +This is an example of building API stub interfaces in Java using the Spring framework. + +The stubs generated can be used in your existing Spring-MVC or Spring-Boot application to create controller endpoints +by adding ```@Controller``` classes that implement the interface. Eg: +```java +@Controller +public class PetController implements PetApi { +// implement all PetApi methods +} +``` + +You can also use the interface to create [Spring-Cloud Feign clients](http://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign-inheritance).Eg: +```java +@FeignClient(name="pet", url="http://petstore.swagger.io/v2") +public interface PetClient extends PetApi { + +} +``` +{{/interfaceOnly}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache new file mode 100644 index 00000000000..f14f27d6cca --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache @@ -0,0 +1,8 @@ +package {{package}}; + +import org.springframework.cloud.netflix.feign.FeignClient; +import {{configPackage}}.ClientConfiguration; + +@FeignClient(name="${ {{{title}}}.name:{{{title}}} }", url="${ {{{title}}}.url:{{{basePath}}} }", configuration = ClientConfiguration.class) +public interface {{classname}}Client extends {{classname}} { +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache new file mode 100644 index 00000000000..a7835fc983d --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiKeyRequestInterceptor.mustache @@ -0,0 +1,31 @@ +package {{configPackage}}; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.Util; + + +public class ApiKeyRequestInterceptor implements RequestInterceptor { + private final String location; + private final String name; + private String value; + + public ApiKeyRequestInterceptor(String location, String name, String value) { + Util.checkNotNull(location, "location", new Object[0]); + Util.checkNotNull(name, "name", new Object[0]); + Util.checkNotNull(value, "value", new Object[0]); + this.location = location; + this.name = name; + this.value = value; + } + + @Override + public void apply(RequestTemplate requestTemplate) { + if(location.equals("header")) { + requestTemplate.header(name, value); + } else if(location.equals("query")) { + requestTemplate.query(name, value); + } + } + +} diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache new file mode 100644 index 00000000000..694ec034db5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache @@ -0,0 +1,105 @@ +package {{configPackage}}; + +import feign.Logger; +import feign.auth.BasicAuthRequestInterceptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +@Configuration +@EnableConfigurationProperties +public class ClientConfiguration { + +{{#authMethods}} + {{#isBasic}} + @Value("${ {{{title}}}.security.{{{name}}}.username }") + private String {{{name}}}Username; + + @Value("${ {{{title}}}.security.{{{name}}}.password }") + private String {{{name}}}Password; + + @Bean + @ConditionalOnProperty(name = "{{{title}}}.security.{{{name}}}.username") + public BasicAuthRequestInterceptor {{{name}}}RequestInterceptor() { + return new BasicAuthRequestInterceptor(this.{{{name}}}Username, this.{{{name}}}Password); + } + + {{/isBasic}} + {{#isApiKey}} + @Value("${ {{{title}}}.security.{{{name}}}.key }") + private String {{{name}}}Key; + + @Bean + @ConditionalOnProperty(name = "{{{title}}}.security.{{{name}}}.key") + public ApiKeyRequestInterceptor {{{name}}}RequestInterceptor() { + return new ApiKeyRequestInterceptor({{#isKeyInHeader}}"header"{{/isKeyInHeader}}{{^isKeyInHeader}}"query"{{/isKeyInHeader}}, "{{{keyParamName}}}", this.{{{name}}}Key); + } + + {{/isApiKey}} + {{#isOAuth}} + @Bean + @ConditionalOnProperty("{{{title}}}.security.{{{name}}}.client-id") + public OAuth2FeignRequestInterceptor {{{name}}}RequestInterceptor() { + return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), {{{name}}}ResourceDetails()); + } + + {{#isCode}} + @Bean + @ConditionalOnProperty("{{{title}}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{{title}}}.security.{{{name}}}") + public AuthorizationCodeResourceDetails {{{name}}}ResourceDetails() { + AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails(); + details.setAccessTokenUri("{{{tokenUrl}}}"); + details.setUserAuthorizationUri("{{{authorizationUrl}}}"); + return details; + } + + {{/isCode}} + {{#isPassword}} + @Bean + @ConditionalOnProperty("{{{title}}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{{title}}}.security.{{{name}}}") + public ResourceOwnerPasswordResourceDetails {{{name}}}ResourceDetails() { + ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails(); + details.setAccessTokenUri("{{{tokenUrl}}}"); + return details; + } + + {{/isPassword}} + {{#isApplication}} + @Bean + @ConditionalOnProperty("{{{title}}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{{title}}}.security.{{{name}}}") + public ClientCredentialsResourceDetails {{{name}}}ResourceDetails() { + ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails(); + details.setAccessTokenUri("{{{tokenUrl}}}"); + return details; + } + + {{/isApplication}} + {{#isImplicit}} + @Bean + @ConditionalOnProperty("{{{title}}}.security.{{{name}}}.client-id") + @ConfigurationProperties("{{{title}}}.security.{{{name}}}") + public ImplicitResourceDetails {{{name}}}ResourceDetails() { + ImplicitResourceDetails details = new ImplicitResourceDetails(); + details.setUserAuthorizationUri("{{{authorizationUrl}}}"); + return details; + } + + {{/isImplicit}} + {{/isOAuth}} +{{/authMethods}} +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache new file mode 100644 index 00000000000..022d49b2bc2 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache @@ -0,0 +1,87 @@ + + 4.0.0 + {{groupId}} + {{artifactId}} + jar + {{artifactId}} + {{artifactVersion}} + + {{#java8}}1.8{{/java8}}{{^java8}}1.7{{/java8}} + ${java.version} + ${java.version} + 1.5.9 + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + src/main/java + {{^interfaceOnly}} + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + {{/interfaceOnly}} + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR1 + pom + import + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + org.springframework.cloud + spring-cloud-starter-feign + + + org.springframework.cloud + spring-cloud-security + + + org.springframework.security.oauth + spring-security-oauth2 + + {{#java8}} + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + {{/java8}} + {{^java8}} + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + + joda-time + joda-time + + {{/java8}} + + \ No newline at end of file diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringOptionsProvider.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringOptionsProvider.java index 3d56410f937..3cc8bfee148 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringOptionsProvider.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/options/SpringOptionsProvider.java @@ -7,6 +7,7 @@ import java.util.Map; public class SpringOptionsProvider extends JavaOptionsProvider { + public static final String TITLE = "swagger"; public static final String CONFIG_PACKAGE_VALUE = "configPackage"; public static final String BASE_PACKAGE_VALUE = "basePackage"; public static final String LIBRARY_VALUE = "spring-mvc"; //FIXME hidding value from super class @@ -23,6 +24,7 @@ public String getLanguage() { @Override public Map createOptions() { Map options = new HashMap(super.createOptions()); + options.put(SpringCodegen.TITLE, TITLE); options.put(SpringCodegen.CONFIG_PACKAGE, CONFIG_PACKAGE_VALUE); options.put(SpringCodegen.BASE_PACKAGE, BASE_PACKAGE_VALUE); options.put(CodegenConstants.LIBRARY, LIBRARY_VALUE); diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/spring/SpringOptionsTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/spring/SpringOptionsTest.java index 3693ab6c550..8adaa67679d 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/spring/SpringOptionsTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/spring/SpringOptionsTest.java @@ -50,6 +50,8 @@ protected void setExpectations() { times = 1; clientCodegen.setFullJavaUtil(Boolean.valueOf(SpringOptionsProvider.FULL_JAVA_UTIL_VALUE)); times = 1; + clientCodegen.setTitle(SpringOptionsProvider.TITLE); + times = 1; clientCodegen.setConfigPackage(SpringOptionsProvider.CONFIG_PACKAGE_VALUE); times = 1; clientCodegen.setBasePackage(SpringOptionsProvider.BASE_PACKAGE_VALUE); diff --git a/samples/client/petstore/spring-cloud/.swagger-codegen-ignore b/samples/client/petstore/spring-cloud/.swagger-codegen-ignore new file mode 100644 index 00000000000..c5fa491b4c5 --- /dev/null +++ b/samples/client/petstore/spring-cloud/.swagger-codegen-ignore @@ -0,0 +1,23 @@ +# Swagger Codegen Ignore +# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/spring-cloud/LICENSE b/samples/client/petstore/spring-cloud/LICENSE new file mode 100644 index 00000000000..8dada3edaf5 --- /dev/null +++ b/samples/client/petstore/spring-cloud/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/samples/client/petstore/spring-cloud/README.md b/samples/client/petstore/spring-cloud/README.md new file mode 100644 index 00000000000..56d8781caad --- /dev/null +++ b/samples/client/petstore/spring-cloud/README.md @@ -0,0 +1,53 @@ +# swagger-spring + +## Requirements + +Building the API client library requires [Maven](https://maven.apache.org/) to be installed. + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn deploy +``` + +Refer to the [official documentation](https://maven.apache.org/plugins/maven-deploy-plugin/usage.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + io.swagger + swagger-spring + 1.0.0 + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "io.swagger:swagger-spring:1.0.0" +``` + +### Others + +At first generate the JAR by executing: + +mvn package + +Then manually install the following JARs: + +* target/swagger-spring-1.0.0.jar +* target/lib/*.jar diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml new file mode 100644 index 00000000000..20490f349a0 --- /dev/null +++ b/samples/client/petstore/spring-cloud/pom.xml @@ -0,0 +1,76 @@ + + 4.0.0 + io.swagger + swagger-spring + jar + swagger-spring + 1.0.0 + + 1.7 + ${java.version} + ${java.version} + 1.5.9 + + + org.springframework.boot + spring-boot-starter-parent + 1.3.5.RELEASE + + + src/main/java + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + + + + + + org.springframework.cloud + spring-cloud-starter-parent + Brixton.SR1 + pom + import + + + + + + + io.swagger + swagger-annotations + ${swagger-core-version} + + + org.springframework.cloud + spring-cloud-starter-feign + + + org.springframework.cloud + spring-cloud-security + + + org.springframework.security.oauth + spring-security-oauth2 + + + + com.fasterxml.jackson.datatype + jackson-datatype-joda + + + joda-time + joda-time + + + \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java new file mode 100644 index 00000000000..9dcc45da00d --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java @@ -0,0 +1,146 @@ +package io.swagger.api; + +import io.swagger.model.Pet; +import io.swagger.model.ModelApiResponse; +import java.io.File; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +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; + + +@Api(value = "pet", description = "the pet API") +public interface PetApi { + + @ApiOperation(value = "Add a new pet to the store", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input", response = Void.class) }) + @RequestMapping(value = "/pet", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.POST) + ResponseEntity addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body); + + + @ApiOperation(value = "Deletes a pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid pet value", response = Void.class) }) + @RequestMapping(value = "/pet/{petId}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.DELETE) + ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey); + + + @ApiOperation(value = "Finds Pets by status", notes = "Multiple status values can be provided with comma separated strings", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class), + @ApiResponse(code = 400, message = "Invalid status value", response = Pet.class) }) + @RequestMapping(value = "/pet/findByStatus", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true) @RequestParam(value = "status", required = true) List status); + + + @ApiOperation(value = "Finds Pets by tags", notes = "Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.", response = Pet.class, responseContainer = "List", authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class), + @ApiResponse(code = 400, message = "Invalid tag value", response = Pet.class) }) + @RequestMapping(value = "/pet/findByTags", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List tags); + + + @ApiOperation(value = "Find pet by ID", notes = "Returns a single pet", response = Pet.class, authorizations = { + @Authorization(value = "api_key") + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Pet.class), + @ApiResponse(code = 400, message = "Invalid ID supplied", response = Pet.class), + @ApiResponse(code = 404, message = "Pet not found", response = Pet.class) }) + @RequestMapping(value = "/pet/{petId}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId); + + + @ApiOperation(value = "Update an existing pet", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied", response = Void.class), + @ApiResponse(code = 404, message = "Pet not found", response = Void.class), + @ApiResponse(code = 405, message = "Validation exception", response = Void.class) }) + @RequestMapping(value = "/pet", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.PUT) + ResponseEntity updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body); + + + @ApiOperation(value = "Updates a pet in the store with form data", notes = "", response = Void.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 405, message = "Invalid input", response = Void.class) }) + @RequestMapping(value = "/pet/{petId}", + produces = "application/json", + consumes = "application/x-www-form-urlencoded", + method = RequestMethod.POST) + ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet" ) @RequestPart(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet" ) @RequestPart(value="status", required=false) String status); + + + @ApiOperation(value = "uploads an image", notes = "", response = ModelApiResponse.class, authorizations = { + @Authorization(value = "petstore_auth", scopes = { + @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), + @AuthorizationScope(scope = "read:pets", description = "read your pets") + }) + }, tags={ "pet", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = ModelApiResponse.class) }) + @RequestMapping(value = "/pet/{petId}/uploadImage", + produces = "application/json", + consumes = "multipart/form-data", + method = RequestMethod.POST) + ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server" ) @RequestPart(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file); + +} diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java new file mode 100644 index 00000000000..01bf75e9151 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java @@ -0,0 +1,8 @@ +package io.swagger.api; + +import org.springframework.cloud.netflix.feign.FeignClient; +import io.swagger.configuration.ClientConfiguration; + +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +public interface PetApiClient extends PetApi { +} \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApi.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApi.java new file mode 100644 index 00000000000..1eb724e96c9 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApi.java @@ -0,0 +1,68 @@ +package io.swagger.api; + +import java.util.Map; +import io.swagger.model.Order; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +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; + + +@Api(value = "store", description = "the store API") +public interface StoreApi { + + @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid ID supplied", response = Void.class), + @ApiResponse(code = 404, message = "Order not found", response = Void.class) }) + @RequestMapping(value = "/store/order/{orderId}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.DELETE) + ResponseEntity deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId); + + + @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Integer.class, responseContainer = "Map", authorizations = { + @Authorization(value = "api_key") + }, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Integer.class) }) + @RequestMapping(value = "/store/inventory", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity> getInventory(); + + + @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid ID supplied", response = Order.class), + @ApiResponse(code = 404, message = "Order not found", response = Order.class) }) + @RequestMapping(value = "/store/order/{orderId}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId); + + + @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class, tags={ "store", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Order.class), + @ApiResponse(code = 400, message = "Invalid Order", response = Order.class) }) + @RequestMapping(value = "/store/order", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.POST) + ResponseEntity placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body); + +} diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java new file mode 100644 index 00000000000..399a16d0b5a --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java @@ -0,0 +1,8 @@ +package io.swagger.api; + +import org.springframework.cloud.netflix.feign.FeignClient; +import io.swagger.configuration.ClientConfiguration; + +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +public interface StoreApiClient extends StoreApi { +} \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApi.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApi.java new file mode 100644 index 00000000000..cf96ef50a4a --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApi.java @@ -0,0 +1,107 @@ +package io.swagger.api; + +import io.swagger.model.User; +import java.util.List; + +import io.swagger.annotations.*; +import org.springframework.http.ResponseEntity; +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; + + +@Api(value = "user", description = "the user API") +public interface UserApi { + + @ApiOperation(value = "Create user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) + @RequestMapping(value = "/user", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.POST) + ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body); + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) + @RequestMapping(value = "/user/createWithArray", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.POST) + ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body); + + + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) + @RequestMapping(value = "/user/createWithList", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.POST) + ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body); + + + @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid username supplied", response = Void.class), + @ApiResponse(code = 404, message = "User not found", response = Void.class) }) + @RequestMapping(value = "/user/{username}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.DELETE) + ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username); + + + @ApiOperation(value = "Get user by user name", notes = "", response = User.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = User.class), + @ApiResponse(code = 400, message = "Invalid username supplied", response = User.class), + @ApiResponse(code = 404, message = "User not found", response = User.class) }) + @RequestMapping(value = "/user/{username}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username); + + + @ApiOperation(value = "Logs user into the system", notes = "", response = String.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = String.class), + @ApiResponse(code = 400, message = "Invalid username/password supplied", response = String.class) }) + @RequestMapping(value = "/user/login", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username,@ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password); + + + @ApiOperation(value = "Logs out current logged in user session", notes = "", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) + @RequestMapping(value = "/user/logout", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.GET) + ResponseEntity logoutUser(); + + + @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) + @ApiResponses(value = { + @ApiResponse(code = 400, message = "Invalid user supplied", response = Void.class), + @ApiResponse(code = 404, message = "User not found", response = Void.class) }) + @RequestMapping(value = "/user/{username}", + produces = "application/json", + consumes = "application/json", + method = RequestMethod.PUT) + ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username,@ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body); + +} diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java new file mode 100644 index 00000000000..38ce88e96d7 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java @@ -0,0 +1,8 @@ +package io.swagger.api; + +import org.springframework.cloud.netflix.feign.FeignClient; +import io.swagger.configuration.ClientConfiguration; + +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +public interface UserApiClient extends UserApi { +} \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ApiKeyRequestInterceptor.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ApiKeyRequestInterceptor.java new file mode 100644 index 00000000000..b83fd9c6bac --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ApiKeyRequestInterceptor.java @@ -0,0 +1,31 @@ +package io.swagger.configuration; + +import feign.RequestInterceptor; +import feign.RequestTemplate; +import feign.Util; + + +public class ApiKeyRequestInterceptor implements RequestInterceptor { + private final String location; + private final String name; + private String value; + + public ApiKeyRequestInterceptor(String location, String name, String value) { + Util.checkNotNull(location, "location", new Object[0]); + Util.checkNotNull(name, "name", new Object[0]); + Util.checkNotNull(value, "value", new Object[0]); + this.location = location; + this.name = name; + this.value = value; + } + + @Override + public void apply(RequestTemplate requestTemplate) { + if(location.equals("header")) { + requestTemplate.header(name, value); + } else if(location.equals("query")) { + requestTemplate.query(name, value); + } + } + +} diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java new file mode 100644 index 00000000000..a0e14b2bd38 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java @@ -0,0 +1,49 @@ +package io.swagger.configuration; + +import feign.Logger; +import feign.auth.BasicAuthRequestInterceptor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.cloud.security.oauth2.client.feign.OAuth2FeignRequestInterceptor; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; +import org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeResourceDetails; +import org.springframework.security.oauth2.client.token.grant.implicit.ImplicitResourceDetails; +import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails; +import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; +import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; + +@Configuration +@EnableConfigurationProperties +public class ClientConfiguration { + + @Bean + @ConditionalOnProperty("swaggerPetstore.security.petstoreAuth.client-id") + public OAuth2FeignRequestInterceptor petstoreAuthRequestInterceptor() { + return new OAuth2FeignRequestInterceptor(new DefaultOAuth2ClientContext(), petstoreAuthResourceDetails()); + } + + @Bean + @ConditionalOnProperty("swaggerPetstore.security.petstoreAuth.client-id") + @ConfigurationProperties("swaggerPetstore.security.petstoreAuth") + public ImplicitResourceDetails petstoreAuthResourceDetails() { + ImplicitResourceDetails details = new ImplicitResourceDetails(); + details.setUserAuthorizationUri("http://petstore.swagger.io/api/oauth/dialog"); + return details; + } + + @Value("${ swaggerPetstore.security.apiKey.key }") + private String apiKeyKey; + + @Bean + @ConditionalOnProperty(name = "swaggerPetstore.security.apiKey.key") + public ApiKeyRequestInterceptor apiKeyRequestInterceptor() { + return new ApiKeyRequestInterceptor("header", "api_key", this.apiKeyKey); + } + +} \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Category.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Category.java new file mode 100644 index 00000000000..67bc75b3b10 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Category.java @@ -0,0 +1,93 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + + +public class Category { + + private Long id = null; + private String name = null; + + /** + **/ + public Category id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Category name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Category category = (Category) o; + return Objects.equals(id, category.id) && + Objects.equals(name, category.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Category {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/ModelApiResponse.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/ModelApiResponse.java new file mode 100644 index 00000000000..5e3aa82bbee --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/ModelApiResponse.java @@ -0,0 +1,113 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + + +public class ModelApiResponse { + + private Integer code = null; + private String type = null; + private String message = null; + + /** + **/ + public ModelApiResponse code(Integer code) { + this.code = code; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("code") + public Integer getCode() { + return code; + } + public void setCode(Integer code) { + this.code = code; + } + + /** + **/ + public ModelApiResponse type(String type) { + this.type = type; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("type") + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + + /** + **/ + public ModelApiResponse message(String message) { + this.message = message; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("message") + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ModelApiResponse _apiResponse = (ModelApiResponse) o; + return Objects.equals(code, _apiResponse.code) && + Objects.equals(type, _apiResponse.type) && + Objects.equals(message, _apiResponse.message); + } + + @Override + public int hashCode() { + return Objects.hash(code, type, message); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ModelApiResponse {\n"); + + sb.append(" code: ").append(toIndentedString(code)).append("\n"); + sb.append(" type: ").append(toIndentedString(type)).append("\n"); + sb.append(" message: ").append(toIndentedString(message)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Order.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Order.java new file mode 100644 index 00000000000..55859fc4089 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Order.java @@ -0,0 +1,196 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.joda.time.DateTime; + + + + + + +public class Order { + + private Long id = null; + private Long petId = null; + private Integer quantity = null; + private DateTime shipDate = null; + + + public enum StatusEnum { + PLACED("placed"), + APPROVED("approved"), + DELIVERED("delivered"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } + + private StatusEnum status = null; + private Boolean complete = false; + + /** + **/ + public Order id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Order petId(Long petId) { + this.petId = petId; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("petId") + public Long getPetId() { + return petId; + } + public void setPetId(Long petId) { + this.petId = petId; + } + + /** + **/ + public Order quantity(Integer quantity) { + this.quantity = quantity; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("quantity") + public Integer getQuantity() { + return quantity; + } + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + /** + **/ + public Order shipDate(DateTime shipDate) { + this.shipDate = shipDate; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("shipDate") + public DateTime getShipDate() { + return shipDate; + } + public void setShipDate(DateTime shipDate) { + this.shipDate = shipDate; + } + + /** + * Order Status + **/ + public Order status(StatusEnum status) { + this.status = status; + return this; + } + + + @ApiModelProperty(value = "Order Status") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + /** + **/ + public Order complete(Boolean complete) { + this.complete = complete; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("complete") + public Boolean getComplete() { + return complete; + } + public void setComplete(Boolean complete) { + this.complete = complete; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Order order = (Order) o; + return Objects.equals(id, order.id) && + Objects.equals(petId, order.petId) && + Objects.equals(quantity, order.quantity) && + Objects.equals(shipDate, order.shipDate) && + Objects.equals(status, order.status) && + Objects.equals(complete, order.complete); + } + + @Override + public int hashCode() { + return Objects.hash(id, petId, quantity, shipDate, status, complete); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Order {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" petId: ").append(toIndentedString(petId)).append("\n"); + sb.append(" quantity: ").append(toIndentedString(quantity)).append("\n"); + sb.append(" shipDate: ").append(toIndentedString(shipDate)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append(" complete: ").append(toIndentedString(complete)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Pet.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Pet.java new file mode 100644 index 00000000000..24092cbee25 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Pet.java @@ -0,0 +1,199 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonValue; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.model.Category; +import io.swagger.model.Tag; +import java.util.ArrayList; +import java.util.List; + + + + + + +public class Pet { + + private Long id = null; + private Category category = null; + private String name = null; + private List photoUrls = new ArrayList(); + private List tags = new ArrayList(); + + + public enum StatusEnum { + AVAILABLE("available"), + PENDING("pending"), + SOLD("sold"); + + private String value; + + StatusEnum(String value) { + this.value = value; + } + + @Override + @JsonValue + public String toString() { + return value; + } + } + + private StatusEnum status = null; + + /** + **/ + public Pet id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Pet category(Category category) { + this.category = category; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("category") + public Category getCategory() { + return category; + } + public void setCategory(Category category) { + this.category = category; + } + + /** + **/ + public Pet name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(example = "doggie", required = true, value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + /** + **/ + public Pet photoUrls(List photoUrls) { + this.photoUrls = photoUrls; + return this; + } + + + @ApiModelProperty(required = true, value = "") + @JsonProperty("photoUrls") + public List getPhotoUrls() { + return photoUrls; + } + public void setPhotoUrls(List photoUrls) { + this.photoUrls = photoUrls; + } + + /** + **/ + public Pet tags(List tags) { + this.tags = tags; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("tags") + public List getTags() { + return tags; + } + public void setTags(List tags) { + this.tags = tags; + } + + /** + * pet status in the store + **/ + public Pet status(StatusEnum status) { + this.status = status; + return this; + } + + + @ApiModelProperty(value = "pet status in the store") + @JsonProperty("status") + public StatusEnum getStatus() { + return status; + } + public void setStatus(StatusEnum status) { + this.status = status; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Pet pet = (Pet) o; + return Objects.equals(id, pet.id) && + Objects.equals(category, pet.category) && + Objects.equals(name, pet.name) && + Objects.equals(photoUrls, pet.photoUrls) && + Objects.equals(tags, pet.tags) && + Objects.equals(status, pet.status); + } + + @Override + public int hashCode() { + return Objects.hash(id, category, name, photoUrls, tags, status); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Pet {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" category: ").append(toIndentedString(category)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append(" photoUrls: ").append(toIndentedString(photoUrls)).append("\n"); + sb.append(" tags: ").append(toIndentedString(tags)).append("\n"); + sb.append(" status: ").append(toIndentedString(status)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Tag.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Tag.java new file mode 100644 index 00000000000..f26d84e74b2 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/Tag.java @@ -0,0 +1,93 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + + +public class Tag { + + private Long id = null; + private String name = null; + + /** + **/ + public Tag id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public Tag name(String name) { + this.name = name; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("name") + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Tag tag = (Tag) o; + return Objects.equals(id, tag.id) && + Objects.equals(name, tag.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class Tag {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" name: ").append(toIndentedString(name)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/User.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/User.java new file mode 100644 index 00000000000..5dc291a7889 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/model/User.java @@ -0,0 +1,214 @@ +package io.swagger.model; + +import java.util.Objects; +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + + + + + + +public class User { + + private Long id = null; + private String username = null; + private String firstName = null; + private String lastName = null; + private String email = null; + private String password = null; + private String phone = null; + private Integer userStatus = null; + + /** + **/ + public User id(Long id) { + this.id = id; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("id") + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + + /** + **/ + public User username(String username) { + this.username = username; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("username") + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + /** + **/ + public User firstName(String firstName) { + this.firstName = firstName; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("firstName") + public String getFirstName() { + return firstName; + } + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + /** + **/ + public User lastName(String lastName) { + this.lastName = lastName; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("lastName") + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + /** + **/ + public User email(String email) { + this.email = email; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("email") + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + /** + **/ + public User password(String password) { + this.password = password; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("password") + public String getPassword() { + return password; + } + public void setPassword(String password) { + this.password = password; + } + + /** + **/ + public User phone(String phone) { + this.phone = phone; + return this; + } + + + @ApiModelProperty(value = "") + @JsonProperty("phone") + public String getPhone() { + return phone; + } + public void setPhone(String phone) { + this.phone = phone; + } + + /** + * User Status + **/ + public User userStatus(Integer userStatus) { + this.userStatus = userStatus; + return this; + } + + + @ApiModelProperty(value = "User Status") + @JsonProperty("userStatus") + public Integer getUserStatus() { + return userStatus; + } + public void setUserStatus(Integer userStatus) { + this.userStatus = userStatus; + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + User user = (User) o; + return Objects.equals(id, user.id) && + Objects.equals(username, user.username) && + Objects.equals(firstName, user.firstName) && + Objects.equals(lastName, user.lastName) && + Objects.equals(email, user.email) && + Objects.equals(password, user.password) && + Objects.equals(phone, user.phone) && + Objects.equals(userStatus, user.userStatus); + } + + @Override + public int hashCode() { + return Objects.hash(id, username, firstName, lastName, email, password, phone, userStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class User {\n"); + + sb.append(" id: ").append(toIndentedString(id)).append("\n"); + sb.append(" username: ").append(toIndentedString(username)).append("\n"); + sb.append(" firstName: ").append(toIndentedString(firstName)).append("\n"); + sb.append(" lastName: ").append(toIndentedString(lastName)).append("\n"); + sb.append(" email: ").append(toIndentedString(email)).append("\n"); + sb.append(" password: ").append(toIndentedString(password)).append("\n"); + sb.append(" phone: ").append(toIndentedString(phone)).append("\n"); + sb.append(" userStatus: ").append(toIndentedString(userStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } +} + From 412022b852670b363dab6094aadb06ea660b690b Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 6 Jul 2016 10:28:34 +0200 Subject: [PATCH 2/6] add petstore samples and fix some issues --- bin/spring-cloud-feign-petstore.sh | 2 +- .../libraries/spring-cloud/apiClient.mustache | 2 +- .../spring-cloud/clientConfiguration.mustache | 6 +- .../spring-cloud/formParams.mustache | 1 + .../libraries/spring-cloud/pom.mustache | 9 +- samples/client/petstore/spring-cloud/pom.xml | 9 +- .../src/main/java/io/swagger/api/PetApi.java | 4 +- .../java/io/swagger/api/PetApiClient.java | 2 +- .../java/io/swagger/api/StoreApiClient.java | 2 +- .../java/io/swagger/api/UserApiClient.java | 2 +- .../configuration/ClientConfiguration.java | 2 +- .../src/test/java/io/swagger/TestUtils.java | 17 ++ .../test/java/io/swagger/api/PetApiTest.java | 205 ++++++++++++++++++ .../java/io/swagger/api/StoreApiTest.java | 89 ++++++++ .../test/java/io/swagger/api/UserApiTest.java | 97 +++++++++ .../src/test/resources/application.yml | 10 + 16 files changed, 444 insertions(+), 15 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/formParams.mustache create mode 100644 samples/client/petstore/spring-cloud/src/test/java/io/swagger/TestUtils.java create mode 100644 samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/PetApiTest.java create mode 100644 samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/StoreApiTest.java create mode 100644 samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/UserApiTest.java create mode 100644 samples/client/petstore/spring-cloud/src/test/resources/application.yml diff --git a/bin/spring-cloud-feign-petstore.sh b/bin/spring-cloud-feign-petstore.sh index 39f5bd03de1..e2cafebda84 100755 --- a/bin/spring-cloud-feign-petstore.sh +++ b/bin/spring-cloud-feign-petstore.sh @@ -26,7 +26,7 @@ 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/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -o samples/client/petstore/spring-cloud --library spring-cloud -DhideGenerationTimestamp=true" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -o samples/client/petstore/spring-cloud --library spring-cloud -DhideGenerationTimestamp=true" echo "Removing files and folders under samples/client/petstore/spring-cloud/src/main" rm -rf samples/client/petstore/spring-cloud/src/main diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache index f14f27d6cca..57d227f6bbb 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/apiClient.mustache @@ -3,6 +3,6 @@ package {{package}}; import org.springframework.cloud.netflix.feign.FeignClient; import {{configPackage}}.ClientConfiguration; -@FeignClient(name="${ {{{title}}}.name:{{{title}}} }", url="${ {{{title}}}.url:{{{basePath}}} }", configuration = ClientConfiguration.class) +@FeignClient(name="${ {{{title}}}.name:{{{title}}}}", url="${ {{{title}}}.url:{{{basePath}}}}", configuration = ClientConfiguration.class) public interface {{classname}}Client extends {{classname}} { } \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache index 694ec034db5..2437b30237e 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/clientConfiguration.mustache @@ -24,10 +24,10 @@ public class ClientConfiguration { {{#authMethods}} {{#isBasic}} - @Value("${ {{{title}}}.security.{{{name}}}.username }") + @Value("${ {{{title}}}.security.{{{name}}}.username:}") private String {{{name}}}Username; - @Value("${ {{{title}}}.security.{{{name}}}.password }") + @Value("${ {{{title}}}.security.{{{name}}}.password:}") private String {{{name}}}Password; @Bean @@ -38,7 +38,7 @@ public class ClientConfiguration { {{/isBasic}} {{#isApiKey}} - @Value("${ {{{title}}}.security.{{{name}}}.key }") + @Value("${ {{{title}}}.security.{{{name}}}.key:}") private String {{{name}}}Key; @Bean diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/formParams.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/formParams.mustache new file mode 100644 index 00000000000..e7547a3ba19 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/formParams.mustache @@ -0,0 +1 @@ +{{#isFormParam}}{{#notFile}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}} {{#allowableValues}}, allowableValues="{{{allowableValues}}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}) @RequestParam(value="{{paramName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{{dataType}}} {{paramName}}{{/notFile}}{{#isFile}}@ApiParam(value = "file detail") @RequestParam("file") MultipartFile {{baseName}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache index 022d49b2bc2..bec76800557 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.5.RELEASE + 1.3.6.RELEASE src/main/java @@ -40,7 +40,7 @@ org.springframework.cloud spring-cloud-starter-parent - Brixton.SR1 + Brixton.SR2 pom import @@ -83,5 +83,10 @@ joda-time {{/java8}} + + org.springframework.boot + spring-boot-starter-test + test + \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml index 20490f349a0..52e3be061db 100644 --- a/samples/client/petstore/spring-cloud/pom.xml +++ b/samples/client/petstore/spring-cloud/pom.xml @@ -14,7 +14,7 @@ org.springframework.boot spring-boot-starter-parent - 1.3.5.RELEASE + 1.3.6.RELEASE src/main/java @@ -38,7 +38,7 @@ org.springframework.cloud spring-cloud-starter-parent - Brixton.SR1 + Brixton.SR2 pom import @@ -72,5 +72,10 @@ joda-time joda-time + + org.springframework.boot + spring-boot-starter-test + test + \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java index 9dcc45da00d..81fea00fe73 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApi.java @@ -126,7 +126,7 @@ public interface PetApi { produces = "application/json", consumes = "application/x-www-form-urlencoded", method = RequestMethod.POST) - ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet" ) @RequestPart(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet" ) @RequestPart(value="status", required=false) String status); + ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet" ) @RequestParam(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet" ) @RequestParam(value="status", required=false) String status); @ApiOperation(value = "uploads an image", notes = "", response = ModelApiResponse.class, authorizations = { @@ -141,6 +141,6 @@ public interface PetApi { produces = "application/json", consumes = "multipart/form-data", method = RequestMethod.POST) - ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server" ) @RequestPart(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file); + ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server" ) @RequestParam(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestParam("file") MultipartFile file); } diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java index 01bf75e9151..4b65141b5c1 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/PetApiClient.java @@ -3,6 +3,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; import io.swagger.configuration.ClientConfiguration; -@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore}", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2}", configuration = ClientConfiguration.class) public interface PetApiClient extends PetApi { } \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java index 399a16d0b5a..2f43ae1839f 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApiClient.java @@ -3,6 +3,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; import io.swagger.configuration.ClientConfiguration; -@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore}", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2}", configuration = ClientConfiguration.class) public interface StoreApiClient extends StoreApi { } \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java index 38ce88e96d7..45c00ef8adc 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/UserApiClient.java @@ -3,6 +3,6 @@ import org.springframework.cloud.netflix.feign.FeignClient; import io.swagger.configuration.ClientConfiguration; -@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore }", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2 }", configuration = ClientConfiguration.class) +@FeignClient(name="${ swaggerPetstore.name:swaggerPetstore}", url="${ swaggerPetstore.url:http://petstore.swagger.io/v2}", configuration = ClientConfiguration.class) public interface UserApiClient extends UserApi { } \ No newline at end of file diff --git a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java index a0e14b2bd38..b0816e2d6e9 100644 --- a/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java +++ b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/configuration/ClientConfiguration.java @@ -37,7 +37,7 @@ public ImplicitResourceDetails petstoreAuthResourceDetails() { return details; } - @Value("${ swaggerPetstore.security.apiKey.key }") + @Value("${ swaggerPetstore.security.apiKey.key:}") private String apiKeyKey; @Bean diff --git a/samples/client/petstore/spring-cloud/src/test/java/io/swagger/TestUtils.java b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/TestUtils.java new file mode 100644 index 00000000000..bf5a476ab29 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/TestUtils.java @@ -0,0 +1,17 @@ +package io.swagger; + +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + +public class TestUtils { + private static final AtomicLong atomicId = createAtomicId(); + + public static long nextId() { + return atomicId.getAndIncrement(); + } + + private static AtomicLong createAtomicId() { + int baseId = new Random(System.currentTimeMillis()).nextInt(1000000) + 20000; + return new AtomicLong((long) baseId); + } +} diff --git a/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/PetApiTest.java b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/PetApiTest.java new file mode 100644 index 00000000000..2bb84d5bdae --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/PetApiTest.java @@ -0,0 +1,205 @@ +package io.swagger.api; + +import feign.FeignException; +import io.swagger.TestUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.swagger.model.Category; +import io.swagger.model.Pet; +import io.swagger.model.Tag; +import org.junit.*; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = PetApiTest.Application.class) +public class PetApiTest { + + @Autowired + private PetApiClient client; + + @Test + public void testCreateAndGetPet() { + Pet pet = createRandomPet(); + client.addPet(pet); + ResponseEntity rp = client.getPetById(pet.getId()); + Pet fetched = rp.getBody(); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testUpdatePet() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + + client.updatePet(pet); + + Pet fetched = client.getPetById(pet.getId()).getBody(); + assertNotNull(fetched); + assertEquals(pet.getId(), fetched.getId()); + assertNotNull(fetched.getCategory()); + assertEquals(fetched.getCategory().getName(), pet.getCategory().getName()); + } + + @Test + public void testFindPetsByStatus() throws Exception { + Pet pet = createRandomPet(); + pet.setName("programmer"); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + + client.updatePet(pet); + + List pets = client.findPetsByStatus(Arrays.asList(new String[]{"available"})).getBody(); + assertNotNull(pets); + + boolean found = false; + for (Pet fetched : pets) { + if (fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + + assertTrue(found); + } + + @Test + public void testFindPetsByTags() throws Exception { + Pet pet = createRandomPet(); + pet.setName("monster"); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + + List tags = new ArrayList(); + Tag tag1 = new Tag(); + tag1.setName("friendly"); + tags.add(tag1); + pet.setTags(tags); + + client.updatePet(pet); + + List pets = client.findPetsByTags(Arrays.asList(new String[]{"friendly"})).getBody(); + assertNotNull(pets); + + boolean found = false; + for (Pet fetched : pets) { + if (fetched.getId().equals(pet.getId())) { + found = true; + break; + } + } + assertTrue(found); + } + + @Test + public void testUpdatePetWithForm() throws Exception { + Pet pet = createRandomPet(); + pet.setName("frank"); + client.addPet(pet); + + Pet fetched = client.getPetById(pet.getId()).getBody(); + + client.updatePetWithForm(fetched.getId(), "furt", null); + Pet updated = client.getPetById(fetched.getId()).getBody(); + + assertEquals(updated.getName(), "furt"); + } + + @Test + public void testDeletePet() throws Exception { + Pet pet = createRandomPet(); + client.addPet(pet); + + Pet fetched = client.getPetById(pet.getId()).getBody(); + client.deletePet(fetched.getId(), null); + + try { + client.getPetById(fetched.getId()); + fail("expected an error"); + } catch (FeignException e) { + assertTrue(e.getMessage().startsWith("status 404 ")); + } + } + + @Ignore("Multipart form is not supported by spring-cloud yet.") + @Test + public void testUploadFile() throws Exception { + Pet pet = createRandomPet(); + client.addPet(pet); + + MockMultipartFile filePart = new MockMultipartFile("file", "bar".getBytes()); + client.uploadFile(pet.getId(), "a test file", filePart); + } + + @Test + public void testEqualsAndHashCode() { + Pet pet1 = new Pet(); + Pet pet2 = new Pet(); + assertTrue(pet1.equals(pet2)); + assertTrue(pet2.equals(pet1)); + assertTrue(pet1.hashCode() == pet2.hashCode()); + assertTrue(pet1.equals(pet1)); + assertTrue(pet1.hashCode() == pet1.hashCode()); + + pet2.setName("really-happy"); + pet2.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + assertFalse(pet1.equals(pet2)); + assertFalse(pet2.equals(pet1)); + assertFalse(pet1.hashCode() == (pet2.hashCode())); + assertTrue(pet2.equals(pet2)); + assertTrue(pet2.hashCode() == pet2.hashCode()); + + pet1.setName("really-happy"); + pet1.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); + assertTrue(pet1.equals(pet2)); + assertTrue(pet2.equals(pet1)); + assertTrue(pet1.hashCode() == pet2.hashCode()); + assertTrue(pet1.equals(pet1)); + assertTrue(pet1.hashCode() == pet1.hashCode()); + } + + private Pet createRandomPet() { + Pet pet = new Pet(); + pet.setId(TestUtils.nextId()); + pet.setName("gorilla"); + + Category category = new Category(); + category.setName("really-happy"); + + pet.setCategory(category); + pet.setStatus(Pet.StatusEnum.AVAILABLE); + List photos = Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"}); + pet.setPhotoUrls(photos); + + return pet; + } + + + @SpringBootApplication + @EnableFeignClients + protected static class Application { + public static void main(String[] args) { + new SpringApplicationBuilder(Application.class).run(args); + } + } + + + + + + +} diff --git a/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/StoreApiTest.java b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/StoreApiTest.java new file mode 100644 index 00000000000..223289baf15 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/StoreApiTest.java @@ -0,0 +1,89 @@ +package io.swagger.api; + +import feign.FeignException; +import io.swagger.TestUtils; +import io.swagger.model.Order; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.lang.reflect.Field; +import java.util.Map; + +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = StoreApiTest.Application.class) +public class StoreApiTest { + + @Autowired + private StoreApiClient client; + + @Test + public void testGetInventory() { + Map inventory = client.getInventory().getBody(); + assertTrue(inventory.keySet().size() > 0); + } + + @Test + public void testPlaceOrder() { + Order order = createOrder(); + client.placeOrder(order); + + Order fetched = client.getOrderById(order.getId()).getBody(); + assertEquals(order.getId(), fetched.getId()); + assertEquals(order.getPetId(), fetched.getPetId()); + assertEquals(order.getQuantity(), fetched.getQuantity()); + assertEquals(order.getShipDate().toInstant(), fetched.getShipDate().toInstant()); + } + + @Test + public void testDeleteOrder() { + Order order = createOrder(); + client.placeOrder(order); + + Order fetched = client.getOrderById(order.getId()).getBody(); + assertEquals(fetched.getId(), order.getId()); + + client.deleteOrder(String.valueOf(order.getId())); + + try { + client.getOrderById(order.getId()); + fail("expected an error"); + } catch (FeignException e) { + assertTrue(e.getMessage().startsWith("status 404 ")); + } + } + + private Order createOrder() { + Order order = new Order(); + order.setPetId(new Long(200)); + order.setQuantity(new Integer(13)); + order.setShipDate(org.joda.time.DateTime.now()); + order.setStatus(Order.StatusEnum.PLACED); + order.setComplete(true); + + try { + Field idField = Order.class.getDeclaredField("id"); + idField.setAccessible(true); + idField.set(order, TestUtils.nextId()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return order; + } + + @SpringBootApplication + @EnableFeignClients + protected static class Application { + public static void main(String[] args) { + new SpringApplicationBuilder(StoreApiTest.Application.class).run(args); + } + } +} diff --git a/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/UserApiTest.java b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/UserApiTest.java new file mode 100644 index 00000000000..4fb9b5e1a12 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/test/java/io/swagger/api/UserApiTest.java @@ -0,0 +1,97 @@ +package io.swagger.api; + +import io.swagger.TestUtils; +import io.swagger.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.cloud.netflix.feign.EnableFeignClients; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.util.Arrays; + +import static org.junit.Assert.*; + +@RunWith(SpringJUnit4ClassRunner.class) +@SpringApplicationConfiguration(classes = UserApiTest.Application.class) + +public class UserApiTest { + + @Autowired + private UserApiClient client; + + @Test + public void testCreateUser() { + User user = createUser(); + + client.createUser(user); + + User fetched = client.getUserByName(user.getUsername()).getBody(); + assertEquals(user.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithArray() { + User user1 = createUser(); + user1.setUsername("user" + user1.getId()); + User user2 = createUser(); + user2.setUsername("user" + user2.getId()); + + client.createUsersWithArrayInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = client.getUserByName(user1.getUsername()).getBody(); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testCreateUsersWithList() { + User user1 = createUser(); + user1.setUsername("user" + user1.getId()); + User user2 = createUser(); + user2.setUsername("user" + user2.getId()); + + client.createUsersWithListInput(Arrays.asList(new User[]{user1, user2})); + + User fetched = client.getUserByName(user1.getUsername()).getBody(); + assertEquals(user1.getId(), fetched.getId()); + } + + @Test + public void testLoginUser() { + User user = createUser(); + client.createUser(user); + + String token = client.loginUser(user.getUsername(), user.getPassword()).getBody(); + assertTrue(token.startsWith("logged in user session:")); + } + + @Test + public void logoutUser() { + client.logoutUser(); + } + + private User createUser() { + User user = new User(); + user.setId(TestUtils.nextId()); + user.setUsername("fred"); + user.setFirstName("Fred"); + user.setLastName("Meyer"); + user.setEmail("fred@fredmeyer.com"); + user.setPassword("xxXXxx"); + user.setPhone("408-867-5309"); + user.setUserStatus(123); + + return user; + } + + @SpringBootApplication + @EnableFeignClients + protected static class Application { + public static void main(String[] args) { + new SpringApplicationBuilder(UserApiTest.Application.class).run(args); + } + } +} diff --git a/samples/client/petstore/spring-cloud/src/test/resources/application.yml b/samples/client/petstore/spring-cloud/src/test/resources/application.yml new file mode 100644 index 00000000000..07a52419295 --- /dev/null +++ b/samples/client/petstore/spring-cloud/src/test/resources/application.yml @@ -0,0 +1,10 @@ +spring: + application: + name: petstore-test + +feign.hystrix.enabled: false + +logging.level.io.swagger.api: + PetApiClient: DEBUG + StoreApiClient: DEBUG + UserApiClient: DEBUG From 5f15121fc2f1315006726e6a90dc08f5eb5566fd Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 6 Jul 2016 11:26:16 +0200 Subject: [PATCH 3/6] add springboot and spring-cloud to verified samples --- pom.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pom.xml b/pom.xml index 37cd5602fb8..c8eb777e41c 100644 --- a/pom.xml +++ b/pom.xml @@ -558,6 +558,30 @@ samples/server/petstore/spring-mvc + + springboot + + + env + java + + + + samples/server/petstore/springboot + + + + spring-cloud + + + env + java + + + + samples/client/petstore/spring-cloud + + samples @@ -589,6 +613,8 @@ samples/client/petstore/javascript samples/client/petstore/scala samples/server/petstore/spring-mvc + samples/server/petstore/springboot + samples/client/petstore/spring-cloud samples/server/petstore/jaxrs/jersey1 samples/server/petstore/jaxrs/jersey2 samples/server/petstore/jaxrs-resteasy From 57f518fe93dfaa3a8aa968265ab28307f3014889 Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 6 Jul 2016 11:47:48 +0200 Subject: [PATCH 4/6] change spring-mvc petstore artifact-id --- bin/spring-mvc-petstore-server.json | 4 +++ bin/spring-mvc-petstore-server.sh | 2 +- samples/server/petstore/spring-mvc/pom.xml | 4 +-- .../src/main/java/io/swagger/api/PetApi.java | 27 ++++++++----------- .../main/java/io/swagger/api/StoreApi.java | 8 +++--- .../src/main/java/io/swagger/api/UserApi.java | 22 +++++++-------- 6 files changed, 32 insertions(+), 35 deletions(-) create mode 100644 bin/spring-mvc-petstore-server.json diff --git a/bin/spring-mvc-petstore-server.json b/bin/spring-mvc-petstore-server.json new file mode 100644 index 00000000000..4642abf8015 --- /dev/null +++ b/bin/spring-mvc-petstore-server.json @@ -0,0 +1,4 @@ +{ + "library": "spring-mvc", + "artifactId": "swagger-spring-mvc-server" +} diff --git a/bin/spring-mvc-petstore-server.sh b/bin/spring-mvc-petstore-server.sh index 736688491c5..d03c5a1647c 100755 --- a/bin/spring-mvc-petstore-server.sh +++ b/bin/spring-mvc-petstore-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/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring --library spring-mvc -o samples/server/petstore/spring-mvc -DhideGenerationTimestamp=true" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -c bin/spring-mvc-petstore-server.json -o samples/server/petstore/spring-mvc -DhideGenerationTimestamp=true" java $JAVA_OPTS -jar $executable $ags diff --git a/samples/server/petstore/spring-mvc/pom.xml b/samples/server/petstore/spring-mvc/pom.xml index df0c832d955..c3a46a657d7 100644 --- a/samples/server/petstore/spring-mvc/pom.xml +++ b/samples/server/petstore/spring-mvc/pom.xml @@ -1,9 +1,9 @@ 4.0.0 io.swagger - swagger-spring-server + swagger-spring-mvc-server jar - swagger-spring-server + swagger-spring-mvc-server 1.0.0 src/main/java diff --git a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/PetApi.java b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/PetApi.java index f0f76394bf3..2957ca3c71b 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/PetApi.java +++ b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/PetApi.java @@ -26,7 +26,7 @@ public interface PetApi { @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 405, message = "Invalid input", response = Void.class) }) @RequestMapping(value = "/pet", @@ -41,14 +41,13 @@ public interface PetApi { @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid pet value", response = Void.class) }) @RequestMapping(value = "/pet/{petId}", produces = { "application/xml", "application/json" }, method = RequestMethod.DELETE) - ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId, - @ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey); + ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey); @ApiOperation(value = "Finds Pets by status", notes = "Multiple status values can be provided with comma separated strings", response = Pet.class, responseContainer = "List", authorizations = { @@ -56,7 +55,7 @@ ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=tru @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Pet.class), @ApiResponse(code = 400, message = "Invalid status value", response = Pet.class) }) @@ -71,7 +70,7 @@ ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=tru @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Pet.class), @ApiResponse(code = 400, message = "Invalid tag value", response = Pet.class) }) @@ -83,7 +82,7 @@ ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=tru @ApiOperation(value = "Find pet by ID", notes = "Returns a single pet", response = Pet.class, authorizations = { @Authorization(value = "api_key") - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Pet.class), @ApiResponse(code = 400, message = "Invalid ID supplied", response = Pet.class), @@ -99,7 +98,7 @@ ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=tru @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid ID supplied", response = Void.class), @ApiResponse(code = 404, message = "Pet not found", response = Void.class), @@ -116,16 +115,14 @@ ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=tru @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 405, message = "Invalid input", response = Void.class) }) @RequestMapping(value = "/pet/{petId}", produces = { "application/xml", "application/json" }, consumes = { "application/x-www-form-urlencoded" }, method = RequestMethod.POST) - ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId, - @ApiParam(value = "Updated name of the pet" ) @RequestPart(value="name", required=false) String name, - @ApiParam(value = "Updated status of the pet" ) @RequestPart(value="status", required=false) String status); + ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Updated name of the pet" ) @RequestPart(value="name", required=false) String name,@ApiParam(value = "Updated status of the pet" ) @RequestPart(value="status", required=false) String status); @ApiOperation(value = "uploads an image", notes = "", response = ModelApiResponse.class, authorizations = { @@ -133,15 +130,13 @@ ResponseEntity updatePetWithForm(@ApiParam(value = "ID of pet that needs t @AuthorizationScope(scope = "write:pets", description = "modify pets in your account"), @AuthorizationScope(scope = "read:pets", description = "read your pets") }) - }) + }, tags={ "pet", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = ModelApiResponse.class) }) @RequestMapping(value = "/pet/{petId}/uploadImage", produces = { "application/json" }, consumes = { "multipart/form-data" }, method = RequestMethod.POST) - ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId, - @ApiParam(value = "Additional data to pass to server" ) @RequestPart(value="additionalMetadata", required=false) String additionalMetadata, - @ApiParam(value = "file detail") @RequestPart("file") MultipartFile file); + ResponseEntity uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId,@ApiParam(value = "Additional data to pass to server" ) @RequestPart(value="additionalMetadata", required=false) String additionalMetadata,@ApiParam(value = "file detail") @RequestPart("file") MultipartFile file); } diff --git a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/StoreApi.java b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/StoreApi.java index f67745dfa32..f5526de9862 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/StoreApi.java +++ b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/StoreApi.java @@ -20,7 +20,7 @@ @Api(value = "store", description = "the store API") public interface StoreApi { - @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class) + @ApiOperation(value = "Delete purchase order by ID", notes = "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", response = Void.class, tags={ "store", }) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid ID supplied", response = Void.class), @ApiResponse(code = 404, message = "Order not found", response = Void.class) }) @@ -32,7 +32,7 @@ public interface StoreApi { @ApiOperation(value = "Returns pet inventories by status", notes = "Returns a map of status codes to quantities", response = Integer.class, responseContainer = "Map", authorizations = { @Authorization(value = "api_key") - }) + }, tags={ "store", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Integer.class) }) @RequestMapping(value = "/store/inventory", @@ -41,7 +41,7 @@ public interface StoreApi { ResponseEntity> getInventory(); - @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class) + @ApiOperation(value = "Find purchase order by ID", notes = "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", response = Order.class, tags={ "store", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Order.class), @ApiResponse(code = 400, message = "Invalid ID supplied", response = Order.class), @@ -52,7 +52,7 @@ public interface StoreApi { ResponseEntity getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId); - @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class) + @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class, tags={ "store", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Order.class), @ApiResponse(code = 400, message = "Invalid Order", response = Order.class) }) diff --git a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/UserApi.java b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/UserApi.java index 508a5c1863d..14658ede06a 100644 --- a/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/UserApi.java +++ b/samples/server/petstore/spring-mvc/src/main/java/io/swagger/api/UserApi.java @@ -20,7 +20,7 @@ @Api(value = "user", description = "the user API") public interface UserApi { - @ApiOperation(value = "Create user", notes = "This can only be done by the logged in user.", response = Void.class) + @ApiOperation(value = "Create user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) @RequestMapping(value = "/user", @@ -29,7 +29,7 @@ public interface UserApi { ResponseEntity createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body); - @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class) + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) @RequestMapping(value = "/user/createWithArray", @@ -38,7 +38,7 @@ public interface UserApi { ResponseEntity createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body); - @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class) + @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) @RequestMapping(value = "/user/createWithList", @@ -47,7 +47,7 @@ public interface UserApi { ResponseEntity createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List body); - @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class) + @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid username supplied", response = Void.class), @ApiResponse(code = 404, message = "User not found", response = Void.class) }) @@ -57,7 +57,7 @@ public interface UserApi { ResponseEntity deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username); - @ApiOperation(value = "Get user by user name", notes = "", response = User.class) + @ApiOperation(value = "Get user by user name", notes = "", response = User.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = User.class), @ApiResponse(code = 400, message = "Invalid username supplied", response = User.class), @@ -68,18 +68,17 @@ public interface UserApi { ResponseEntity getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username); - @ApiOperation(value = "Logs user into the system", notes = "", response = String.class) + @ApiOperation(value = "Logs user into the system", notes = "", response = String.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = String.class), @ApiResponse(code = 400, message = "Invalid username/password supplied", response = String.class) }) @RequestMapping(value = "/user/login", produces = { "application/xml", "application/json" }, method = RequestMethod.GET) - ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username, - @ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password); + ResponseEntity loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username,@ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password); - @ApiOperation(value = "Logs out current logged in user session", notes = "", response = Void.class) + @ApiOperation(value = "Logs out current logged in user session", notes = "", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 200, message = "successful operation", response = Void.class) }) @RequestMapping(value = "/user/logout", @@ -88,14 +87,13 @@ ResponseEntity loginUser(@ApiParam(value = "The user name for login", re ResponseEntity logoutUser(); - @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class) + @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) @ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid user supplied", response = Void.class), @ApiResponse(code = 404, message = "User not found", response = Void.class) }) @RequestMapping(value = "/user/{username}", produces = { "application/xml", "application/json" }, method = RequestMethod.PUT) - ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username, - @ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body); + ResponseEntity updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username,@ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body); } From df7b694c4b9af2a2510613292f917912fca54d93 Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 6 Jul 2016 11:51:56 +0200 Subject: [PATCH 5/6] change spring-cloud petstore artifact-id --- bin/spring-cloud-feign-petstore.json | 4 ++++ bin/spring-cloud-feign-petstore.sh | 2 +- samples/client/petstore/spring-cloud/README.md | 8 ++++---- samples/client/petstore/spring-cloud/pom.xml | 4 ++-- 4 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 bin/spring-cloud-feign-petstore.json diff --git a/bin/spring-cloud-feign-petstore.json b/bin/spring-cloud-feign-petstore.json new file mode 100644 index 00000000000..7425cee47f6 --- /dev/null +++ b/bin/spring-cloud-feign-petstore.json @@ -0,0 +1,4 @@ +{ + "library": "spring-cloud", + "artifactId": "swagger-petstore-spring-cloud" +} diff --git a/bin/spring-cloud-feign-petstore.sh b/bin/spring-cloud-feign-petstore.sh index e2cafebda84..a5605217b07 100755 --- a/bin/spring-cloud-feign-petstore.sh +++ b/bin/spring-cloud-feign-petstore.sh @@ -26,7 +26,7 @@ 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/JavaSpring/libraries/spring-cloud -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -o samples/client/petstore/spring-cloud --library spring-cloud -DhideGenerationTimestamp=true" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l spring -c bin/spring-cloud-feign-petstore.json -o samples/client/petstore/spring-cloud -DhideGenerationTimestamp=true" echo "Removing files and folders under samples/client/petstore/spring-cloud/src/main" rm -rf samples/client/petstore/spring-cloud/src/main diff --git a/samples/client/petstore/spring-cloud/README.md b/samples/client/petstore/spring-cloud/README.md index 56d8781caad..0d2d58540db 100644 --- a/samples/client/petstore/spring-cloud/README.md +++ b/samples/client/petstore/spring-cloud/README.md @@ -1,4 +1,4 @@ -# swagger-spring +# swagger-petstore-spring-cloud ## Requirements @@ -27,7 +27,7 @@ Add this dependency to your project's POM: ```xml io.swagger - swagger-spring + swagger-petstore-spring-cloud 1.0.0 compile @@ -38,7 +38,7 @@ Add this dependency to your project's POM: Add this dependency to your project's build file: ```groovy -compile "io.swagger:swagger-spring:1.0.0" +compile "io.swagger:swagger-petstore-spring-cloud:1.0.0" ``` ### Others @@ -49,5 +49,5 @@ mvn package Then manually install the following JARs: -* target/swagger-spring-1.0.0.jar +* target/swagger-petstore-spring-cloud-1.0.0.jar * target/lib/*.jar diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml index 52e3be061db..fbe01604b10 100644 --- a/samples/client/petstore/spring-cloud/pom.xml +++ b/samples/client/petstore/spring-cloud/pom.xml @@ -1,9 +1,9 @@ 4.0.0 io.swagger - swagger-spring + swagger-petstore-spring-cloud jar - swagger-spring + swagger-petstore-spring-cloud 1.0.0 1.7 From e2c7dc014795a118ac7782401a677c769046a448 Mon Sep 17 00:00:00 2001 From: cbornet Date: Wed, 6 Jul 2016 15:29:54 +0200 Subject: [PATCH 6/6] don't repackage as a spring boot app --- .../libraries/spring-cloud/pom.mustache | 15 --------------- samples/client/petstore/spring-cloud/pom.xml | 13 ------------- 2 files changed, 28 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache index bec76800557..84e0b0c2f99 100644 --- a/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/JavaSpring/libraries/spring-cloud/pom.mustache @@ -18,21 +18,6 @@ src/main/java - {{^interfaceOnly}} - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - - - - {{/interfaceOnly}} diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml index fbe01604b10..159fdae3e61 100644 --- a/samples/client/petstore/spring-cloud/pom.xml +++ b/samples/client/petstore/spring-cloud/pom.xml @@ -18,19 +18,6 @@ src/main/java - - - org.springframework.boot - spring-boot-maven-plugin - - - - repackage - - - - -