Skip to content

Commit a98a2e5

Browse files
committed
Code review. Fixes #1053
1 parent 0be549e commit a98a2e5

File tree

10 files changed

+755
-30
lines changed

10 files changed

+755
-30
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [1.5.4] - 2021-02-09
8+
### Added
9+
- #1053 - Add @RepositoryRestController documentation generation
10+
### Changed
11+
- Upgrade versions: swagger-ui to 3.42.0
12+
### Fixed
13+
- #1051 - IllegalStateException in org.springdoc.core.SpringDocConfiguration$OpenApiResourceAdvice.handleNoHandlerFound
14+
- #1047 - swaggerWelcome `WebFluxProperties' that could not be found
15+
716
## [1.5.3] - 2021-01-26
817
### Added
918
- Added Support for spring.webflux.base-path

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
<maven-release-plugin.version>2.5.3</maven-release-plugin.version>
6868
<nexus-staging-maven-plugin>1.6.8</nexus-staging-maven-plugin>
6969
<swagger-api.version>2.1.6</swagger-api.version>
70-
<swagger-ui.version>3.40.0</swagger-ui.version>
70+
<swagger-ui.version>3.42.0</swagger-ui.version>
7171
<spring-security-oauth2.version>2.3.8.RELEASE</spring-security-oauth2.version>
7272
<classgraph.version>4.8.69</classgraph.version>
7373
<webjars-locator-core.version>0.45</webjars-locator-core.version>

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package org.springdoc.core;
22

33
import java.util.List;
4+
import java.util.Map;
45

56
import io.swagger.v3.oas.models.OpenAPI;
67
import org.springdoc.core.fn.RouterOperation;
@@ -18,4 +19,19 @@ public interface RepositoryRestResourceProvider {
1819
* @return the router operations
1920
*/
2021
List<RouterOperation> getRouterOperations(OpenAPI openAPI);
22+
23+
/**
24+
* Gets repository rest controller endpoints.
25+
*
26+
* @return the repository rest controller endpoints
27+
*/
28+
Map<String, Object> getRepositoryRestControllerEndpoints();
29+
30+
/**
31+
* Gets handler methods.
32+
*
33+
* @return the handler methods
34+
*/
35+
Map getHandlerMethods();
36+
2137
}

springdoc-openapi-data-rest/src/main/java/org/springdoc/data/rest/SpringRepositoryRestResourceProvider.java

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springdoc.data.rest.core.DataRestRouterOperationService;
4444

4545
import org.springframework.context.ApplicationContext;
46+
import org.springframework.core.annotation.AnnotatedElementUtils;
4647
import org.springframework.data.mapping.PersistentEntity;
4748
import org.springframework.data.mapping.PersistentProperty;
4849
import org.springframework.data.mapping.SimpleAssociationHandler;
@@ -54,13 +55,15 @@
5455
import org.springframework.data.rest.core.mapping.SearchResourceMappings;
5556
import org.springframework.data.rest.webmvc.BasePathAwareHandlerMapping;
5657
import org.springframework.data.rest.webmvc.ProfileController;
58+
import org.springframework.data.rest.webmvc.RepositoryRestController;
5759
import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping;
5860
import org.springframework.data.rest.webmvc.alps.AlpsController;
5961
import org.springframework.data.rest.webmvc.json.JacksonMetadata;
6062
import org.springframework.data.rest.webmvc.mapping.Associations;
6163
import org.springframework.web.method.HandlerMethod;
6264
import org.springframework.web.servlet.HandlerMapping;
6365
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
66+
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
6467

6568
/**
6669
* The type Spring repository rest resource provider.
@@ -69,34 +72,39 @@
6972
public class SpringRepositoryRestResourceProvider implements RepositoryRestResourceProvider {
7073

7174
/**
72-
* The constant REPOSITORY_ENTITY_CONTROLLER.
75+
* The constant SPRING_DATA_REST_PACKAGE.
7376
*/
74-
private static final String REPOSITORY_ENTITY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryEntityController";
77+
private static final String SPRING_DATA_REST_PACKAGE = "org.springframework.data.rest";
7578

7679
/**
77-
* The constant REPOSITORY_SERACH_CONTROLLER.
80+
* The constant REPOSITORY_SCHEMA_CONTROLLER.
7881
*/
79-
private static final String REPOSITORY_SERACH_CONTROLLER = "org.springframework.data.rest.webmvc.RepositorySearchController";
82+
public static final String REPOSITORY_SCHEMA_CONTROLLER = SPRING_DATA_REST_PACKAGE + ".webmvc.RepositorySchemaController";
8083

