[spring] add an option to choose the response wrapper type

Also generate the spring-cloud sample with a HystrixCommand wrapper
This commit is contained in:
cbornet 2016-10-25 15:40:51 +02:00
parent 92c474b2c2
commit 21ec2bc866
15 changed files with 157 additions and 129 deletions

View File

@ -26,7 +26,7 @@ fi
# if you've executed sbt assembly previously it will use that instead. # 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" 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" echo "Removing files and folders under samples/client/petstore/spring-cloud/src/main"
rm -rf samples/client/petstore/spring-cloud/src/main rm -rf samples/client/petstore/spring-cloud/src/main

View File

@ -17,6 +17,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
public static final String SINGLE_CONTENT_TYPES = "singleContentTypes"; public static final String SINGLE_CONTENT_TYPES = "singleContentTypes";
public static final String JAVA_8 = "java8"; public static final String JAVA_8 = "java8";
public static final String ASYNC = "async"; 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_MVC_LIBRARY = "spring-mvc";
public static final String SPRING_CLOUD_LIBRARY = "spring-cloud"; public static final String SPRING_CLOUD_LIBRARY = "spring-cloud";
@ -27,6 +28,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
protected boolean singleContentTypes = false; protected boolean singleContentTypes = false;
protected boolean java8 = false; protected boolean java8 = false;
protected boolean async = false; protected boolean async = false;
protected String responseWrapper = "";
public SpringCodegen() { public SpringCodegen() {
super(); 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(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(JAVA_8, "use java8 default interface"));
cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers")); 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(DEFAULT_LIBRARY, "Spring-boot Server application using the SpringFox integration.");
supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC 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())); 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("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
@ -173,11 +180,43 @@ public class SpringCodegen extends AbstractJavaCodegen {
if (this.java8) { if (this.java8) {
additionalProperties.put("javaVersion", "1.8"); additionalProperties.put("javaVersion", "1.8");
additionalProperties.put("jdk8", "true"); additionalProperties.put("jdk8", "true");
if (this.async) {
additionalProperties.put(RESPONSE_WRAPPER, "CompletableFuture");
}
typeMapping.put("date", "LocalDate"); typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "OffsetDateTime"); typeMapping.put("DateTime", "OffsetDateTime");
importMapping.put("LocalDate", "java.time.LocalDate"); importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("OffsetDateTime", "java.time.OffsetDateTime"); 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 @Override
@ -355,6 +394,8 @@ public class SpringCodegen extends AbstractJavaCodegen {
public void setAsync(boolean async) { this.async = async; } public void setAsync(boolean async) { this.async = async; }
public void setResponseWrapper(String responseWrapper) { this.responseWrapper = responseWrapper; }
@Override @Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property); super.postProcessModelProperty(model, property);

View File

@ -43,7 +43,7 @@ public interface {{classname}} {
produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}} produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}}
consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}} consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}}
method = RequestMethod.{{httpMethod}}) 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}} { {{/hasMore}}{{/allParams}}){{^jdk8}};{{/jdk8}}{{#jdk8}} {
// do some magic! // do some magic!
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}}; return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}};

View File

@ -14,7 +14,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.6.RELEASE</version> <version>1.4.1.RELEASE</version>
</parent> </parent>
<build> <build>
<sourceDirectory>src/main/java</sourceDirectory> <sourceDirectory>src/main/java</sourceDirectory>
@ -25,7 +25,7 @@
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId> <artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.SR2</version> <version>Camden.SR1</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>

View File

@ -15,6 +15,7 @@ public class SpringOptionsProvider extends JavaOptionsProvider {
public static final String SINGLE_CONTENT_TYPES = "true"; public static final String SINGLE_CONTENT_TYPES = "true";
public static final String JAVA_8 = "true"; public static final String JAVA_8 = "true";
public static final String ASYNC = "true"; public static final String ASYNC = "true";
public static final String RESPONSE_WRAPPER = "Callable";
@Override @Override
public String getLanguage() { public String getLanguage() {
@ -32,6 +33,7 @@ public class SpringOptionsProvider extends JavaOptionsProvider {
options.put(SpringCodegen.SINGLE_CONTENT_TYPES, SINGLE_CONTENT_TYPES); options.put(SpringCodegen.SINGLE_CONTENT_TYPES, SINGLE_CONTENT_TYPES);
options.put(SpringCodegen.JAVA_8, JAVA_8); options.put(SpringCodegen.JAVA_8, JAVA_8);
options.put(SpringCodegen.ASYNC, ASYNC); options.put(SpringCodegen.ASYNC, ASYNC);
options.put(SpringCodegen.RESPONSE_WRAPPER, RESPONSE_WRAPPER);
return options; return options;
} }

View File

@ -64,6 +64,8 @@ public class SpringOptionsTest extends JavaClientOptionsTest {
times = 1; times = 1;
clientCodegen.setAsync(Boolean.valueOf(SpringOptionsProvider.ASYNC)); clientCodegen.setAsync(Boolean.valueOf(SpringOptionsProvider.ASYNC));
times = 1; times = 1;
clientCodegen.setResponseWrapper(SpringOptionsProvider.RESPONSE_WRAPPER);
times = 1;
}}; }};
} }

