diff --git a/src/main/java/io/sinistral/proteus/server/tools/oas/Reader.java b/src/main/java/io/sinistral/proteus/server/tools/oas/Reader.java index 6f41db2..727da5a 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/oas/Reader.java +++ b/src/main/java/io/sinistral/proteus/server/tools/oas/Reader.java @@ -592,6 +592,8 @@ else if (StringUtils.isBlank(httpMethod) && subResource != null) // LOGGER.warn(i + " Arrays.asList(paramAnnotations[i]): " + Arrays.asList(paramAnnotations[i])); + boolean isOptional = isOptionalType(TypeFactory.defaultInstance().constructType(paramType)); + ResolvedParameter resolvedParameter = getParameters( paramType, Arrays.asList(paramAnnotations[i]), operation, classConsumes, methodConsumes, jsonViewAnnotation); @@ -603,7 +605,7 @@ else if (StringUtils.isBlank(httpMethod) && subResource != null) } if (resolvedParameter.requestBody != null) { -// LOGGER.warn("Found request body param for " + paramType); +// LOGGER.warn("Found request body param for " + paramType + " isOptional: " + isOptional); processRequestBody( resolvedParameter.requestBody, operation, @@ -616,10 +618,11 @@ else if (StringUtils.isBlank(httpMethod) && subResource != null) } else if (resolvedParameter.formParameter != null) { -// LOGGER.warn("Found request form param for " + paramType); +// LOGGER.warn("Found request form param for " + paramType + " isOptional: " + isOptional); // collect params to use together as request // Body + resolvedParameter.formParameter.setRequired(!isOptional); formParameters.add(resolvedParameter.formParameter); } } @@ -635,6 +638,8 @@ else if (resolvedParameter.formParameter != null) io.swagger.v3.oas.annotations.Parameter paramAnnotation = AnnotationsUtils .getAnnotation(io.swagger.v3.oas.annotations.Parameter.class, paramAnnotations[i]); Type paramType = ParameterProcessor.getParameterType(paramAnnotation, true); + + if (paramType == null) { paramType = type; @@ -647,6 +652,8 @@ else if (resolvedParameter.formParameter != null) } } + boolean isOptional = isOptionalType(TypeFactory.defaultInstance().constructType(paramType)); + ResolvedParameter resolvedParameter = getParameters( paramType, Arrays.asList(paramAnnotations[i]), operation, classConsumes, methodConsumes, jsonViewAnnotation); @@ -656,6 +663,8 @@ else if (resolvedParameter.formParameter != null) } if (resolvedParameter.requestBody != null) { +// LOGGER.warn("Found annotated param request body param for " + paramType + " isOptional: " + isOptional); + processRequestBody( resolvedParameter.requestBody, operation, @@ -668,6 +677,8 @@ else if (resolvedParameter.formParameter != null) } else if (resolvedParameter.formParameter != null) { +// LOGGER.warn("Found annotated param request form param for " + paramType + " isOptional: " + isOptional); + // collect params to use together as request // Body formParameters.add(resolvedParameter.formParameter); @@ -679,11 +690,23 @@ else if (resolvedParameter.formParameter != null) if (formParameters.size() > 0) { Schema mergedSchema = new ObjectSchema(); + + boolean isRequired = false; + for (Parameter formParam : formParameters) - { + { + if(formParam.getRequired()) + { + isRequired = true; + } + mergedSchema.addProperties(formParam.getName(), formParam.getSchema()); } + Parameter merged = new Parameter().schema(mergedSchema); + + merged.setRequired(isRequired); + processRequestBody( merged, operation, @@ -814,7 +837,7 @@ public static Annotation[][] getParameterAnnotations(Method method) Annotation[][] methodAnnotations = method.getParameterAnnotations(); - LOGGER.warn("methodAnnotations length at start: " + methodAnnotations.length); +// LOGGER.warn("methodAnnotations length at start: " + methodAnnotations.length); java.lang.reflect.Parameter[] params = method.getParameters(); @@ -934,9 +957,9 @@ protected void processRequestBody( Parameter requestBodyParameter, Operation ope JsonView jsonViewAnnotation) { - boolean isOptional = false; + boolean isOptional = !(requestBodyParameter.getRequired() != null ? requestBodyParameter.getRequired() : true); - if(type != null) + if(type != null && !isOptional) { JavaType classType = TypeFactory.defaultInstance().constructType(type); diff --git a/src/main/java/io/sinistral/proteus/server/tools/oas/ServerModelResolver.java b/src/main/java/io/sinistral/proteus/server/tools/oas/ServerModelResolver.java index bc363f0..f0333f9 100644 --- a/src/main/java/io/sinistral/proteus/server/tools/oas/ServerModelResolver.java +++ b/src/main/java/io/sinistral/proteus/server/tools/oas/ServerModelResolver.java @@ -9,6 +9,7 @@ import java.nio.ByteBuffer; import java.util.Iterator; import java.util.List; +import java.util.Optional; import java.util.concurrent.CompletableFuture; import com.fasterxml.jackson.databind.BeanDescription; @@ -65,6 +66,8 @@ public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context if (rawClass != null && !resolvedType.isPrimitive()) { + //log.debug("resolvedType in " + resolvedType); + if (rawClass.isAssignableFrom(ServerResponse.class)) { resolvedType = classType.containedType(0); @@ -75,44 +78,61 @@ else if (rawClass.isAssignableFrom(CompletableFuture.class)) if (futureCls.isAssignableFrom(ServerResponse.class)) { - log.debug("class is assignable from ServerResponse"); + //log.debug("class is assignable from ServerResponse"); final JavaType futureType = TypeFactory.defaultInstance().constructType(classType.containedType(0)); resolvedType = futureType.containedType(0); } else { - log.debug("class is NOT assignable from ServerResponse"); + //log.debug("class is NOT assignable from ServerResponse"); resolvedType = classType.containedType(0); } } if(resolvedType != null) { - if (resolvedType.getTypeName().contains("ByteBuffer")) + + + if (resolvedType.getTypeName().contains("java.lang.Void")) { - resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.lang.Void.class.getName()); } - - if (resolvedType.getTypeName().contains("java.nio.file.Path")) + else if(resolvedType.getTypeName().contains("Optional")) { - resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + if (resolvedType.getTypeName().contains("java.nio.file.Path")) + { + resolvedType = TypeFactory.defaultInstance().constructParametricType(Optional.class, File.class); + } + + if (resolvedType.getTypeName().contains("ByteBuffer")) + { + resolvedType = TypeFactory.defaultInstance().constructParametricType(Optional.class, File.class); + } + } + else + { + if (resolvedType.getTypeName().contains("java.nio.file.Path")) + { + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + } + + if (resolvedType.getTypeName().contains("ByteBuffer")) + { + resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.io.File.class.getName()); + } + } - -// if (resolvedType.getTypeName().contains("java.lang.Void")) -// { -// resolvedType = TypeFactory.defaultInstance().constructFromCanonical(java.lang.Void.class.getName()); -// } annotatedType.setType(resolvedType); - log.debug("resolvedType out " + resolvedType); + //log.debug("resolvedType out " + resolvedType); } } try { - log.info("Processing " + annotatedType + " " + classType + " " + annotatedType.getName()); + //log.info("Processing " + annotatedType + " " + classType + " " + annotatedType.getName()); return super.resolve(annotatedType, context, next); diff --git a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java index a619b38..385d920 100644 --- a/src/test/java/io/sinistral/proteus/test/controllers/Tests.java +++ b/src/test/java/io/sinistral/proteus/test/controllers/Tests.java @@ -213,8 +213,8 @@ public ServerResponse responseUploadOptionalFilePath(ServerRequest r @POST @Path("/response/json/echo") - @Produces(MediaType.APPLICATION_OCTET_STREAM) - @Consumes("*/*") + @Produces(MediaType.APPLICATION_JSON) + @Consumes(MediaType.MULTIPART_FORM_DATA) @ApiOperation(value = "Echo json endpoint", httpMethod = "POST" ) public ServerResponse responseEchoJson(ServerRequest request, @FormParam("user") User user ) throws Exception {