8184
/**
82-
* The constant REPOSITORY_SCHEMA_CONTROLLER.
85+
* The constant REPOSITORY_ENTITY_CONTROLLER.
8386
*/
84-
public static final String REPOSITORY_SCHEMA_CONTROLLER = "org.springframework.data.rest.webmvc.RepositorySchemaController";
87+
private static final String REPOSITORY_ENTITY_CONTROLLER = SPRING_DATA_REST_PACKAGE + ".webmvc.RepositoryEntityController";
88+
89+
/**
90+
* The constant REPOSITORY_SEARCH_CONTROLLER.
91+
*/
92+
private static final String REPOSITORY_SERACH_CONTROLLER = SPRING_DATA_REST_PACKAGE + ".webmvc.RepositorySearchController";
8593

8694
/**
8795
* The constant REPOSITORY_PROPERTY_CONTROLLER.
8896
*/
89-
private static final String REPOSITORY_PROPERTY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController";
97+
private static final String REPOSITORY_PROPERTY_CONTROLLER = SPRING_DATA_REST_PACKAGE + ".webmvc.RepositoryPropertyReferenceController";
9098

9199
/**
92100
* The Delegating handler mapping class.
93101
*/
94-
private static final String DELEGATING_HANDLER_MAPPING_CLASS = "org.springframework.data.rest.webmvc.config.DelegatingHandlerMapping";
102+
private static final String DELEGATING_HANDLER_MAPPING_CLASS = SPRING_DATA_REST_PACKAGE + ".webmvc.config.DelegatingHandlerMapping";
95103

96104
/**
97105
* The Delegating handler mapping interface.
98106
*/
99-
private static final String DELEGATING_HANDLER_MAPPING_INTERFACE = "org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping";
107+
private static final String DELEGATING_HANDLER_MAPPING_INTERFACE = SPRING_DATA_REST_PACKAGE + ".webmvc.support.DelegatingHandlerMapping";
100108

101109
/**
102110
* The constant LOGGER.
@@ -138,6 +146,11 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou
138146
*/
139147
private ApplicationContext applicationContext;
140148