View File

@ -14,7 +14,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>1.3.6.RELEASE</version> <version>1.4.1.RELEASE</version>
</parent> </parent>
<build> <build>
<sourceDirectory>src/main/java</sourceDirectory> <sourceDirectory>src/main/java</sourceDirectory>
@ -25,7 +25,7 @@
<dependency> <dependency>
<groupId>org.springframework.cloud</groupId> <groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-parent</artifactId> <artifactId>spring-cloud-starter-parent</artifactId>
<version>Brixton.SR2</version> <version>Camden.SR1</version>
<type>pom</type> <type>pom</type>
<scope>import</scope> <scope>import</scope>
</dependency> </dependency>

View File

@ -33,7 +33,7 @@ public interface PetApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Void> addPet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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 = { @ApiOperation(value = "Deletes a pet", notes = "", response = Void.class, authorizations = {
@ -48,7 +48,7 @@ public interface PetApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.DELETE) method = RequestMethod.DELETE)
ResponseEntity<Void> deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId, com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> deletePet(@ApiParam(value = "Pet id to delete",required=true ) @PathVariable("petId") Long petId,
@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey); @ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) String apiKey);
@ -65,7 +65,7 @@ public interface PetApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<List<Pet>> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "AVAILABLE, PENDING, SOLD") @RequestParam(value = "status", required = true) List<String> status); com.netflix.hystrix.HystrixCommand<ResponseEntity<List<Pet>>> findPetsByStatus(@ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "AVAILABLE, PENDING, SOLD") @RequestParam(value = "status", required = true) List<String> 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 = { @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", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<List<Pet>> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List<String> tags); com.netflix.hystrix.HystrixCommand<ResponseEntity<List<Pet>>> findPetsByTags(@ApiParam(value = "Tags to filter by", required = true) @RequestParam(value = "tags", required = true) List<String> tags);
@ApiOperation(value = "Find pet by ID", notes = "Returns a single pet", response = Pet.class, authorizations = { @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", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<Pet> getPetById(@ApiParam(value = "ID of pet to return",required=true ) @PathVariable("petId") Long petId); com.netflix.hystrix.HystrixCommand<ResponseEntity<Pet>> 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 = { @ApiOperation(value = "Update an existing pet", notes = "", response = Void.class, authorizations = {
@ -112,7 +112,7 @@ public interface PetApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.PUT) method = RequestMethod.PUT)
ResponseEntity<Void> updatePet(@ApiParam(value = "Pet object that needs to be added to the store" ,required=true ) @RequestBody Pet body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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 = { @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", produces = "application/json",
consumes = "application/x-www-form-urlencoded", consumes = "application/x-www-form-urlencoded",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Void> updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated",required=true ) @PathVariable("petId") Long petId, com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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 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); @ApiParam(value = "Updated status of the pet" ) @RequestParam(value="status", required=false) String status);
@ -144,7 +144,7 @@ public interface PetApi {
produces = "application/json", produces = "application/json",
consumes = "multipart/form-data", consumes = "multipart/form-data",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<ModelApiResponse> uploadFile(@ApiParam(value = "ID of pet to update",required=true ) @PathVariable("petId") Long petId, com.netflix.hystrix.HystrixCommand<ResponseEntity<ModelApiResponse>> 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 = "Additional data to pass to server" ) @RequestParam(value="additionalMetadata", required=false) String additionalMetadata,
@ApiParam(value = "file detail") @RequestParam("file") MultipartFile file); @ApiParam(value = "file detail") @RequestParam("file") MultipartFile file);

View File

@ -28,7 +28,7 @@ public interface StoreApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.DELETE) method = RequestMethod.DELETE)
ResponseEntity<Void> deleteOrder(@ApiParam(value = "ID of the order that needs to be deleted",required=true ) @PathVariable("orderId") String orderId); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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 = { @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", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<Map<String, Integer>> getInventory(); com.netflix.hystrix.HystrixCommand<ResponseEntity<Map<String, Integer>>> 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", }) @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", })
@ -52,7 +52,7 @@ public interface StoreApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<Order> getOrderById(@ApiParam(value = "ID of pet that needs to be fetched",required=true ) @PathVariable("orderId") Long orderId); com.netflix.hystrix.HystrixCommand<ResponseEntity<Order>> 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", }) @ApiOperation(value = "Place an order for a pet", notes = "", response = Order.class, tags={ "store", })
@ -63,6 +63,6 @@ public interface StoreApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Order> placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Order>> placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @RequestBody Order body);
} }

