Remove Accept request header from api signature (#6704)

* Remove Accept request header from api signature

* Inject HttpServletRequest to get request header and clean templates

* Use constructor injection for HttpServletRequest

* Implement example in default controller responses
This commit is contained in:
Christophe Bornet
2017-10-27 16:45:31 +02:00
committed by wing328
parent f14e07280a
commit fe2ed67f20
128 changed files with 3465 additions and 2665 deletions

View File

@@ -7,12 +7,19 @@ package {{package}};
{{#imports}}import {{import}};
{{/imports}}
{{#jdk8-no-delegate}}
import com.fasterxml.jackson.databind.ObjectMapper;
{{/jdk8-no-delegate}}
import io.swagger.annotations.*;
{{#jdk8}}
{{#jdk8-no-delegate}}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
{{/jdk8}}
{{/jdk8-no-delegate}}
import org.springframework.http.ResponseEntity;
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated;
{{/useBeanValidation}}
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
@@ -21,26 +28,54 @@ 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;
{{^useSpringCloudClient}}
import java.io.IOException;
{{/useSpringCloudClient}}
{{#jdk8-no-delegate}}
import javax.servlet.http.HttpServletRequest;
{{/jdk8-no-delegate}}
{{#useBeanValidation}}
import javax.validation.Valid;
import javax.validation.constraints.*;
{{/useBeanValidation}}
{{#jdk8-no-delegate}}
import java.io.IOException;
{{/jdk8-no-delegate}}
import java.util.List;
{{#useOptional}}
{{#jdk8-no-delegate}}
import java.util.Optional;
{{/useOptional}}
{{/jdk8-no-delegate}}
{{^jdk8-no-delegate}}
{{#useOptional}}
import java.util.Optional;
{{/useOptional}}
{{/jdk8-no-delegate}}
{{#async}}
import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}};
{{/async}}
{{#useBeanValidation}}
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.*;
import javax.validation.Valid;
{{/useBeanValidation}}
{{>generatedAnnotation}}
@Api(value = "{{{baseName}}}", description = "the {{{baseName}}} API")
{{#operations}}
public interface {{classname}} {
{{#jdk8}}
{{^isDelegate}}
Logger log = LoggerFactory.getLogger({{classname}}.class);
default Optional<ObjectMapper> getObjectMapper() {
return Optional.empty();
}
default Optional<HttpServletRequest> getRequest() {
return Optional.empty();
}
default Optional<String> getAcceptHeader() {
return getRequest().map(r -> r.getHeader("Accept"));
}
{{/isDelegate}}
{{#isDelegate}}
{{classname}}Delegate getDelegate();
{{/isDelegate}}
{{/jdk8}}
{{#operation}}
@ApiOperation(value = "{{{summary}}}", nickname = "{{{operationId}}}", notes = "{{{notes}}}"{{#returnBaseType}}, response = {{{returnBaseType}}}.class{{/returnBaseType}}{{#returnContainer}}, responseContainer = "{{{returnContainer}}}"{{/returnContainer}}{{#hasAuthMethods}}, authorizations = {
@@ -65,20 +100,29 @@ public interface {{classname}} {
produces = { {{#produces}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/produces}} }, {{/hasProduces}}{{#hasConsumes}}
consumes = { {{#consumes}}"{{{mediaType}}}"{{#hasMore}}, {{/hasMore}}{{/consumes}} },{{/hasConsumes}}{{/singleContentTypes}}
method = RequestMethod.{{httpMethod}})
{{#useSpringCloudClient}}
{{#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.NOT_IMPLEMENTED){{#async}}){{/async}};
{{^isDelegate}}
if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
{{#examples}}
if (getAcceptHeader().get().contains("{{{contentType}}}")) {
try {
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(getObjectMapper().get().readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}};
} catch (IOException e) {
log.error("Couldn't serialize response for content type {{{contentType}}}", e);
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR){{#async}}){{/async}};
}
}
{{/examples}}
} else {
log.warn("ObjectMapper or HttpServletRequest not configured in default {{classname}} interface so no example is generated");
}
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}};
{{/isDelegate}}
{{#isDelegate}}
return getDelegate().{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/isDelegate}}
}{{/jdk8}}
{{/useSpringCloudClient}}
{{^useSpringCloudClient}}
{{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},{{/allParams}} @RequestHeader(value = "Accept", required = false) String accept) throws Exception{{^jdk8}};{{/jdk8}}{{#jdk8}} {
// do some magic!
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}};
}{{/jdk8}}
{{/useSpringCloudClient}}
{{/operation}}
}
{{/operations}}

View File

@@ -1,16 +1,21 @@
package {{package}};
{{^jdk8-no-delegate}}
{{^jdk8}}
{{#imports}}import {{import}};
{{/imports}}
{{/jdk8}}
{{^isDelegate}}
import com.fasterxml.jackson.databind.ObjectMapper;
{{/isDelegate}}
{{^jdk8}}
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
{{/jdk8-no-delegate}}
{{/jdk8}}
import org.springframework.stereotype.Controller;
{{^jdk8-no-delegate}}
{{^jdk8}}
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
@@ -18,31 +23,35 @@ import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
{{#useOptional}}
import java.util.Optional;
{{/useOptional}}
{{#async}}
import java.util.concurrent.Callable;
{{/async}}
{{/jdk8-no-delegate}}
{{^useSpringCloudClient}}
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
{{/useSpringCloudClient}}
{{#useBeanValidation}}
{{#useBeanValidation}}
import javax.validation.constraints.*;
import javax.validation.Valid;
{{/useBeanValidation}}
{{/useBeanValidation}}
{{/jdk8}}
{{^isDelegate}}
import javax.servlet.http.HttpServletRequest;
{{#jdk8}}
import java.util.Optional;
{{/jdk8}}
{{/isDelegate}}
{{^jdk8-no-delegate}}
{{#useOptional}}
import java.util.Optional;
{{/useOptional}}
{{/jdk8-no-delegate}}
{{^jdk8}}
{{^isDelegate}}
import java.io.IOException;
{{/isDelegate}}
import java.util.List;
{{#async}}
import java.util.concurrent.Callable;
{{/async}}
{{/jdk8}}
{{>generatedAnnotation}}
@Controller
{{#operations}}
public class {{classname}}Controller implements {{classname}} {
private final ObjectMapper objectMapper;
public {{classname}}Controller(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
{{#isDelegate}}
private final {{classname}}Delegate delegate;
@@ -51,48 +60,78 @@ public class {{classname}}Controller implements {{classname}} {
public {{classname}}Controller({{classname}}Delegate delegate) {
this.delegate = delegate;
}
{{#jdk8}}
@Override
public {{classname}}Delegate getDelegate() {
return delegate;
}
{{/jdk8}}
{{/isDelegate}}
{{^isDelegate}}
{{^jdk8}}
private static final Logger log = LoggerFactory.getLogger({{classname}}Controller.class);
{{/jdk8}}
private final ObjectMapper objectMapper;
private final HttpServletRequest request;
@org.springframework.beans.factory.annotation.Autowired
public {{classname}}Controller(ObjectMapper objectMapper, HttpServletRequest request) {
this.objectMapper = objectMapper;
this.request = request;
}
{{#jdk8}}
@Override
public Optional<ObjectMapper> getObjectMapper() {
return Optional.ofNullable(objectMapper);
}
@Override
public Optional<HttpServletRequest> getRequest() {
return Optional.ofNullable(request);
}
{{/jdk8}}
{{/isDelegate}}
{{^jdk8-no-delegate}}
{{^jdk8}}
{{#operation}}
public {{#async}}Callable<{{/async}}ResponseEntity<{{>returnTypes}}>{{#async}}>{{/async}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}},
{{/allParams}}@RequestHeader(value = "Accept", required = false) String accept) throws Exception {
// do some magic!
{{#useSpringCloudClient}}
{{^isDelegate}}
{{^async}}
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK);
{{/async}}
{{#async}}
return new Callable<ResponseEntity<{{>returnTypes}}>>() {
@Override
public ResponseEntity<{{>returnTypes}}> call() throws Exception {
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK);
}
};
{{/async}}
{{/isDelegate}}
{{#isDelegate}}
return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/isDelegate}}
{{/useSpringCloudClient}}
{{^useSpringCloudClient}}
public {{#async}}Callable<{{/async}}ResponseEntity<{{>returnTypes}}>{{#async}}>{{/async}} {{operationId}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{#hasMore}},{{/hasMore}}{{/allParams}}) {
{{^isDelegate}}
{{^async}}
String accept = request.getHeader("Accept");
{{#examples}}
if (accept != null && accept.contains("{{{contentType}}}")) {
return new ResponseEntity<{{>returnTypes}}>(objectMapper.readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.OK);
try {
return new ResponseEntity<{{>returnTypes}}>(objectMapper.readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.NOT_IMPLEMENTED);
} catch (IOException e) {
log.error("Couldn't serialize response for content type {{{contentType}}}", e);
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
{{/examples}}
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK);
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.NOT_IMPLEMENTED);
{{/async}}
{{#async}}
return new Callable<ResponseEntity<{{>returnTypes}}>>() {
@Override
public ResponseEntity<{{>returnTypes}}> call() throws Exception {
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK);
public ResponseEntity<{{>returnTypes}}> call() {
String accept = request.getHeader("Accept");
{{#examples}}
if (accept != null && accept.contains("{{{contentType}}}")) {
try {
return new ResponseEntity<{{>returnTypes}}>(objectMapper.readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.NOT_IMPLEMENTED);
} catch (IOException e) {
log.error("Couldn't serialize response for content type {{{contentType}}}", e);
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
{{/examples}}
return new ResponseEntity<{{>returnTypes}}>(HttpStatus.NOT_IMPLEMENTED);
}
};
{{/async}}
@@ -100,10 +139,9 @@ public class {{classname}}Controller implements {{classname}} {
{{#isDelegate}}
return delegate.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
{{/isDelegate}}
{{/useSpringCloudClient}}
}
{{/operation}}
{{/jdk8-no-delegate}}
{{/jdk8}}
}
{{/operations}}

View File

@@ -2,13 +2,33 @@ package {{package}};
{{#imports}}import {{import}};
{{/imports}}
import io.swagger.annotations.*;{{#jdk8}}
import org.springframework.http.HttpStatus;{{/jdk8}}
{{#jdk8}}
import com.fasterxml.jackson.databind.ObjectMapper;
{{/jdk8}}
import io.swagger.annotations.*;
{{#jdk8}}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
{{/jdk8}}
import org.springframework.http.ResponseEntity;
import org.springframework.web.multipart.MultipartFile;
{{#jdk8}}
import java.io.IOException;
{{/jdk8}}
{{#jdk8}}
import javax.servlet.http.HttpServletRequest;
{{/jdk8}}
import java.util.List;
{{#jdk8}}
import java.util.Optional;
{{/jdk8}}
{{^jdk8}}
{{#useOptional}}
import java.util.Optional;
{{/useOptional}}
{{/jdk8}}
{{#async}}
import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture{{/jdk8}};
{{/async}}
@@ -16,11 +36,26 @@ import java.util.concurrent.{{^jdk8}}Callable{{/jdk8}}{{#jdk8}}CompletableFuture
{{#operations}}
/**
* A delegate to be called by the {@link {{classname}}Controller}}.
* Should be implemented as a controller but without the {@link org.springframework.stereotype.Controller} annotation.
* Instead, use spring to autowire this class into the {@link {{classname}}Controller}.
* Implement this interface with a {@link org.springframework.stereotype.Service} annotated class.
*/
{{>generatedAnnotation}}
public interface {{classname}}Delegate {
{{#jdk8}}
Logger log = LoggerFactory.getLogger({{classname}}.class);
default Optional<ObjectMapper> getObjectMapper() {
return Optional.empty();
}
default Optional<HttpServletRequest> getRequest() {
return Optional.empty();
}
default Optional<String> getAcceptHeader() {
return getRequest().map(r -> r.getHeader("Accept"));
}
{{/jdk8}}
{{#operation}}
/**
@@ -28,8 +63,21 @@ public interface {{classname}}Delegate {
*/
{{#jdk8}}default {{/jdk8}}{{#responseWrapper}}{{.}}<{{/responseWrapper}}ResponseEntity<{{>returnTypes}}>{{#responseWrapper}}>{{/responseWrapper}} {{operationId}}({{#allParams}}{{^isFile}}{{{dataType}}}{{/isFile}}{{#isFile}}MultipartFile{{/isFile}} {{paramName}}{{#hasMore}},
{{/hasMore}}{{/allParams}}){{^jdk8}};{{/jdk8}}{{#jdk8}} {
// do some magic!
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<{{>returnTypes}}>(HttpStatus.OK){{#async}}){{/async}};
if(getObjectMapper().isPresent() && getAcceptHeader().isPresent()) {
{{#examples}}
if (getAcceptHeader().get().contains("{{{contentType}}}")) {
try {
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(getObjectMapper().get().readValue("{{#lambdaRemoveLineBreak}}{{#lambdaEscapeDoubleQuote}}{{{example}}}{{/lambdaEscapeDoubleQuote}}{{/lambdaRemoveLineBreak}}", {{>exampleReturnTypes}}.class), HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}};
} catch (IOException e) {
log.error("Couldn't serialize response for content type {{{contentType}}}", e);
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR){{#async}}){{/async}};
}
}
{{/examples}}
} else {
log.warn("ObjectMapper or HttpServletRequest not configured in default {{classname}} interface so no example is generated");
}
return {{#async}}CompletableFuture.completedFuture({{/async}}new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED){{#async}}){{/async}};
}{{/jdk8}}
{{/operation}}

View File

@@ -1,20 +1,20 @@
{{#pattern}} @Pattern(regexp="{{{pattern}}}"){{/pattern}}{{!
{{#pattern}}@Pattern(regexp="{{{pattern}}}") {{/pattern}}{{!
minLength && maxLength set
}}{{#minLength}}{{#maxLength}} @Size(min={{minLength}},max={{maxLength}}){{/maxLength}}{{/minLength}}{{!
}}{{#minLength}}{{#maxLength}}@Size(min={{minLength}},max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
minLength set, maxLength not
}}{{#minLength}}{{^maxLength}} @Size(min={{minLength}}){{/maxLength}}{{/minLength}}{{!
}}{{#minLength}}{{^maxLength}}@Size(min={{minLength}}) {{/maxLength}}{{/minLength}}{{!
minLength not set, maxLength set
}}{{^minLength}}{{#maxLength}} @Size(max={{maxLength}}){{/maxLength}}{{/minLength}}{{!
}}{{^minLength}}{{#maxLength}}@Size(max={{maxLength}}) {{/maxLength}}{{/minLength}}{{!
@Size: minItems && maxItems set
}}{{#minItems}}{{#maxItems}} @Size(min={{minItems}},max={{maxItems}}){{/maxItems}}{{/minItems}}{{!
}}{{#minItems}}{{#maxItems}}@Size(min={{minItems}},max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems set, maxItems not
}}{{#minItems}}{{^maxItems}} @Size(min={{minItems}}){{/maxItems}}{{/minItems}}{{!
}}{{#minItems}}{{^maxItems}}@Size(min={{minItems}}) {{/maxItems}}{{/minItems}}{{!
@Size: minItems not set && maxItems set
}}{{^minItems}}{{#maxItems}} @Size(max={{maxItems}}){{/maxItems}}{{/minItems}}{{!
}}{{^minItems}}{{#maxItems}}@Size(max={{maxItems}}) {{/maxItems}}{{/minItems}}{{!
check for integer or long / all others=decimal type with @Decimal*
isInteger set
}}{{#isInteger}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isInteger}}{{!
}}{{#isInteger}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isInteger}}{{!
isLong set
}}{{#isLong}}{{#minimum}} @Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}){{/maximum}}{{/isLong}}{{!
}}{{#isLong}}{{#minimum}}@Min({{minimum}}){{/minimum}}{{#maximum}} @Max({{maximum}}) {{/maximum}}{{/isLong}}{{!
Not Integer, not Long => we have a decimal value!
}}{{^isInteger}}{{^isLong}}{{#minimum}} @DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}"){{/maximum}}{{/isLong}}{{/isInteger}}
}}{{^isInteger}}{{^isLong}}{{#minimum}}@DecimalMin("{{minimum}}"){{/minimum}}{{#maximum}} @DecimalMax("{{maximum}}") {{/maximum}}{{/isLong}}{{/isInteger}}

View File

@@ -1 +1 @@
{{#required}} @NotNull{{/required}}{{>beanValidationCore}}
{{#required}}@NotNull {{/required}}{{>beanValidationCore}}