Skip to content

Commit 88327e6

Browse files
author
bnasslahsen
committed
Allow ModelAndView to be detected. Fixes #428.
1 parent f2a75b3 commit 88327e6

File tree

12 files changed

+187
-85
lines changed

12 files changed

+187
-85
lines changed

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
8181

8282
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
8383

84-
private final SpringDocConfigProperties springDocConfigProperties;
84+
protected final SpringDocConfigProperties springDocConfigProperties;
8585

8686
private static final List<Class<?>> ADDITIONAL_REST_CONTROLLERS = new ArrayList<>();
8787
private static final List<Class<?>> HIDDEN_REST_CONTROLLERS = new ArrayList<>();
@@ -110,7 +110,7 @@ protected AbstractOpenApiResource(String groupName, OpenAPIBuilder openAPIBuilde
110110

111111
protected synchronized OpenAPI getOpenApi() {
112112
OpenAPI openApi;
113-
if (!computeDone || Boolean.TRUE.equals(springDocConfigProperties.getCache().getDisabled())) {
113+
if (!computeDone || springDocConfigProperties.getCache().isDisabled()) {
114114
Instant start = Instant.now();
115115
openAPIBuilder.build();
116116
Map<String, Object> restControllersMap = openAPIBuilder.getRestControllersMap();

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/OpenAPIBuilder.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public Operation buildTags(HandlerMethod handlerMethod, Operation operation, Ope
213213
operation.setTags(new ArrayList<>(tagsStr));
214214
}
215215

216-
if (CollectionUtils.isEmpty(operation.getTags()) && Boolean.TRUE.equals(springDocConfigProperties.getAutoTagClasses())) {
216+
if (CollectionUtils.isEmpty(operation.getTags()) && springDocConfigProperties.isAutoTagClasses()) {
217217
operation.addTagsItem(splitCamelCase(handlerMethod.getBeanType().getSimpleName()));
218218
}
219219

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/SpringDocConfigProperties.java

+25-15
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
@ConditionalOnProperty(name = SPRINGDOC_ENABLED, matchIfMissing = true)
3333
public class SpringDocConfigProperties {
3434

35-
private Boolean showActuator = false;
35+
private boolean showActuator;
3636

3737
private Webjars webjars = new Webjars();
3838

@@ -50,16 +50,26 @@ public class SpringDocConfigProperties {
5050

5151
private List<GroupConfig> groupConfigs = new ArrayList<>();
5252

53-
private Boolean autoTagClasses = true;
53+
private boolean autoTagClasses = true;
5454

55-
public Boolean getAutoTagClasses() {
55+
private boolean modelAndViewAllowed;
56+
57+
public boolean isAutoTagClasses() {
5658
return autoTagClasses;
5759
}
5860

59-
public void setAutoTagClasses(Boolean autoTagClasses) {
61+
public void setAutoTagClasses(boolean autoTagClasses) {
6062
this.autoTagClasses = autoTagClasses;
6163
}
6264

65+
public boolean isModelAndViewAllowed() {
66+
return modelAndViewAllowed;
67+
}
68+
69+
public void setModelAndViewAllowed(boolean modelAndViewAllowed) {
70+
this.modelAndViewAllowed = modelAndViewAllowed;
71+
}
72+
6373
public List<String> getPackagesToExclude() {
6474
return packagesToExclude;
6575
}
@@ -84,11 +94,11 @@ public void setPackagesToScan(List<String> packagesToScan) {
8494
this.packagesToScan = packagesToScan;
8595
}
8696

87-
public Boolean getShowActuator() {
97+
public boolean isShowActuator() {
8898
return showActuator;
8999
}
90100

91-
public void setShowActuator(Boolean showActuator) {
101+
public void setShowActuator(boolean showActuator) {
92102
this.showActuator = showActuator;
93103
}
94104

@@ -145,7 +155,7 @@ public static class ApiDocs {
145155
/**
146156
* Weather to generate and serve a OpenAPI document.
147157
*/
148-
private Boolean enabled = true;
158+
private boolean enabled = true;
149159

150160
private Groups groups = new Groups();
151161

@@ -157,11 +167,11 @@ public void setPath(String path) {
157167
this.path = path;
158168
}
159169

160-
public Boolean getEnabled() {
170+
public boolean isEnabled() {
161171
return enabled;
162172
}
163173

164-
public void setEnabled(Boolean enabled) {
174+
public void setEnabled(boolean enabled) {
165175
this.enabled = enabled;
166176
}
167177

@@ -175,25 +185,25 @@ public void setGroups(Groups groups) {
175185
}
176186

177187
public static class Groups {
178-
private Boolean enabled = false;
188+
private boolean enabled;
179189

180-
public Boolean getEnabled() {
190+
public boolean isEnabled() {
181191
return enabled;
182192
}
183193

184-
public void setEnabled(Boolean enabled) {
194+
public void setEnabled(boolean enabled) {
185195
this.enabled = enabled;
186196
}
187197
}
188198

189199
public static class Cache {
190-
private Boolean disabled = false;
200+
private boolean disabled;
191201

192-
public Boolean getDisabled() {
202+
public boolean isDisabled() {
193203
return disabled;
194204
}
195205

196-
public void setDisabled(Boolean disabled) {
206+
public void setDisabled(boolean disabled) {
197207
this.disabled = disabled;
198208
}
199209
}

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222
import java.util.List;
2323
import java.util.Optional;
2424

25+
import com.fasterxml.jackson.databind.node.ObjectNode;
2526
import io.swagger.v3.core.converter.ModelConverter;
2627
import io.swagger.v3.oas.models.OpenAPI;
28+
import io.swagger.v3.oas.models.media.ObjectSchema;
29+
import org.springdoc.core.converters.AdditionalModelsConverter;
2730
import org.springdoc.core.converters.ModelConverterRegistrar;
28-
import org.springdoc.core.converters.ObjectNodeConverter;
2931
import org.springdoc.core.converters.PropertyCustomizingConverter;
3032
import org.springdoc.core.converters.ResponseSupportConverter;
3133
import org.springdoc.core.customizers.PropertyCustomizer;
@@ -49,14 +51,17 @@
4951
@ConditionalOnProperty(name = SPRINGDOC_ENABLED, matchIfMissing = true)
5052
public class SpringDocConfiguration {
5153

54+
static {
55+
AdditionalModelsConverter.replaceWithSchema(ObjectNode.class, new ObjectSchema());
56+
}
5257
@Bean
5358
LocalVariableTableParameterNameDiscoverer localSpringDocParameterNameDiscoverer() {
5459
return new LocalVariableTableParameterNameDiscoverer();
5560
}
5661

5762
@Bean
58-
ObjectNodeConverter objectNodeConverter() {
59-
return new ObjectNodeConverter();
63+
AdditionalModelsConverter pageableSupportConverter() {
64+
return new AdditionalModelsConverter();
6065
}
6166

6267
@Bean

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ObjectNodeConverter.java renamed to springdoc-openapi-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java

+19-7
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,31 @@
1818

1919
package org.springdoc.core.converters;
2020

21+
22+
import java.util.HashMap;
2123
import java.util.Iterator;
24+
import java.util.Map;
2225

2326
import com.fasterxml.jackson.databind.JavaType;
24-
import com.fasterxml.jackson.databind.node.ObjectNode;
2527
import io.swagger.v3.core.converter.AnnotatedType;
2628
import io.swagger.v3.core.converter.ModelConverter;
2729
import io.swagger.v3.core.converter.ModelConverterContext;
2830
import io.swagger.v3.core.util.Json;
29-
import io.swagger.v3.oas.models.media.ObjectSchema;
3031
import io.swagger.v3.oas.models.media.Schema;
3132

32-
@SuppressWarnings("rawtypes")
33-
public class ObjectNodeConverter implements ModelConverter {
33+
public class AdditionalModelsConverter implements ModelConverter {
3434

35+
private static Map<Class, Class> modelToClassMap= new HashMap();
36+
private static Map<Class, Schema> modelToSchemaMap= new HashMap();
3537
@Override
3638
public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterator<ModelConverter> chain) {
3739
JavaType javaType = Json.mapper().constructType(type.getType());
3840
if (javaType != null) {
3941
Class<?> cls = javaType.getRawClass();
40-
if (ObjectNode.class.isAssignableFrom(cls)) {
41-
return new ObjectSchema();
42-
}
42+
if(modelToSchemaMap.containsKey(cls))
43+
return modelToSchemaMap.get(cls);
44+
if(modelToClassMap.containsKey(cls))
45+
type = new AnnotatedType(modelToClassMap.get(cls));
4346
}
4447
if (chain.hasNext()) {
4548
return chain.next().resolve(type, context, chain);
@@ -48,4 +51,13 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
4851
return null;
4952
}
5053
}
54+
55+
public static void replaceWithClass(Class source, Class target) {
56+
modelToClassMap.put(source, target);
57+
}
58+
59+
public static void replaceWithSchema(Class source, Schema target) {
60+
modelToSchemaMap.put(source, target);
61+
}
62+
5163
}

Diff for: springdoc-openapi-common/src/main/java/org/springdoc/core/converters/ConverterUtils.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ public static void addResponseTypeToIgnore(Class<?> cls){
4848
RESPONSE_TYPES_TO_IGNORE.add(cls);
4949
}
5050

51-
public static boolean isResponseTypeWrapper(Class<?> rawClass) {
51+
static boolean isResponseTypeWrapper(Class<?> rawClass) {
5252
return RESULT_WRAPPERS_TO_IGNORE.stream().anyMatch(clazz -> clazz.isAssignableFrom(rawClass));
5353
}
5454

Diff for: springdoc-openapi-data-rest/src/main/java/org/springdoc/core/SpringDocDataRestConfiguration.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
import io.swagger.v3.oas.models.media.MapSchema;
2929
import io.swagger.v3.oas.models.media.ObjectSchema;
3030
import io.swagger.v3.oas.models.media.StringSchema;
31-
import org.springdoc.core.converters.PageableSupportConverter;
31+
import org.springdoc.core.converters.AdditionalModelsConverter;
32+
import org.springdoc.core.converters.Pageable;
3233
import org.springdoc.core.customizers.OpenApiCustomiser;
3334

3435
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -46,10 +47,10 @@
4647
@ConditionalOnProperty(name = SPRINGDOC_ENABLED, matchIfMissing = true)
4748
public class SpringDocDataRestConfiguration {
4849

49-
@Bean
50-
PageableSupportConverter pageableSupportConverter() {
51-
return new PageableSupportConverter();
52-
}
50+
static {
51+
AdditionalModelsConverter.replaceWithClass(org.springframework.data.domain.Pageable.class, Pageable.class);
52+
AdditionalModelsConverter.replaceWithClass(org.springframework.data.domain.PageRequest.class,Pageable.class);
53+
}
5354

5455
@Bean
5556
public HalProvider halProvider(RepositoryRestConfiguration repositoryRestConfiguration) {

Diff for: springdoc-openapi-data-rest/src/main/java/org/springdoc/core/converters/PageableSupportConverter.java

-50
This file was deleted.

Diff for: springdoc-openapi-webmvc-core/src/main/java/org/springdoc/api/OpenApiResource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ private boolean isRestController(Map<String, Object> restControllers, HandlerMet
145145

146146
return (responseBodyAnnotation != null && restControllers.containsKey(handlerMethod.getBean().toString()) || isAdditionalRestController(handlerMethod.getBeanType()))
147147
&& operationPath.startsWith(DEFAULT_PATH_SEPARATOR)
148-
&& !ModelAndView.class.isAssignableFrom(handlerMethod.getMethod().getReturnType());
148+
&& (springDocConfigProperties.isModelAndViewAllowed()|| !ModelAndView.class.isAssignableFrom(handlerMethod.getMethod().getReturnType()));
149149
}
150150

151151
private void calculateServerUrl(HttpServletRequest request, String apiDocsUrl) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
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 test.org.springdoc.api.app89;
20+
21+
import io.swagger.v3.oas.annotations.Operation;
22+
23+
import org.springframework.http.MediaType;
24+
import org.springframework.web.bind.annotation.GetMapping;
25+
import org.springframework.web.bind.annotation.PathVariable;
26+
import org.springframework.web.bind.annotation.RestController;
27+
import org.springframework.web.servlet.ModelAndView;
28+
29+
@RestController
30+
public class HelloController {
31+
32+
@Operation(summary = "Get Status")
33+
@GetMapping(value = "/status", produces = MediaType.TEXT_HTML_VALUE)
34+
public ModelAndView getAddress(@PathVariable String id) {
35+
return null;
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
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 test.org.springdoc.api.app89;
20+
21+
22+
import io.swagger.v3.oas.models.media.ObjectSchema;
23+
import test.org.springdoc.api.AbstractSpringDocTest;
24+
25+
import org.springframework.boot.autoconfigure.SpringBootApplication;
26+
import org.springframework.test.context.TestPropertySource;
27+
import org.springframework.web.servlet.ModelAndView;
28+
29+
import static org.springdoc.core.converters.AdditionalModelsConverter.replaceWithSchema;
30+
31+
@TestPropertySource(properties = "springdoc.model-and-view-allowed=true")
32+
public class SpringDocApp89Test extends AbstractSpringDocTest {
33+
34+
@SpringBootApplication
35+
static class SpringDocTestApp {}
36+
37+
static {
38+
replaceWithSchema(ModelAndView .class, new ObjectSchema());
39+
}
40+
}

0 commit comments

Comments
 (0)