Skip to content

Commit

Permalink
Javadoc description of the @RequestPart param of multipart/form-data …
Browse files Browse the repository at this point in the history
…goes to requestBody description, not to parameter description. Fixes #1923
  • Loading branch information
bnasslahsen committed Nov 16, 2022
1 parent 8b01535 commit 42b76f9
Show file tree
Hide file tree
Showing 17 changed files with 300 additions and 265 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -271,16 +271,15 @@ ModelConverterRegistrar modelConverterRegistrar(Optional<List<ModelConverter>> m
* @param requestBodyService the request body service
* @param securityParser the security parser
* @param propertyResolverUtils the property resolver utils
* @param javadocProvider the javadoc provider
* @return the operation service
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
OperationService operationBuilder(GenericParameterService parameterBuilder, RequestBodyService requestBodyService,
SecurityService securityParser, PropertyResolverUtils propertyResolverUtils, Optional<JavadocProvider> javadocProvider) {
SecurityService securityParser, PropertyResolverUtils propertyResolverUtils) {
return new OperationService(parameterBuilder, requestBodyService,
securityParser, propertyResolverUtils, javadocProvider);
securityParser, propertyResolverUtils);
}

/**
Expand Down Expand Up @@ -341,16 +340,17 @@ ReturnTypeParser genericReturnTypeParser() {
* @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
* @param optionalWebConversionServiceProvider the optional web conversion service provider
* @param objectMapperProvider the object mapper provider
* @param javadocProvider the javadoc provider
* @return the generic parameter builder
*/
@Bean
@ConditionalOnMissingBean
@Lazy(false)
GenericParameterService parameterBuilder(PropertyResolverUtils propertyResolverUtils,
Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer,
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider) {
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider,Optional<JavadocProvider> javadocProvider) {
return new GenericParameterService(propertyResolverUtils, optionalDelegatingMethodParameterCustomizer,
optionalWebConversionServiceProvider, objectMapperProvider);
optionalWebConversionServiceProvider, objectMapperProvider,javadocProvider);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
package org.springdoc.core.service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
Expand Down Expand Up @@ -64,7 +63,6 @@
import jakarta.validation.constraints.Size;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springdoc.core.customizers.ParameterCustomizer;
import org.springdoc.core.extractor.DelegatingMethodParameter;
import org.springdoc.core.models.MethodAttributes;
Expand Down Expand Up @@ -95,7 +93,6 @@
import org.springframework.web.util.UriComponentsBuilder;

import static org.springdoc.core.converters.SchemaPropertyDeprecatingConverter.containsDeprecatedAnnotation;
import static org.springdoc.core.utils.Constants.DOT;
import static org.springdoc.core.utils.Constants.OPENAPI_ARRAY_TYPE;
import static org.springdoc.core.utils.Constants.OPENAPI_STRING_TYPE;

Expand Down Expand Up @@ -264,7 +261,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
Map<ParameterId, io.swagger.v3.oas.annotations.Parameter> parametersDocMap = getApiParameters(handlerMethod.getMethod());
Components components = openAPI.getComponents();

JavadocProvider javadocProvider = operationService.getJavadocProvider();
JavadocProvider javadocProvider = parameterBuilder.getJavadocProvider();

