diff --git a/bin/spring-cloud-feign-petstore.sh b/bin/spring-cloud-feign-petstore.sh
index a5605217b07..9f76a40ded5 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 -c bin/spring-cloud-feign-petstore.json -o samples/client/petstore/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,responseWrapper=HystrixCommand"
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/java/io/swagger/codegen/languages/SpringCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SpringCodegen.java
index 43c0a90e4c2..2b0cb059f21 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
@@ -17,6 +17,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
public static final String SINGLE_CONTENT_TYPES = "singleContentTypes";
public static final String JAVA_8 = "java8";
public static final String ASYNC = "async";
+ public static final String RESPONSE_WRAPPER = "responseWrapper";
public static final String SPRING_MVC_LIBRARY = "spring-mvc";
public static final String SPRING_CLOUD_LIBRARY = "spring-cloud";
@@ -27,6 +28,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
protected boolean singleContentTypes = false;
protected boolean java8 = false;
protected boolean async = false;
+ protected String responseWrapper = "";
public SpringCodegen() {
super();
@@ -51,6 +53,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
cliOptions.add(CliOption.newBoolean(SINGLE_CONTENT_TYPES, "Whether to select only one produces/consumes content-type by operation."));
cliOptions.add(CliOption.newBoolean(JAVA_8, "use java8 default interface"));
cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers"));
+ cliOptions.add(new CliOption(RESPONSE_WRAPPER, "wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)"));
supportedLibraries.put(DEFAULT_LIBRARY, "Spring-boot Server application using the SpringFox integration.");
supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC Server application using the SpringFox integration.");
@@ -117,6 +120,10 @@ public class SpringCodegen extends AbstractJavaCodegen {
this.setAsync(Boolean.valueOf(additionalProperties.get(ASYNC).toString()));
}
+ if (additionalProperties.containsKey(RESPONSE_WRAPPER)) {
+ this.setResponseWrapper((String) additionalProperties.get(RESPONSE_WRAPPER));
+ }
+
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@@ -173,11 +180,43 @@ public class SpringCodegen extends AbstractJavaCodegen {
if (this.java8) {
additionalProperties.put("javaVersion", "1.8");
additionalProperties.put("jdk8", "true");
+ if (this.async) {
+ additionalProperties.put(RESPONSE_WRAPPER, "CompletableFuture");
+ }
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "OffsetDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("OffsetDateTime", "java.time.OffsetDateTime");
+ } else if (this.async) {
+ additionalProperties.put(RESPONSE_WRAPPER, "Callable");
}
+
+ // Some well-known Spring or Spring-Cloud response wrappers
+ switch (this.responseWrapper) {
+ case "Future":
+ case "Callable":
+ case "CompletableFuture":
+ additionalProperties.put(RESPONSE_WRAPPER, "java.util.concurrent" + this.responseWrapper);
+ break;
+ case "ListenableFuture":
+ additionalProperties.put(RESPONSE_WRAPPER, "org.springframework.util.concurrent.ListenableFuture");
+ break;
+ case "DeferredResult":
+ additionalProperties.put(RESPONSE_WRAPPER, "org.springframework.web.context.request.DeferredResult");
+ break;
+ case "HystrixCommand":
+ additionalProperties.put(RESPONSE_WRAPPER, "com.netflix.hystrix.HystrixCommand");
+ break;
+ case "RxObservable":
+ additionalProperties.put(RESPONSE_WRAPPER, "rx.Observable");
+ break;
+ case "RxSingle":
+ additionalProperties.put(RESPONSE_WRAPPER, "rx.Single");
+ break;
+ default:
+ break;
+ }
+
}
@Override
@@ -355,6 +394,8 @@ public class SpringCodegen extends AbstractJavaCodegen {
public void setAsync(boolean async) { this.async = async; }
+ public void setResponseWrapper(String responseWrapper) { this.responseWrapper = responseWrapper; }
+
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
diff --git a/modules/swagger-codegen/src/main/resources/JavaSpring/api.mustache b/modules/swagger-codegen/src/main/resources/JavaSpring/api.mustache
index 8852a36b9b9..4a97c5d5f33 100644
--- a/modules/swagger-codegen/src/main/resources/JavaSpring/api.mustache
+++ b/modules/swagger-codegen/src/main/resources/JavaSpring/api.mustache
@@ -43,7 +43,7 @@ public interface {{classname}} {
produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}}
consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}}
method = RequestMethod.{{httpMethod}})
- {{#jdk8}}default {{/jdk8}}{{#async}}{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture<{{/jdk8}}{{/async}}ResponseEntity<{{>returnTypes}}>{{#async}}>{{/async}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
+ {{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},
{{/hasMore}}{{/allParams}}){{^jdk8}};{{/jdk8}}{{#jdk8}} {
// do some magic!
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}};
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 84e0b0c2f99..f8f7d16f02b 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.6.RELEASE
+ 1.4.1.RELEASE
src/main/java
@@ -25,7 +25,7 @@
org.springframework.cloud
spring-cloud-starter-parent
- Brixton.SR2
+ Camden.SR1
pom
import
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 3cc8bfee148..de7caa0d6c7 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
@@ -15,6 +15,7 @@ public class SpringOptionsProvider extends JavaOptionsProvider {
public static final String SINGLE_CONTENT_TYPES = "true";
public static final String JAVA_8 = "true";
public static final String ASYNC = "true";
+ public static final String RESPONSE_WRAPPER = "Callable";
@Override
public String getLanguage() {
@@ -32,6 +33,7 @@ public class SpringOptionsProvider extends JavaOptionsProvider {
options.put(SpringCodegen.SINGLE_CONTENT_TYPES, SINGLE_CONTENT_TYPES);
options.put(SpringCodegen.JAVA_8, JAVA_8);
options.put(SpringCodegen.ASYNC, ASYNC);
+ options.put(SpringCodegen.RESPONSE_WRAPPER, RESPONSE_WRAPPER);
return options;
}
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 8adaa67679d..4084c0a80e9 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
@@ -64,6 +64,8 @@ public class SpringOptionsTest extends JavaClientOptionsTest {
times = 1;
clientCodegen.setAsync(Boolean.valueOf(SpringOptionsProvider.ASYNC));
times = 1;
+ clientCodegen.setResponseWrapper(SpringOptionsProvider.RESPONSE_WRAPPER);
+ times = 1;
}};
}
diff --git a/samples/client/petstore/spring-cloud/pom.xml b/samples/client/petstore/spring-cloud/pom.xml
index 159fdae3e61..38b81bfaae5 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.6.RELEASE
+ 1.4.1.RELEASE
src/main/java
@@ -25,7 +25,7 @@
org.springframework.cloud
spring-cloud-starter-parent
- Brixton.SR2
+ Camden.SR1
pom
import
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 4bba62c661d..812ca04e270 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
@@ -33,7 +33,7 @@ public interface PetApi {
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);
+ com.netflix.hystrix.HystrixCommand> 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 = {
@@ -48,7 +48,7 @@ public interface PetApi {
produces = "application/json",
consumes = "application/json",
method = RequestMethod.DELETE)
- ResponseEntity deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,
+ com.netflix.hystrix.HystrixCommand> deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,
@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey);
@@ -65,7 +65,7 @@ public interface PetApi {
produces = "application/json",
consumes = "application/json",
method = RequestMethod.GET)
- ResponseEntity> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "AVAILABLE, PENDING, SOLD") @RequestParam(value = "status", required = true) List status);
+ com.netflix.hystrix.HystrixCommand>> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "AVAILABLE, PENDING, SOLD") @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 = {
@@ -81,7 +81,7 @@ public interface PetApi {
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);
+ com.netflix.hystrix.HystrixCommand>> 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 = {
@@ -95,7 +95,7 @@ public interface PetApi {
produces = "application/json",
consumes = "application/json",
method = RequestMethod.GET)
- ResponseEntity getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId);
+ com.netflix.hystrix.HystrixCommand> 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 = {
@@ -112,7 +112,7 @@ public interface PetApi {
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);
+ com.netflix.hystrix.HystrixCommand> 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 = {
@@ -127,7 +127,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,
+ com.netflix.hystrix.HystrixCommand> 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);
@@ -144,7 +144,7 @@ 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,
+ com.netflix.hystrix.HystrixCommand> 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/StoreApi.java b/samples/client/petstore/spring-cloud/src/main/java/io/swagger/api/StoreApi.java
index 1eb724e96c9..4442f2ff784 100644
--- 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
@@ -28,7 +28,7 @@ public interface StoreApi {
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);
+ com.netflix.hystrix.HystrixCommand> 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 = {
@@ -40,7 +40,7 @@ public interface StoreApi {
produces = "application/json",
consumes = "application/json",
method = RequestMethod.GET)
- ResponseEntity