Skip to content

Commit 01c5392

Browse files
author
bnasslahsen
committed
Merge branch 'mvh77-feat/370_support_completion_stage_return_type'
2 parents 4fad109 + 0c57462 commit 01c5392

File tree

22 files changed

+609
-376
lines changed

22 files changed

+609
-376
lines changed

springdoc-openapi-common/src/main/java/org/springdoc/api/AbstractOpenApiResource.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
import org.slf4j.Logger;
4646
import org.slf4j.LoggerFactory;
4747
import org.springdoc.core.AbstractRequestBuilder;
48-
import org.springdoc.core.AbstractResponseBuilder;
48+
import org.springdoc.core.GenericResponseBuilder;
4949
import org.springdoc.core.MethodAttributes;
5050
import org.springdoc.core.OpenAPIBuilder;
5151
import org.springdoc.core.OperationBuilder;
@@ -72,7 +72,7 @@ public abstract class AbstractOpenApiResource {
7272

7373
private final AbstractRequestBuilder requestBuilder;
7474

75-
private final AbstractResponseBuilder responseBuilder;
75+
private final GenericResponseBuilder responseBuilder;
7676

7777
private final OperationBuilder operationParser;
7878

@@ -92,7 +92,7 @@ public abstract class AbstractOpenApiResource {
9292
private boolean cacheDisabled;
9393

9494
protected AbstractOpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
95-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
95+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
9696
Optional<List<OpenApiCustomiser>> openApiCustomisers) {
9797
super();
9898
this.openAPIBuilder = openAPIBuilder;
@@ -103,7 +103,7 @@ protected AbstractOpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequest
103103
}
104104

105105
protected AbstractOpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
106-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
106+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
107107
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch, List<String> packagesToScan, boolean cacheDisabled) {
108108
super();
109109
this.openAPIBuilder = openAPIBuilder;
@@ -224,7 +224,7 @@ protected void calculatePath(OpenAPIBuilder openAPIBuilder, HandlerMethod handle
224224
.getRepeatableAnnotations(method, io.swagger.v3.oas.annotations.callbacks.Callback.class);
225225

226226
// callbacks
227-
if (apiCallbacks != null) {
227+
if (!CollectionUtils.isEmpty(apiCallbacks)) {
228228
operationParser.buildCallbacks(apiCallbacks, components, openAPI, methodAttributes)
229229
.ifPresent(operation::setCallbacks);
230230
}

springdoc-openapi-common/src/main/java/org/springdoc/core/AbstractResponseBuilder.java renamed to springdoc-openapi-common/src/main/java/org/springdoc/core/GenericResponseBuilder.java

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@
5858
import static org.springdoc.core.Constants.DEFAULT_DESCRIPTION;
5959

6060
@SuppressWarnings("rawtypes")
61-
public abstract class AbstractResponseBuilder {
61+
public class GenericResponseBuilder {
6262

6363
private final Map<String, ApiResponse> genericMapResponse = new LinkedHashMap<>();
6464

6565
private final OperationBuilder operationBuilder;
6666

6767
private final List<ReturnTypeParser> returnTypeParsers;
6868

69-
protected AbstractResponseBuilder(OperationBuilder operationBuilder, List<ReturnTypeParser> returnTypeParsers) {
69+
protected GenericResponseBuilder(OperationBuilder operationBuilder, List<ReturnTypeParser> returnTypeParsers) {
7070
super();
7171
this.operationBuilder = operationBuilder;
7272
this.returnTypeParsers = returnTypeParsers;
@@ -104,23 +104,6 @@ public void buildGenericResponse(Components components, Map<String, Object> find
104104
}
105105
}
106106

107-
protected abstract Schema calculateSchemaFromParameterizedType(Components components, ParameterizedType returnType,
108-
JsonView jsonView);
109-
110-
protected Schema calculateSchemaParameterizedType(Components components, ParameterizedType parameterizedType,
111-
JsonView jsonView) {
112-
Schema schemaN = null;
113-
Type type = parameterizedType.getActualTypeArguments()[0];
114-
if ((type instanceof Class || type instanceof ParameterizedType) && !Void.class.equals(type)) {
115-
schemaN = calculateSchema(components, parameterizedType, jsonView);
116-
}
117-
else if (Void.class.equals(type)) {
118-
// if void, no content
119-
schemaN = AnnotationsUtils.resolveSchemaFromType(String.class, null, jsonView);
120-
}
121-
return schemaN;
122-
}
123-
124107
private List<Method> getMethods(Map<String, Object> findControllerAdvice) {
125108
List<Method> methods = new ArrayList<>();
126109
for (Map.Entry<String, Object> entry : findControllerAdvice.entrySet()) {
@@ -275,9 +258,6 @@ private Schema<?> calculateSchema(Components components, Type returnType, JsonVi
275258
// if void, no content
276259
return null;
277260
}
278-
if (returnType instanceof ParameterizedType) {
279-
schemaN = calculateSchemaFromParameterizedType(components, (ParameterizedType) returnType, jsonView);
280-
}
281261
else if (ResponseEntity.class.getName().equals(returnType.getTypeName()) || HttpEntity.class.getName().equals(returnType.getTypeName())) {
282262
schemaN = AnnotationsUtils.resolveSchemaFromType(String.class, null, jsonView);
283263
}
@@ -295,17 +275,6 @@ private void setContent(String[] methodProduces, Content content,
295275
Arrays.stream(methodProduces).forEach(mediaTypeStr -> content.addMediaType(mediaTypeStr, mediaType));
296276
}
297277

298-
private Schema calculateSchema(Components components, ParameterizedType parameterizedType, JsonView jsonView) {
299-
Schema schemaN;
300-
schemaN = SpringDocAnnotationsUtils.extractSchema(components, parameterizedType.getActualTypeArguments()[0],
301-
jsonView);
302-
if (schemaN.getType() == null) {
303-
schemaN = SpringDocAnnotationsUtils.extractSchema(components,
304-
parameterizedType.getActualTypeArguments()[0], jsonView);
305-
}
306-
return schemaN;
307-
}
308-
309278
private void buildApiResponses(Components components, Method method, ApiResponses apiResponsesOp,
310279
MethodAttributes methodAttributes, String httpCode, ApiResponse apiResponse, boolean isGeneric) {
311280
// No documentation
@@ -379,7 +348,15 @@ private String evaluateResponseStatus(Method method, Class<?> beanType, boolean
379348
}
380349

381350
private boolean isVoid(Type returnType) {
382-
return Void.TYPE.equals(returnType) || (returnType instanceof ParameterizedType
383-
&& Void.class.equals(((ParameterizedType) returnType).getActualTypeArguments()[0]));
351+
if (Void.TYPE.equals(returnType))
352+
return true;
353+
if (returnType instanceof ParameterizedType) {
354+
Type[] types = ((ParameterizedType) returnType).getActualTypeArguments();
355+
if(types !=null)
356+
return isVoid(types[0]);
357+
}
358+
if (Void.class.equals(returnType))
359+
return true;
360+
return false;
384361
}
385362
}

springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springdoc.core.converters.ModelConverterRegistrar;
2828
import org.springdoc.core.converters.ObjectNodeConverter;
2929
import org.springdoc.core.converters.PropertyCustomizingConverter;
30+
import org.springdoc.core.converters.ResponseSupportConverter;
3031
import org.springdoc.core.customizers.PropertyCustomizer;
3132

3233
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
@@ -63,6 +64,11 @@ PropertyCustomizingConverter propertyCustomizingConverter(Optional<List<Property
6364
return new PropertyCustomizingConverter(customizers);
6465
}
6566

67+
@Bean
68+
ResponseSupportConverter responseSupportConverter(){
69+
return new ResponseSupportConverter();
70+
}
71+
6672
@Bean
6773
IgnoredParameterAnnotationsDefault ignoredParameterAnnotationsDefault() {
6874
return new IgnoredParameterAnnotationsDefault();
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package org.springdoc.core.converters;
20+
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
import java.util.concurrent.Callable;
24+
import java.util.concurrent.CompletionStage;
25+
26+
import org.springframework.http.HttpEntity;
27+
import org.springframework.http.ResponseEntity;
28+
29+
public class ConverterUtils {
30+
31+
private static final List<Class<?>> RESULT_WRAPPERS_TO_IGNORE = new ArrayList<>();
32+
33+
static {
34+
RESULT_WRAPPERS_TO_IGNORE.add(Callable.class);
35+
RESULT_WRAPPERS_TO_IGNORE.add(ResponseEntity.class);
36+
RESULT_WRAPPERS_TO_IGNORE.add(HttpEntity.class);
37+
RESULT_WRAPPERS_TO_IGNORE.add(CompletionStage.class);
38+
}
39+
40+
public static void addResponseWrapperToIgnore(Class<?> cls){
41+
RESULT_WRAPPERS_TO_IGNORE.add(cls);
42+
}
43+
44+
public static boolean isResponseTypeWrapper(Class<?> rawClass) {
45+
return RESULT_WRAPPERS_TO_IGNORE.stream().anyMatch(clazz -> clazz.isAssignableFrom(rawClass));
46+
}
47+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
*
3+
* * Copyright 2019-2020 the original author or authors.
4+
* *
5+
* * Licensed under the Apache License, Version 2.0 (the "License");
6+
* * you may not use this file except in compliance with the License.
7+
* * You may obtain a copy of the License at
8+
* *
9+
* * https://www.apache.org/licenses/LICENSE-2.0
10+
* *
11+
* * Unless required by applicable law or agreed to in writing, software
12+
* * distributed under the License is distributed on an "AS IS" BASIS,
13+
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* * See the License for the specific language governing permissions and
15+
* * limitations under the License.
16+
*
17+
*/
18+
19+
package org.springdoc.core.converters;
20+
21+
22+
import java.util.Iterator;
23+
24+
import com.fasterxml.jackson.databind.JavaType;
25+
import io.swagger.v3.core.converter.AnnotatedType;
26+
import io.swagger.v3.core.converter.ModelConverter;
27+
import io.swagger.v3.core.converter.ModelConverterContext;
28+
import io.swagger.v3.core.util.Json;
29+
import io.swagger.v3.oas.models.media.Schema;
30+
31+
import static org.springdoc.core.converters.ConverterUtils.isResponseTypeWrapper;
32+
33+
public class ResponseSupportConverter implements ModelConverter {
34+
35+
@Override
36+
public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
37+
JavaType javaType = Json.mapper().constructType(type.getType());
38+
if (javaType != null) {
39+
Class<?> cls = javaType.getRawClass();
40+
if (isResponseTypeWrapper(cls)) {
41+
JavaType innerType = javaType.getBindings().getBoundType(0);
42+
if (innerType.getBindings() != null && isResponseTypeWrapper(innerType.getRawClass())) {
43+
type = new AnnotatedType(innerType).jsonViewAnnotation(type.getJsonViewAnnotation()).resolveAsRef(true);
44+
return this.resolve(type, context, chain);
45+
}else {
46+
type = new AnnotatedType(innerType).jsonViewAnnotation(type.getJsonViewAnnotation()).resolveAsRef(true);
47+
}
48+
}
49+
}
50+
if (chain.hasNext()) {
51+
return chain.next().resolve(type, context, chain);
52+
}
53+
else {
54+
return null;
55+
}
56+
}
57+
58+
}

springdoc-openapi-webflux-core/src/main/java/org/springdoc/api/MultipleOpenApiResource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
import com.fasterxml.jackson.core.JsonProcessingException;
2727
import io.swagger.v3.oas.annotations.Operation;
2828
import org.springdoc.core.AbstractRequestBuilder;
29-
import org.springdoc.core.AbstractResponseBuilder;
29+
import org.springdoc.core.GenericResponseBuilder;
3030
import org.springdoc.core.GroupedOpenApi;
3131
import org.springdoc.core.OpenAPIBuilder;
3232
import org.springdoc.core.OperationBuilder;
@@ -57,7 +57,7 @@ public class MultipleOpenApiResource implements InitializingBean {
5757

5858
private final AbstractRequestBuilder requestBuilder;
5959

60-
private final AbstractResponseBuilder responseBuilder;
60+
private final GenericResponseBuilder responseBuilder;
6161

6262
private final OperationBuilder operationParser;
6363

@@ -70,7 +70,7 @@ public class MultipleOpenApiResource implements InitializingBean {
7070

7171
public MultipleOpenApiResource(List<GroupedOpenApi> groupedOpenApis,
7272
ObjectFactory<OpenAPIBuilder> defaultOpenAPIBuilder, AbstractRequestBuilder requestBuilder,
73-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
73+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
7474
RequestMappingInfoHandlerMapping requestMappingHandlerMapping) {
7575

7676
this.groupedOpenApis = groupedOpenApis;

springdoc-openapi-webflux-core/src/main/java/org/springdoc/api/OpenApiResource.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import io.swagger.v3.oas.annotations.Operation;
3232
import io.swagger.v3.oas.models.OpenAPI;
3333
import org.springdoc.core.AbstractRequestBuilder;
34-
import org.springdoc.core.AbstractResponseBuilder;
34+
import org.springdoc.core.GenericResponseBuilder;
3535
import org.springdoc.core.OpenAPIBuilder;
3636
import org.springdoc.core.OperationBuilder;
3737
import org.springdoc.core.customizers.OpenApiCustomiser;
@@ -60,15 +60,15 @@ public class OpenApiResource extends AbstractOpenApiResource {
6060
private final RequestMappingInfoHandlerMapping requestMappingHandlerMapping;
6161

6262
public OpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
63-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
63+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
6464
RequestMappingInfoHandlerMapping requestMappingHandlerMapping,
6565
Optional<List<OpenApiCustomiser>> openApiCustomisers) {
6666
super(openAPIBuilder, requestBuilder, responseBuilder, operationParser, openApiCustomisers);
6767
this.requestMappingHandlerMapping = requestMappingHandlerMapping;
6868
}
6969

7070
public OpenApiResource(OpenAPIBuilder openAPIBuilder, AbstractRequestBuilder requestBuilder,
71-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
71+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
7272
RequestMappingInfoHandlerMapping requestMappingHandlerMapping,
7373
Optional<List<OpenApiCustomiser>> openApiCustomisers, List<String> pathsToMatch, List<String> packagesToScan, boolean cacheDisabled) {
7474
super(openAPIBuilder, requestBuilder, responseBuilder, operationParser, openApiCustomisers, pathsToMatch, packagesToScan, cacheDisabled);

springdoc-openapi-webflux-core/src/main/java/org/springdoc/core/MultipleOpenApiWebFluxConfiguration.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class MultipleOpenApiWebFluxConfiguration {
4242
@Bean
4343
public MultipleOpenApiResource multipleOpenApiResource(List<GroupedOpenApi> groupedOpenApis,
4444
ObjectFactory<OpenAPIBuilder> defaultOpenAPIBuilder, AbstractRequestBuilder requestBuilder,
45-
AbstractResponseBuilder responseBuilder, OperationBuilder operationParser,
45+
GenericResponseBuilder responseBuilder, OperationBuilder operationParser,
4646
RequestMappingInfoHandlerMapping requestMappingHandlerMapping) {
4747
return new MultipleOpenApiResource(groupedOpenApis,
4848
defaultOpenAPIBuilder, requestBuilder,

0 commit comments

Comments
 (0)