Skip to content

Commit cc96c71

Browse files
committedOct 8, 2024·
Swagger doesn't work after custom annotation replacing request parameters. Fixes #2752
1 parent 428702b commit cc96c71

File tree

5 files changed

+51
-37
lines changed

5 files changed

+51
-37
lines changed
 

Diff for: ‎springdoc-openapi-starter-common/src/main/java/org/springdoc/core/data/DataRestRequestService.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@
6565
import org.springframework.web.bind.annotation.RequestMethod;
6666
import org.springframework.web.method.HandlerMethod;
6767

68+
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
69+
6870
/**
6971
* The type Data rest request builder.
7072
*
@@ -164,7 +166,7 @@ public void buildCommonParameters(OpenAPI openAPI, RequestMethod requestMethod,
164166
ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder, parameterDoc);
165167
if (isParamToIgnore(methodParameter)) {
166168
if (PersistentEntityResource.class.equals(methodParameter.getParameterType())) {
167-
Schema<?> schema = SpringDocAnnotationsUtils.resolveSchemaFromType(domainType, openAPI.getComponents(), null, methodParameter.getParameterAnnotations(), openAPI.getSpecVersion());
169+
Schema<?> schema = SpringDocAnnotationsUtils.resolveSchemaFromType(domainType, openAPI.getComponents(), null, getParameterAnnotations(methodParameter), openAPI.getSpecVersion());
168170
parameterInfo.setParameterModel(new Parameter().schema(schema));
169171
}
170172
else if (methodParameter.getParameterAnnotation(BackendId.class) != null) {
@@ -223,7 +225,7 @@ private boolean isParamToIgnore(MethodParameter methodParameter) {
223225
*/
224226
private void addParameters(OpenAPI openAPI, RequestMethod requestMethod, MethodAttributes methodAttributes, Operation operation,
225227
MethodParameter methodParameter, ParameterInfo parameterInfo, Parameter parameter) {
226-
List<Annotation> parameterAnnotations = Arrays.asList(methodParameter.getParameterAnnotations());
228+
List<Annotation> parameterAnnotations = Arrays.asList(getParameterAnnotations(methodParameter));
227229
if (requestBuilder.isValidParameter(parameter)) {
228230
requestBuilder.applyBeanValidatorAnnotations(parameter, parameterAnnotations);
229231
operation.addParametersItem(parameter);

Diff for: ‎springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/AbstractRequestService.java

+2-32
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@
6363
import jakarta.validation.constraints.Min;
6464
import jakarta.validation.constraints.Pattern;
6565
import jakarta.validation.constraints.Size;
66-
import org.apache.commons.lang3.ArrayUtils;
6766
import org.apache.commons.lang3.StringUtils;
68-
import org.jetbrains.annotations.NotNull;
6967
import org.springdoc.core.customizers.ParameterCustomizer;
7068
import org.springdoc.core.discoverer.SpringDocParameterNameDiscoverer;
7169
import org.springdoc.core.extractor.DelegatingMethodParameter;
@@ -98,6 +96,7 @@
9896
import static org.springdoc.core.service.GenericParameterService.isFile;
9997
import static org.springdoc.core.utils.Constants.OPENAPI_ARRAY_TYPE;
10098
import static org.springdoc.core.utils.Constants.OPENAPI_STRING_TYPE;
99+
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
101100
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
102101

103102
/**
@@ -325,7 +324,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
325324
// Merge with the operation parameters
326325
parameter = GenericParameterService.mergeParameter(operationParameters, parameter);
327326

328-
List<Annotation> parameterAnnotations = getParameterAnnotations(methodParameter);
327+
List<Annotation> parameterAnnotations = List.of(getParameterAnnotations(methodParameter));
329328

330329
if (isValidParameter(parameter)) {
331330
// Add param javadoc
@@ -375,35 +374,6 @@ else if (!RequestMethod.GET.equals(requestMethod) || OpenApiVersion.OPENAPI_3_1.
375374
return operation;
376375
}
377376

378-
/**
379-
* Gets parameter annotations.
380-
*
381-
* @param methodParameter the method parameter
382-
* @return the parameter annotations
383-
*/
384-
@NotNull
385-
private static List<Annotation> getParameterAnnotations(MethodParameter methodParameter) {
386-
// Initialize the list for parameter annotations
387-
List<Annotation> parameterAnnotations = new ArrayList<>();
388-
// Add the parameter annotations (direct annotations)
389-
if (ArrayUtils.isNotEmpty(methodParameter.getParameterAnnotations())) {
390-
parameterAnnotations.addAll(Arrays.asList(methodParameter.getParameterAnnotations()));
391-
}
392-
// Separate list to store meta-annotations
393-
List<Annotation> metaAnnotationsList = new ArrayList<>();
394-
// Iterate over the direct annotations and collect meta-annotations
395-
for (Annotation parameterAnnotation : parameterAnnotations) {
396-
Annotation[] metaAnnotations = parameterAnnotation.annotationType().getAnnotations();
397-
398-
if (ArrayUtils.isNotEmpty(metaAnnotations)) {
399-
metaAnnotationsList.addAll(Arrays.asList(metaAnnotations));
400-
}
401-
}
402-
// Add all the collected meta-annotations to the main list
403-
parameterAnnotations.addAll(metaAnnotationsList);
404-
return parameterAnnotations;
405-
}
406-
407377
/**
408378
* Gets parameter linked hash map.
409379
*

Diff for: ‎springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericParameterService.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
import org.springframework.web.multipart.MultipartRequest;
8989

9090
import static org.springdoc.core.utils.Constants.DOT;
91+
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
9192

9293
/**
9394
* The type Generic parameter builder.
@@ -377,7 +378,7 @@ Schema calculateSchema(Components components, ParameterInfo parameterInfo, Reque
377378
type = springConvertedType;
378379
}
379380
}
380-
schemaN = SpringDocAnnotationsUtils.extractSchema(components, type, jsonView, methodParameter.getParameterAnnotations(), propertyResolverUtils.getSpecVersion());
381+
schemaN = SpringDocAnnotationsUtils.extractSchema(components, type, jsonView, getParameterAnnotations(methodParameter), propertyResolverUtils.getSpecVersion());
381382
}
382383
else
383384
schemaN = parameterInfo.getParameterModel().getSchema();

Diff for: ‎springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/GenericResponseService.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.extractSchema;
9595
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.getContent;
9696
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.mergeSchema;
97+
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
9798

9899
/**
99100
* The type Generic response builder.
@@ -518,7 +519,7 @@ public Set<io.swagger.v3.oas.annotations.responses.ApiResponse> getApiResponses(
518519
*/
519520
private Content buildContent(Components components, MethodParameter methodParameter, String[] methodProduces, JsonView jsonView) {
520521
Type returnType = GenericTypeResolver.resolveType(methodParameter.getGenericParameterType(), methodParameter.getContainingClass());
521-
return buildContent(components, methodParameter.getParameterAnnotations(), methodProduces, jsonView, returnType);
522+
return buildContent(components, getParameterAnnotations(methodParameter), methodProduces, jsonView, returnType);
522523
}
523524

524525
/**
@@ -611,7 +612,7 @@ else if (CollectionUtils.isEmpty(apiResponse.getContent()))
611612
Content existingContent = apiResponse.getContent();
612613
Type type = GenericTypeResolver.resolveType( methodParameter.getGenericParameterType(), methodParameter.getContainingClass());
613614
Schema<?> schemaN = calculateSchema(components, type,
614-
methodAttributes.getJsonViewAnnotation(), methodParameter.getParameterAnnotations());
615+
methodAttributes.getJsonViewAnnotation(), getParameterAnnotations(methodParameter));
615616
if (schemaN != null && ArrayUtils.isNotEmpty(methodAttributes.getMethodProduces()))
616617
Arrays.stream(methodAttributes.getMethodProduces()).forEach(mediaTypeStr -> mergeSchema(existingContent, schemaN, mediaTypeStr));
617618
}

Diff for: ‎springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocUtils.java

+40
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@
2727
package org.springdoc.core.utils;
2828

2929
import java.lang.annotation.Annotation;
30+
import java.util.ArrayList;
31+
import java.util.List;
3032
import java.util.function.Predicate;
3133

3234
import io.swagger.v3.oas.models.media.Schema;
35+
import org.apache.commons.lang3.ArrayUtils;
3336
import org.apache.commons.lang3.StringUtils;
37+
import org.jetbrains.annotations.NotNull;
3438
import org.springdoc.api.AbstractOpenApiResource;
3539
import org.springdoc.core.converters.AdditionalModelsConverter;
3640
import org.springdoc.core.converters.ConverterUtils;
@@ -41,6 +45,8 @@
4145
import org.springdoc.core.service.GenericParameterService;
4246
import org.springdoc.core.service.GenericResponseService;
4347

48+
import org.springframework.core.MethodParameter;
49+
4450
/**
4551
* The type Spring doc utils.
4652
*
@@ -402,5 +408,39 @@ public SpringDocUtils addParentType(String ...parentTypes) {
402408
PolymorphicModelConverter.addParentType(parentTypes);
403409
return this;
404410
}
411+
412+
/**
413+
* Gets parameter annotations.
414+
*
415+
* @param methodParameter the method parameter
416+
* @return the parameter annotations
417+
*/
418+
@NotNull
419+
public static Annotation[] getParameterAnnotations(MethodParameter methodParameter) {
420+
// Get the parameter annotations directly as an array
421+
Annotation[] annotations = methodParameter.getParameterAnnotations();
422+
// Return early if no annotations are found, avoiding unnecessary processing
423+
if (ArrayUtils.isEmpty(annotations)) {
424+
return new Annotation[0];
425+
}
426+
// Create a list that can contain both parameter and meta-annotations
427+
List<Annotation> resultAnnotations = new ArrayList<>(annotations.length);
428+
429+
// Add all direct annotations
430+
resultAnnotations.addAll(List.of(annotations));
431+
432+
// Process each direct annotation to collect its meta-annotations
433+
for (Annotation annotation : annotations) {
434+
// Fetch meta-annotations
435+
Annotation[] metaAnnotations = annotation.annotationType().getAnnotations();
436+
437+
// Only add meta-annotations if they exist
438+
if (ArrayUtils.isNotEmpty(metaAnnotations)) {
439+
resultAnnotations.addAll(List.of(metaAnnotations));
440+
}
441+
}
442+
// Convert the list to an array and return
443+
return resultAnnotations.toArray(new Annotation[0]);
444+
}
405445
}
406446

0 commit comments

Comments
 (0)
Please sign in to comment.