View File

@ -27,7 +27,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Void> createUser(@ApiParam(value = "Created user object" ,required=true ) @RequestBody User body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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", }) @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", })
@ -37,7 +37,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Void> createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List<User> body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> createUsersWithArrayInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List<User> body);
@ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", }) @ApiOperation(value = "Creates list of users with given input array", notes = "", response = Void.class, tags={ "user", })
@ -47,7 +47,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.POST) method = RequestMethod.POST)
ResponseEntity<Void> createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List<User> body); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> createUsersWithListInput(@ApiParam(value = "List of user object" ,required=true ) @RequestBody List<User> body);
@ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) @ApiOperation(value = "Delete user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", })
@ -58,7 +58,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.DELETE) method = RequestMethod.DELETE)
ResponseEntity<Void> deleteUser(@ApiParam(value = "The name that needs to be deleted",required=true ) @PathVariable("username") String username); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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", }) @ApiOperation(value = "Get user by user name", notes = "", response = User.class, tags={ "user", })
@ -70,7 +70,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<User> getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing. ",required=true ) @PathVariable("username") String username); com.netflix.hystrix.HystrixCommand<ResponseEntity<User>> 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", }) @ApiOperation(value = "Logs user into the system", notes = "", response = String.class, tags={ "user", })
@ -81,7 +81,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<String> loginUser(@ApiParam(value = "The user name for login", required = true) @RequestParam(value = "username", required = true) String username, com.netflix.hystrix.HystrixCommand<ResponseEntity<String>> 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); @ApiParam(value = "The password for login in clear text", required = true) @RequestParam(value = "password", required = true) String password);
@ -92,7 +92,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.GET) method = RequestMethod.GET)
ResponseEntity<Void> logoutUser(); com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> logoutUser();
@ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", }) @ApiOperation(value = "Updated user", notes = "This can only be done by the logged in user.", response = Void.class, tags={ "user", })
@ -103,7 +103,7 @@ public interface UserApi {
produces = "application/json", produces = "application/json",
consumes = "application/json", consumes = "application/json",
method = RequestMethod.PUT) method = RequestMethod.PUT)
ResponseEntity<Void> updateUser(@ApiParam(value = "name that need to be deleted",required=true ) @PathVariable("username") String username, com.netflix.hystrix.HystrixCommand<ResponseEntity<Void>> 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); @ApiParam(value = "Updated user object" ,required=true ) @RequestBody User body);
} }

View File

@ -0,0 +1,20 @@
package io.swagger;
import feign.Logger;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableFeignClients
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}

View File

