Skip to content

Commit

Permalink
Use required attribute from spring RequestBody annotation. Fixes #468
Browse files Browse the repository at this point in the history
  • Loading branch information
bnasslahsen committed Mar 3, 2020
1 parent 5c0a7b5 commit 97fdec3
Show file tree
Hide file tree
Showing 17 changed files with 454 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Content;
import io.swagger.v3.oas.models.media.MediaType;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import org.apache.commons.lang3.StringUtils;
import org.springdoc.core.customizers.OperationCustomizer;
import org.springdoc.core.customizers.ParameterCustomizer;
Expand Down Expand Up @@ -81,7 +84,7 @@ public abstract class AbstractRequestBuilder {
private static final List<Class> PARAM_TYPES_TO_IGNORE = new ArrayList<>();

// using string litterals to support both validation-api v1 and v2
private static final String[] ANNOTATIONS_FOR_REQUIRED = { NotNull.class.getName(), "javax.validation.constraints.NotBlank", "javax.validation.constraints.NotEmpty" };
private static final String[] ANNOTATIONS_FOR_REQUIRED = { NotNull.class.getName(), org.springframework.web.bind.annotation.RequestBody.class.getName(),"javax.validation.constraints.NotBlank", "javax.validation.constraints.NotEmpty" };

private static final String POSITIVE_OR_ZERO = "javax.validation.constraints.PositiveOrZero";

Expand Down Expand Up @@ -183,6 +186,7 @@ else if (!RequestMethod.GET.equals(requestMethod)) {
requestBodyInfo.setRequestBody(operation.getRequestBody());
requestBodyBuilder.calculateRequestBodyInfo(components, handlerMethod, methodAttributes, i,
parameterInfo, requestBodyInfo);
applyBeanValidatorAnnotations(requestBodyInfo.getRequestBody(), Arrays.asList(parameters[i].getAnnotations()));
}
customiseParameter(parameter, parameterInfo, handlerMethod);
}
Expand Down Expand Up @@ -349,54 +353,26 @@ private Parameter buildParam(String in, Components components, ParameterInfo par

private void applyBeanValidatorAnnotations(final Parameter parameter, final List<Annotation> annotations) {
Map<String, Annotation> annos = new HashMap<>();
if (annotations != null) {
if (annotations != null)
annotations.forEach(annotation -> annos.put(annotation.annotationType().getName(), annotation));
}

boolean annotationExists = Arrays.stream(ANNOTATIONS_FOR_REQUIRED).anyMatch(annos::containsKey);

if (annotationExists) {
if (annotationExists)
parameter.setRequired(true);
}

Schema<?> schema = parameter.getSchema();
applyValidationsToSchema(annos, schema);
}

if (annos.containsKey(Min.class.getName())) {
Min min = (Min) annos.get(Min.class.getName());
schema.setMinimum(BigDecimal.valueOf(min.value()));
}
if (annos.containsKey(Max.class.getName())) {
Max max = (Max) annos.get(Max.class.getName());
schema.setMaximum(BigDecimal.valueOf(max.value()));
}
calculateSize(annos, schema);
if (annos.containsKey(DecimalMin.class.getName())) {
DecimalMin min = (DecimalMin) annos.get(DecimalMin.class.getName());
if (min.inclusive()) {
schema.setMinimum(BigDecimal.valueOf(Double.parseDouble(min.value())));
}
else {
schema.setExclusiveMinimum(!min.inclusive());
}
}
if (annos.containsKey(DecimalMax.class.getName())) {
DecimalMax max = (DecimalMax) annos.get(DecimalMax.class.getName());
if (max.inclusive()) {
schema.setMaximum(BigDecimal.valueOf(Double.parseDouble(max.value())));
}
else {
schema.setExclusiveMaximum(!max.inclusive());
}
}
if (annos.containsKey(POSITIVE_OR_ZERO)) {
schema.setMinimum(BigDecimal.ZERO);
}
if (annos.containsKey(NEGATIVE_OR_ZERO)) {
schema.setMaximum(BigDecimal.ZERO);
}
if (annos.containsKey(Pattern.class.getName())) {
Pattern pattern = (Pattern) annos.get(Pattern.class.getName());
schema.setPattern(pattern.regexp());
private void applyBeanValidatorAnnotations(final RequestBody requestBody, final List<Annotation> annotations) {
Map<String, Annotation> annos = new HashMap<>();
if (annotations != null)
annotations.forEach(annotation -> annos.put(annotation.annotationType().getName(), annotation));
boolean annotationExists = Arrays.stream(ANNOTATIONS_FOR_REQUIRED).anyMatch(annos::containsKey);
if (annotationExists)
requestBody.setRequired(true);
Content content = requestBody.getContent();
for (MediaType mediaType : content.values()) {
Schema schema = mediaType.getSchema();
applyValidationsToSchema(annos, schema);
}
}

Expand Down Expand Up @@ -451,6 +427,46 @@ private Map<String, io.swagger.v3.oas.annotations.Parameter> getApiParameters(Me
return apiParametersMap;
}

private void applyValidationsToSchema(Map<String, Annotation> annos, Schema<?> schema) {
if (annos.containsKey(Min.class.getName())) {
Min min = (Min) annos.get(Min.class.getName());
schema.setMinimum(BigDecimal.valueOf(min.value()));
}
if (annos.containsKey(Max.class.getName())) {
Max max = (Max) annos.get(Max.class.getName());
schema.setMaximum(BigDecimal.valueOf(max.value()));
}
calculateSize(annos, schema);
if (annos.containsKey(DecimalMin.class.getName())) {
DecimalMin min = (DecimalMin) annos.get(DecimalMin.class.getName());
if (min.inclusive()) {
schema.setMinimum(BigDecimal.valueOf(Double.parseDouble(min.value())));
}
else {
schema.setExclusiveMinimum(!min.inclusive());
}
}
if (annos.containsKey(DecimalMax.class.getName())) {
DecimalMax max = (DecimalMax) annos.get(DecimalMax.class.getName());
if (max.inclusive()) {
schema.setMaximum(BigDecimal.valueOf(Double.parseDouble(max.value())));
}
else {
schema.setExclusiveMaximum(!max.inclusive());
}
}
if (annos.containsKey(POSITIVE_OR_ZERO)) {
schema.setMinimum(BigDecimal.ZERO);
}
if (annos.containsKey(NEGATIVE_OR_ZERO)) {
schema.setMaximum(BigDecimal.ZERO);
}
if (annos.containsKey(Pattern.class.getName())) {
Pattern pattern = (Pattern) annos.get(Pattern.class.getName());
schema.setPattern(pattern.regexp());
}
}

public static void addRequestWrapperToIgnore(Class<?>... classes) {
PARAM_TYPES_TO_IGNORE.addAll(Arrays.asList(classes));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
# */
#
spring.main.banner-mode:"off"
logging.level.root=OFF
logging.level.root=ERROR
logging.level.test.org.springdoc.api=ERROR
22 changes: 0 additions & 22 deletions springdoc-openapi-data-rest/src/test/resources/logback-test.xml

This file was deleted.

88 changes: 45 additions & 43 deletions springdoc-openapi-data-rest/src/test/resources/results/app4.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,111 +11,113 @@
}
],
"paths": {
"/employees": {
"/employees/{id}": {
"get": {
"tags": [
"employee-controller"
],
"operationId": "findAll",
"operationId": "findOne",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"responses": {
"200": {
"description": "default response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/CollectionModelEntityModelEmployee"
"$ref": "#/components/schemas/EntityModelEmployee"
}
}
}
}
}
},
"post": {
"put": {
"tags": [
"employee-controller"
],
"operationId": "newEmployee",
"operationId": "updateEmployee",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Employee"
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "default response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/EntityModelEmployee"
}
}
}
"description": "default response"
}
}
}
},
"/employees/{id}": {
"/employees": {
"get": {
"tags": [
"employee-controller"
],
"operationId": "findOne",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"operationId": "findAll",
"responses": {
"200": {
"description": "default response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/EntityModelEmployee"
"$ref": "#/components/schemas/CollectionModelEntityModelEmployee"
}
}
}
}
}
},
"put": {
"post": {
"tags": [
"employee-controller"
],
"operationId": "updateEmployee",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "integer",
"format": "int64"
}
}
],
"operationId": "newEmployee",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Employee"
}
}
}
},
"required": true
},
"responses": {
"200": {
"description": "default response"
"description": "default response",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/EntityModelEmployee"
}
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"$ref": "#/components/schemas/Person"
}
}
}
},
"required": true
},
"responses": {
"200": {
Expand Down Expand Up @@ -57,7 +58,8 @@
"$ref": "#/components/schemas/Person"
}
}
}
},
"required": true
},
"responses": {
"200": {
Expand Down
Loading

0 comments on commit 97fdec3

Please sign in to comment.