149+
/**
150+
* The Handler mapping list.
151+
*/
152+
private List<HandlerMapping> handlerMappingList;
153+
141154
/**
142155
* Instantiates a new Spring repository rest resource provider.
143156
*
@@ -159,9 +172,10 @@ public SpringRepositoryRestResourceProvider(ResourceMappings mappings, Repositor
159172
this.mapper = mapper;
160173
}
161174

175+
162176
public List<RouterOperation> getRouterOperations(OpenAPI openAPI) {
163177
List<RouterOperation> routerOperationList = new ArrayList<>();
164-
List<HandlerMapping> handlerMappingList = getHandlerMappingList();
178+
handlerMappingList = getHandlerMappingList();
165179
for (Class<?> domainType : repositories) {
166180
Class<?> repository = repositories.getRequiredRepositoryInformation(domainType).getRepositoryInterface();
167181
DataRestRepository dataRestRepository = new DataRestRepository(domainType, repository);
@@ -223,34 +237,61 @@ else if (handlerMapping instanceof BasePathAwareHandlerMapping) {
223237
return routerOperationList;
224238
}
225239

240+
/**
241+
* Gets repository rest controller endpoints.
242+
*
243+
* @return the repository rest controller endpoints
244+
*/
245+
@Override
246+
public Map<String, Object> getRepositoryRestControllerEndpoints() {
247+
return applicationContext.getBeansWithAnnotation(RepositoryRestController.class);
248+
}
249+
250+
/**
251+
* Gets handler methods.
252+
*
253+
* @return the handler methods
254+
*/
255+
@Override
256+
public Map getHandlerMethods() {
257+
handlerMappingList = getHandlerMappingList();
258+
return handlerMappingList.stream().filter(RequestMappingInfoHandlerMapping.class::isInstance)
259+
.flatMap(
260+
handler -> ((RequestMappingInfoHandlerMapping) handler).getHandlerMethods().entrySet().stream())
261+
.filter(entry -> !entry.getValue().getBeanType().getName().startsWith(SPRING_DATA_REST_PACKAGE) && AnnotatedElementUtils.hasAnnotation(entry.getValue().getBeanType(), RepositoryRestController.class))
262+
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
263+
}
226264
/**
227265
* Gets handler mapping list.
228266
*
229267
* @return the handler mapping list
230268
*/
231269
private List<HandlerMapping> getHandlerMappingList() {
232-
List<HandlerMapping> handlerMappingList = new ArrayList<>();
233-
Class delegatingHandlerMappingClass = null;
234-
try {
235-
delegatingHandlerMappingClass = Class.forName(DELEGATING_HANDLER_MAPPING_CLASS);
236-
}
237-
catch (ClassNotFoundException e) {
270+
if (handlerMappingList == null) {
271+
handlerMappingList = new ArrayList<>();
272+
Class delegatingHandlerMappingClass = null;
238273
try {
239-
delegatingHandlerMappingClass = Class.forName(DELEGATING_HANDLER_MAPPING_INTERFACE);
240-
}
241-
catch (ClassNotFoundException exception) {
242-
LOGGER.warn(e.getMessage());
274+
delegatingHandlerMappingClass = Class.forName(DELEGATING_HANDLER_MAPPING_CLASS);
243275
}
244-
}
245-
if (delegatingHandlerMappingClass != null) {
246-
Object object = applicationContext.getBean(delegatingHandlerMappingClass);
247-
try {
248-
handlerMappingList = (List<HandlerMapping>) MethodUtils.invokeMethod(object, "getDelegates");
276+
catch (ClassNotFoundException e) {
277+
try {
278+
delegatingHandlerMappingClass = Class.forName(DELEGATING_HANDLER_MAPPING_INTERFACE);
279+
}
280+
catch (ClassNotFoundException exception) {
281+
LOGGER.warn(e.getMessage());
282+
}
249283
}
250-
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
251-
LOGGER.warn(e.getMessage());
284+
if (delegatingHandlerMappingClass != null) {
285+
Object object = applicationContext.getBean(delegatingHandlerMappingClass);
286+
try {
287+
handlerMappingList = (List<HandlerMapping>) MethodUtils.invokeMethod(object, "getDelegates");
288+
}
289+
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
290+
LOGGER.warn(e.getMessage());
291+
}
252292
}
253293
}
294+
254295
return handlerMappingList;
255296
}
256297

@@ -312,8 +353,7 @@ private List<RouterOperation> findSearchControllers(List<RouterOperation> router
312353
* @param openAPI the open api
313354
* @return the list
314355
*/
315-
private List<RouterOperation> findControllers
316-
(List<RouterOperation> routerOperationList,
356+
private List<RouterOperation> findControllers(List<RouterOperation> routerOperationList,
317357
Map<RequestMappingInfo, HandlerMethod> handlerMethodMap, ResourceMetadata resourceMetadata,
318358
DataRestRepository dataRestRepository, OpenAPI openAPI) {
319359
dataRestRouterOperationService.buildEntityRouterOperationList(routerOperationList, handlerMethodMap, resourceMetadata,
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2020 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*
22+
*/
23+
24+
package test.org.springdoc.api.app22;
25+
26+
import javax.persistence.Entity;
27+
import javax.persistence.GeneratedValue;
28+
import javax.persistence.GenerationType;
29+
import javax.persistence.Id;
30+
31+
@Entity
32+
public class Person {
33+
34+
@Id
35+
@GeneratedValue(strategy = GenerationType.AUTO)
36+
private long id;
37+
38+
private String firstName;
39+
private String lastName;
40+
41+
public String getFirstName() {
42+
return firstName;
43+
}
44+
45+
public void setFirstName(String firstName) {
46+
this.firstName = firstName;
47+
}
48+
49+
public String getLastName() {
50+
return lastName;
51+
}
52+
53+
public void setLastName(String lastName) {
54+
this.lastName = lastName;
55+
}
56+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2020 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*
22+
*/
23+
24+
package test.org.springdoc.api.app22;
25+
26+
import org.springframework.data.rest.webmvc.RepositoryRestController;
27+
import org.springframework.web.bind.annotation.GetMapping;
28+
29+
@RepositoryRestController
30+
public class PersonApi {
31+
32+
@GetMapping("/people/test")
33+
public Person test() {
34+
return new Person();
35+
}
36+
37+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
*
3+
* *
4+
* * *
5+
* * * * Copyright 2019-2020 the original author or authors.
6+
* * * *
7+
* * * * Licensed under the Apache License, Version 2.0 (the "License");
8+
* * * * you may not use this file except in compliance with the License.
9+
* * * * You may obtain a copy of the License at
10+
* * * *
11+
* * * * https://www.apache.org/licenses/LICENSE-2.0
12+
* * * *
13+
* * * * Unless required by applicable law or agreed to in writing, software
14+
* * * * distributed under the License is distributed on an "AS IS" BASIS,
15+
* * * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
* * * * See the License for the specific language governing permissions and
17+
* * * * limitations under the License.
18+
* * *
19+
* *
20+
*
21+
*
22+
*/
23+
24+
package test.org.springdoc.api.app22;
25+
26+
import org.springframework.data.repository.PagingAndSortingRepository;
27+
import org.springframework.data.rest.core.annotation.RepositoryRestResource;
28+
29+
@RepositoryRestResource(path = "people", collectionResourceRel = "people")
30+
public interface PersonRepository extends PagingAndSortingRepository<Person, Long> {
31+
32+
}

0 commit comments

Comments
 (0)