@ -1,30 +1,28 @@
package io.swagger.api; package io.swagger.api;
import feign.FeignException; import com.netflix.hystrix.exception.HystrixRuntimeException;
import io.swagger.Application;
import io.swagger.TestUtils; 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.Category;
import io.swagger.model.Pet; import io.swagger.model.Pet;
import io.swagger.model.Tag; import io.swagger.model.Tag;
import org.junit.*; import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest;
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.mock.web.MockMultipartFile;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = PetApiTest.Application.class) @SpringBootTest(classes = Application.class)
public class PetApiTest { public class PetApiTest {
@Autowired @Autowired
@ -33,9 +31,8 @@ public class PetApiTest {
@Test @Test
public void testCreateAndGetPet() { public void testCreateAndGetPet() {
Pet pet = createRandomPet(); Pet pet = createRandomPet();
client.addPet(pet); client.addPet(pet).execute();
ResponseEntity<Pet> rp = client.getPetById(pet.getId()); Pet fetched = client.getPetById(pet.getId()).execute().getBody();
Pet fetched = rp.getBody();
assertNotNull(fetched); assertNotNull(fetched);
assertEquals(pet.getId(), fetched.getId()); assertEquals(pet.getId(), fetched.getId());
assertNotNull(fetched.getCategory()); assertNotNull(fetched.getCategory());
@ -47,9 +44,9 @@ public class PetApiTest {
Pet pet = createRandomPet(); Pet pet = createRandomPet();
pet.setName("programmer"); pet.setName("programmer");
client.updatePet(pet); client.updatePet(pet).execute();
Pet fetched = client.getPetById(pet.getId()).getBody(); Pet fetched = client.getPetById(pet.getId()).execute().getBody();
assertNotNull(fetched); assertNotNull(fetched);
assertEquals(pet.getId(), fetched.getId()); assertEquals(pet.getId(), fetched.getId());
assertNotNull(fetched.getCategory()); assertNotNull(fetched.getCategory());
@ -63,9 +60,9 @@ public class PetApiTest {
pet.setName("programmer"); pet.setName("programmer");
pet.setStatus(Pet.StatusEnum.AVAILABLE); pet.setStatus(Pet.StatusEnum.AVAILABLE);
client.updatePet(pet); client.updatePet(pet).execute();
List<Pet> pets = client.findPetsByStatus(Arrays.asList(new String[]{"available"})).getBody(); List<Pet> pets = client.findPetsByStatus(Collections.singletonList("available")).execute().getBody();
assertNotNull(pets); assertNotNull(pets);
boolean found = false; boolean found = false;
@ -92,9 +89,9 @@ public class PetApiTest {
tags.add(tag1); tags.add(tag1);
pet.setTags(tags); pet.setTags(tags);
client.updatePet(pet); client.updatePet(pet).execute();
List<Pet> pets = client.findPetsByTags(Arrays.asList(new String[]{"friendly"})).getBody(); List<Pet> pets = client.findPetsByTags(Collections.singletonList("friendly")).execute().getBody();
assertNotNull(pets); assertNotNull(pets);
boolean found = false; boolean found = false;
@ -111,12 +108,12 @@ public class PetApiTest {
public void testUpdatePetWithForm() throws Exception { public void testUpdatePetWithForm() throws Exception {
Pet pet = createRandomPet(); Pet pet = createRandomPet();
pet.setName("frank"); pet.setName("frank");
client.addPet(pet); client.addPet(pet).execute();
Pet fetched = client.getPetById(pet.getId()).getBody(); Pet fetched = client.getPetById(pet.getId()).execute().getBody();
client.updatePetWithForm(fetched.getId(), "furt", null); client.updatePetWithForm(fetched.getId(), "furt", null).execute();
Pet updated = client.getPetById(fetched.getId()).getBody(); Pet updated = client.getPetById(fetched.getId()).execute().getBody();
assertEquals(updated.getName(), "furt"); assertEquals(updated.getName(), "furt");
} }
@ -124,16 +121,16 @@ public class PetApiTest {
@Test @Test
public void testDeletePet() throws Exception { public void testDeletePet() throws Exception {
Pet pet = createRandomPet(); Pet pet = createRandomPet();
client.addPet(pet); client.addPet(pet).execute();
Pet fetched = client.getPetById(pet.getId()).getBody(); Pet fetched = client.getPetById(pet.getId()).execute().getBody();
client.deletePet(fetched.getId(), null); client.deletePet(fetched.getId(), null).execute();
try { try {
client.getPetById(fetched.getId()); client.getPetById(fetched.getId()).execute();
fail("expected an error"); fail("expected an error");
} catch (FeignException e) { } catch (HystrixRuntimeException e) {
assertTrue(e.getMessage().startsWith("status 404 ")); assertTrue(e.getCause().getMessage().startsWith("status 404 "));
} }
} }
@ -141,10 +138,10 @@ public class PetApiTest {
@Test @Test
public void testUploadFile() throws Exception { public void testUploadFile() throws Exception {
Pet pet = createRandomPet(); Pet pet = createRandomPet();
client.addPet(pet); client.addPet(pet).execute();
MockMultipartFile filePart = new MockMultipartFile("file", "bar".getBytes()); MockMultipartFile filePart = new MockMultipartFile("file", "bar".getBytes());
client.uploadFile(pet.getId(), "a test file", filePart); client.uploadFile(pet.getId(), "a test file", filePart).execute();
} }
@Test @Test
@ -158,7 +155,7 @@ public class PetApiTest {
assertTrue(pet1.hashCode() == pet1.hashCode()); assertTrue(pet1.hashCode() == pet1.hashCode());
pet2.setName("really-happy"); pet2.setName("really-happy");
pet2.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); pet2.setPhotoUrls(Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2"));
assertFalse(pet1.equals(pet2)); assertFalse(pet1.equals(pet2));
assertFalse(pet2.equals(pet1)); assertFalse(pet2.equals(pet1));
assertFalse(pet1.hashCode() == (pet2.hashCode())); assertFalse(pet1.hashCode() == (pet2.hashCode()));
@ -166,7 +163,7 @@ public class PetApiTest {
assertTrue(pet2.hashCode() == pet2.hashCode()); assertTrue(pet2.hashCode() == pet2.hashCode());
pet1.setName("really-happy"); pet1.setName("really-happy");
pet1.setPhotoUrls(Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"})); pet1.setPhotoUrls(Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2"));
assertTrue(pet1.equals(pet2)); assertTrue(pet1.equals(pet2));
assertTrue(pet2.equals(pet1)); assertTrue(pet2.equals(pet1));
assertTrue(pet1.hashCode() == pet2.hashCode()); assertTrue(pet1.hashCode() == pet2.hashCode());
@ -184,24 +181,10 @@ public class PetApiTest {
pet.setCategory(category); pet.setCategory(category);
pet.setStatus(Pet.StatusEnum.AVAILABLE); pet.setStatus(Pet.StatusEnum.AVAILABLE);
List<String> photos = Arrays.asList(new String[]{"http://foo.bar.com/1", "http://foo.bar.com/2"}); List<String> photos = Arrays.asList("http://foo.bar.com/1", "http://foo.bar.com/2");
pet.setPhotoUrls(photos); pet.setPhotoUrls(photos);
return pet; return pet;
} }
@SpringBootApplication
@EnableFeignClients
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).run(args);
}
}
} }

View File

@ -1,15 +1,13 @@
package io.swagger.api; package io.swagger.api;
import feign.FeignException; import com.netflix.hystrix.exception.HystrixRuntimeException;
import io.swagger.Application;
import io.swagger.TestUtils; import io.swagger.TestUtils;
import io.swagger.model.Order; import io.swagger.model.Order;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest;
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 org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@ -18,7 +16,7 @@ import java.util.Map;
import static org.junit.Assert.*; import static org.junit.Assert.*;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = StoreApiTest.Application.class) @SpringBootTest(classes = Application.class)
public class StoreApiTest { public class StoreApiTest {
@Autowired @Autowired
@ -26,16 +24,16 @@ public class StoreApiTest {
@Test @Test
public void testGetInventory() { public void testGetInventory() {
Map<String, Integer> inventory = client.getInventory().getBody(); Map<String, Integer> inventory = client.getInventory().execute().getBody();
assertTrue(inventory.keySet().size() > 0); assertTrue(inventory.keySet().size() > 0);
} }
@Test @Test
public void testPlaceOrder() { public void testPlaceOrder() {
Order order = createOrder(); Order order = createOrder();
client.placeOrder(order); client.placeOrder(order).execute();
Order fetched = client.getOrderById(order.getId()).getBody(); Order fetched = client.getOrderById(order.getId()).execute().getBody();
assertEquals(order.getId(), fetched.getId()); assertEquals(order.getId(), fetched.getId());
assertEquals(order.getPetId(), fetched.getPetId()); assertEquals(order.getPetId(), fetched.getPetId());
assertEquals(order.getQuantity(), fetched.getQuantity()); assertEquals(order.getQuantity(), fetched.getQuantity());
@ -45,25 +43,25 @@ public class StoreApiTest {
@Test @Test
public void testDeleteOrder() { public void testDeleteOrder() {
Order order = createOrder(); Order order = createOrder();
client.placeOrder(order); client.placeOrder(order).execute();
Order fetched = client.getOrderById(order.getId()).getBody(); Order fetched = client.getOrderById(order.getId()).execute().getBody();
assertEquals(fetched.getId(), order.getId()); assertEquals(fetched.getId(), order.getId());
client.deleteOrder(String.valueOf(order.getId())); client.deleteOrder(String.valueOf(order.getId())).execute();
try { try {
client.getOrderById(order.getId()); client.getOrderById(order.getId()).execute();
fail("expected an error"); fail("expected an error");
} catch (FeignException e) { } catch (HystrixRuntimeException e) {
assertTrue(e.getMessage().startsWith("status 404 ")); assertTrue(e.getCause().getMessage().startsWith("status 404 "));
} }
} }
private Order createOrder() { private Order createOrder() {
Order order = new Order(); Order order = new Order();
order.setPetId(new Long(200)); order.setPetId(200L);
order.setQuantity(new Integer(13)); order.setQuantity(13);
order.setShipDate(org.joda.time.DateTime.now()); order.setShipDate(org.joda.time.DateTime.now());
order.setStatus(Order.StatusEnum.PLACED); order.setStatus(Order.StatusEnum.PLACED);
order.setComplete(true); order.setComplete(true);
@ -79,11 +77,4 @@ public class StoreApiTest {
return order; return order;
} }
@SpringBootApplication
@EnableFeignClients
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(StoreApiTest.Application.class).run(args);
}
}
} }

View File

@ -1,23 +1,21 @@
package io.swagger.api; package io.swagger.api;
import io.swagger.Application;
import io.swagger.TestUtils; import io.swagger.TestUtils;
import io.swagger.model.User; import io.swagger.model.User;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.test.context.SpringBootTest;
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 org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.util.Arrays; import java.util.Arrays;
import static org.junit.Assert.*; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = UserApiTest.Application.class) @SpringBootTest(classes = Application.class)
public class UserApiTest { public class UserApiTest {
@Autowired @Autowired
@ -27,9 +25,9 @@ public class UserApiTest {
public void testCreateUser() { public void testCreateUser() {
User user = createUser(); User user = createUser();
client.createUser(user); client.createUser(user).execute();
User fetched = client.getUserByName(user.getUsername()).getBody(); User fetched = client.getUserByName(user.getUsername()).execute().getBody();
assertEquals(user.getId(), fetched.getId()); assertEquals(user.getId(), fetched.getId());
} }
@ -40,9 +38,9 @@ public class UserApiTest {
User user2 = createUser(); User user2 = createUser();
user2.setUsername("user" + user2.getId()); user2.setUsername("user" + user2.getId());
client.createUsersWithArrayInput(Arrays.asList(new User[]{user1, user2})); client.createUsersWithArrayInput(Arrays.asList(user1, user2)).execute();
User fetched = client.getUserByName(user1.getUsername()).getBody(); User fetched = client.getUserByName(user1.getUsername()).execute().getBody();
assertEquals(user1.getId(), fetched.getId()); assertEquals(user1.getId(), fetched.getId());
} }
@ -53,24 +51,24 @@ public class UserApiTest {
User user2 = createUser(); User user2 = createUser();
user2.setUsername("user" + user2.getId()); user2.setUsername("user" + user2.getId());
client.createUsersWithListInput(Arrays.asList(new User[]{user1, user2})); client.createUsersWithListInput(Arrays.asList(user1, user2)).execute();
User fetched = client.getUserByName(user1.getUsername()).getBody(); User fetched = client.getUserByName(user1.getUsername()).execute().getBody();
assertEquals(user1.getId(), fetched.getId()); assertEquals(user1.getId(), fetched.getId());
} }
@Test @Test
public void testLoginUser() { public void testLoginUser() {
User user = createUser(); User user = createUser();
client.createUser(user); client.createUser(user).execute();
String token = client.loginUser(user.getUsername(), user.getPassword()).getBody(); String token = client.loginUser(user.getUsername(), user.getPassword()).execute().getBody();
assertTrue(token.startsWith("logged in user session:")); assertTrue(token.startsWith("logged in user session:"));
} }
@Test @Test
public void logoutUser() { public void logoutUser() {
client.logoutUser(); client.logoutUser().execute();
} }
private User createUser() { private User createUser() {
@ -87,11 +85,4 @@ public class UserApiTest {
return user; return user;
} }
@SpringBootApplication
@EnableFeignClients
protected static class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(UserApiTest.Application.class).run(args);
}
}
} }

View File

@ -2,9 +2,7 @@ spring:
application: application:
name: petstore-test name: petstore-test
feign.hystrix.enabled: false hystrix.command.default.execution.timeout.enabled: false
logging.level.io.swagger.api: DEBUG
logging.level.io.swagger.api:
PetApiClient: DEBUG
StoreApiClient: DEBUG
UserApiClient: DEBUG