for (MethodParameter methodParameter : parameters) {
// check if query param
Expand Down Expand Up @@ -304,7 +301,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
if (isValidParameter(parameter)) {
// Add param javadoc
if (StringUtils.isBlank(parameter.getDescription()) && javadocProvider != null) {
String paramJavadocDescription = getParamJavadoc(javadocProvider, methodParameter, pName);
String paramJavadocDescription = parameterBuilder.getParamJavadoc(javadocProvider, methodParameter);
if (!StringUtils.isBlank(paramJavadocDescription)) {
parameter.setDescription(paramJavadocDescription);
}
Expand All @@ -316,13 +313,6 @@ else if (!RequestMethod.GET.equals(requestMethod) || OpenApiVersion.OPENAPI_3_1.
requestBodyInfo.setRequestBody(operation.getRequestBody());
requestBodyService.calculateRequestBodyInfo(components, methodAttributes,
parameterInfo, requestBodyInfo);
// Add requestBody javadoc
if (StringUtils.isBlank(requestBodyInfo.getRequestBody().getDescription()) && javadocProvider != null) {
String paramJavadocDescription = getParamJavadoc(javadocProvider, methodParameter, pName);
if (!StringUtils.isBlank(paramJavadocDescription)) {
requestBodyInfo.getRequestBody().setDescription(paramJavadocDescription);
}
}
applyBeanValidatorAnnotations(requestBodyInfo.getRequestBody(), parameterAnnotations, methodParameter.isOptional());
}
customiseParameter(parameter, parameterInfo, operationParameters);
Expand Down Expand Up @@ -741,31 +731,6 @@ private boolean isRequestBodyParam(RequestMethod requestMethod, ParameterInfo pa
|| (!ClassUtils.isPrimitiveOrWrapper(methodParameter.getParameterType()) && (!ArrayUtils.isEmpty(methodParameter.getParameterAnnotations()))));
}

/**
* Gets param javadoc.
*
* @param javadocProvider the javadoc provider
* @param methodParameter the method parameter
* @param pName the p name
* @return the param javadoc
*/
private String getParamJavadoc(JavadocProvider javadocProvider, MethodParameter methodParameter, String pName) {
DelegatingMethodParameter delegatingMethodParameter = (DelegatingMethodParameter) methodParameter;
final String paramJavadocDescription;
if (delegatingMethodParameter.isParameterObject()) {
String fieldName;
if (StringUtils.isNotEmpty(pName) && pName.contains(DOT))
fieldName = StringUtils.substringAfterLast(pName, DOT);
else
fieldName = pName;
Field field = FieldUtils.getDeclaredField(((DelegatingMethodParameter) methodParameter).getExecutable().getDeclaringClass(), fieldName, true);
paramJavadocDescription = javadocProvider.getFieldJavadoc(field);
}
else
paramJavadocDescription = javadocProvider.getParamJavadoc(methodParameter.getMethod(), pName);
return paramJavadocDescription;
}

/**
* Is default flat param object boolean.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
Expand All @@ -36,6 +37,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

import com.fasterxml.jackson.annotation.JsonView;
Expand All @@ -55,13 +57,16 @@
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.parameters.Parameter;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
import org.springdoc.core.extractor.DelegatingMethodParameter;
import org.springdoc.core.extractor.MethodParameterPojoExtractor;
import org.springdoc.core.models.ParameterInfo;
import org.springdoc.core.models.RequestBodyInfo;
import org.springdoc.core.parsers.ReturnTypeParser;
import org.springdoc.core.providers.JavadocProvider;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.providers.WebConversionServiceProvider;
import org.springdoc.core.utils.Constants;
Expand All @@ -73,11 +78,14 @@
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.core.MethodParameter;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.io.Resource;
import org.springframework.web.context.request.RequestScope;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartRequest;

import static org.springdoc.core.utils.Constants.DOT;

/**
* The type Generic parameter builder.
* @author bnasslahsen, coutin
Expand Down Expand Up @@ -131,21 +139,28 @@ public class GenericParameterService {
*/
private final ObjectMapperProvider objectMapperProvider;

/**
* The javadoc provider.
*/
private final Optional<JavadocProvider> javadocProviderOptional;

/**
* Instantiates a new Generic parameter builder.
* @param propertyResolverUtils the property resolver utils
* @param optionalDelegatingMethodParameterCustomizer the optional delegating method parameter customizer
* @param optionalWebConversionServiceProvider the optional web conversion service provider
* @param objectMapperProvider the object mapper provider
* @param javadocProviderOptional the javadoc provider
*/
public GenericParameterService(PropertyResolverUtils propertyResolverUtils, Optional<DelegatingMethodParameterCustomizer> optionalDelegatingMethodParameterCustomizer,
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider) {
Optional<WebConversionServiceProvider> optionalWebConversionServiceProvider, ObjectMapperProvider objectMapperProvider, Optional<JavadocProvider> javadocProviderOptional) {
this.propertyResolverUtils = propertyResolverUtils;
this.optionalDelegatingMethodParameterCustomizer = optionalDelegatingMethodParameterCustomizer;
this.optionalWebConversionServiceProvider = optionalWebConversionServiceProvider;
this.configurableBeanFactory = propertyResolverUtils.getFactory();
this.expressionContext = (configurableBeanFactory != null ? new BeanExpressionContext(configurableBeanFactory, new RequestScope()) : null);
this.objectMapperProvider = objectMapperProvider;
this.javadocProviderOptional = javadocProviderOptional;
}

/**
Expand Down Expand Up @@ -359,6 +374,16 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque

if (requestBodyInfo != null) {
schemaN = calculateRequestBodySchema(components, parameterInfo, requestBodyInfo, schemaN, paramName);
JavadocProvider javadocProvider = javadocProviderOptional.orElse(null);
if (schemaN != null && javadocProvider != null && !isRequestBodyPresent(parameterInfo)) {
String paramJavadocDescription = getParamJavadoc(javadocProvider, methodParameter);
if (schemaN.getProperties() != null && schemaN.getProperties().containsKey(parameterInfo.getpName())) {
Map<String, Schema> properties = schemaN.getProperties();
if (!StringUtils.isBlank(paramJavadocDescription) && StringUtils.isBlank(properties.get(parameterInfo.getpName()).getDescription())) {
properties.get(parameterInfo.getpName()).setDescription(paramJavadocDescription);
}
}
}
}

return schemaN;
Expand Down Expand Up @@ -666,4 +691,48 @@ public String ref() {
}
};
}

/**
* Gets javadoc provider.
*
* @return the javadoc provider
*/
public JavadocProvider getJavadocProvider() {
return javadocProviderOptional.orElse(null);
}

/**
* Is request body present boolean.
*
* @param parameterInfo the parameter info
* @return the boolean
*/
public boolean isRequestBodyPresent(ParameterInfo parameterInfo) {
return parameterInfo.getMethodParameter().getParameterAnnotation(io.swagger.v3.oas.annotations.parameters.RequestBody.class) != null
|| parameterInfo.getMethodParameter().getParameterAnnotation(org.springframework.web.bind.annotation.RequestBody.class) != null
|| AnnotatedElementUtils.findMergedAnnotation(Objects.requireNonNull(parameterInfo.getMethodParameter().getMethod()), io.swagger.v3.oas.annotations.parameters.RequestBody.class) != null;
}

/**
* Gets param javadoc.
*
* @param javadocProvider the javadoc provider
* @param methodParameter the method parameter
* @return the param javadoc
*/
String getParamJavadoc(JavadocProvider javadocProvider, MethodParameter methodParameter) {
String pName = methodParameter.getParameterName();
DelegatingMethodParameter delegatingMethodParameter = (DelegatingMethodParameter) methodParameter;
final String paramJavadocDescription;
if (delegatingMethodParameter.isParameterObject()) {
String fieldName; if (StringUtils.isNotEmpty(pName) && pName.contains(DOT))
fieldName = StringUtils.substringAfterLast(pName, DOT);
else fieldName = pName;
Field field = FieldUtils.getDeclaredField(((DelegatingMethodParameter) methodParameter).getExecutable().getDeclaringClass(), fieldName, true);
paramJavadocDescription = javadocProvider.getFieldJavadoc(field);
}
else
paramJavadocDescription = javadocProvider.getParamJavadoc(methodParameter.getMethod(), pName);
return paramJavadocDescription;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,27 +94,20 @@ public class OperationService {
*/
private final PropertyResolverUtils propertyResolverUtils;

/**
* The javadoc provider.
*/
private final Optional<JavadocProvider> javadocProvider;

/**
* Instantiates a new Operation builder.
* @param parameterBuilder the parameter builder
* @param requestBodyService the request body builder
* @param securityParser the security parser
* @param propertyResolverUtils the property resolver utils
* @param javadocProvider the javadoc provider
*/
public OperationService(GenericParameterService parameterBuilder, RequestBodyService requestBodyService,
SecurityService securityParser, PropertyResolverUtils propertyResolverUtils, Optional<JavadocProvider> javadocProvider) {
SecurityService securityParser, PropertyResolverUtils propertyResolverUtils) {
super();
this.parameterBuilder = parameterBuilder;
this.requestBodyService = requestBodyService;
this.securityParser = securityParser;
this.propertyResolverUtils = propertyResolverUtils;
this.javadocProvider = javadocProvider;
}

/**
Expand Down Expand Up @@ -628,12 +621,12 @@ public Operation mergeOperation(Operation operation, Operation operationModel) {
return operation;
}

/**
/**
* Gets javadoc provider.
*
* @return the javadoc provider
*/
public JavadocProvider getJavadocProvider() {
return javadocProvider.orElse(null);
return parameterBuilder.getJavadocProvider();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,16 @@ else if (!methodAttributes.isWithResponseBodySchemaDoc()) {
methodAttributes.getJsonViewAnnotationForRequestBody());
mergeContent(requestBody, methodAttributes, schema);
}


// Add requestBody javadoc
if (StringUtils.isBlank(requestBody.getDescription()) && parameterBuilder.getJavadocProvider() != null
&& parameterBuilder.isRequestBodyPresent(parameterInfo)) {
String paramJavadocDescription = parameterBuilder.getParamJavadoc(parameterBuilder.getJavadocProvider(), parameterInfo.getMethodParameter());
if (!StringUtils.isBlank(paramJavadocDescription)) {
requestBodyInfo.getRequestBody().setDescription(paramJavadocDescription);
}
}
return requestBody;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@

import static org.springdoc.core.utils.Constants.CLASSPATH_RESOURCE_LOCATION;
import static org.springdoc.core.utils.Constants.DEFAULT_WEB_JARS_PREFIX_URL;
import static org.springdoc.core.utils.Constants.SWAGGER_INITIALIZER_JS;
import static org.springdoc.core.utils.Constants.SWAGGER_UI_PREFIX;
import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
import static org.springdoc.core.utils.Constants.SWAGGER_INITIALIZER_JS;
/**
* The type Swagger web mvc configurer.
* @author bnasslahsen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
"description": "Post my request body string.",
"operationId": "postMyRequestBody",
"requestBody": {
"description": "the body",
"content": {
"multipart/form-data": {
"schema": {
Expand All @@ -41,6 +40,7 @@
},
"file": {
"type": "string",
"description": "the file",
"format": "binary"
}
}
Expand Down Expand Up @@ -87,4 +87,4 @@
}
}
}
}
}

0 comments on commit 42b76f9

Please sign in to comment.