Skip to content

Commit 8b6d232

Browse files
author
bnasslahsen
committed
spring-rest-docs api-docs endpoint 500 error using Spring Boot: 2.4.0-M2. Fixes #847.
1 parent 2dae34a commit 8b6d232

File tree

2 files changed

+68
-18
lines changed

2 files changed

+68
-18
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
5050
import org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties;
5151
import org.springframework.boot.autoconfigure.hateoas.HateoasProperties;
52+
import org.springframework.context.ApplicationContext;
5253
import org.springframework.context.annotation.Bean;
5354
import org.springframework.context.annotation.Configuration;
5455
import org.springframework.context.annotation.Lazy;
@@ -65,7 +66,6 @@
6566
import org.springframework.data.rest.webmvc.RootResourceInformation;
6667
import org.springframework.data.rest.webmvc.mapping.Associations;
6768
import org.springframework.data.rest.webmvc.support.DefaultedPageable;
68-
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
6969
import org.springframework.data.rest.webmvc.support.ETag;
7070

7171
import static org.springdoc.core.Constants.SPRINGDOC_ENABLED;
@@ -159,7 +159,7 @@ static class SpringRepositoryRestResourceProviderConfiguration {
159159
* @param mappings the mappings
160160
* @param repositories the repositories
161161
* @param associations the associations
162-
* @param delegatingHandlerMapping the delegating handler mapping
162+
* @param applicationContext the application context
163163
* @param dataRestRouterOperationBuilder the data rest router operation builder
164164
* @param persistentEntities the persistent entities
165165
* @param mapper the mapper
@@ -168,10 +168,10 @@ static class SpringRepositoryRestResourceProviderConfiguration {
168168
@Bean
169169
@ConditionalOnMissingBean
170170
SpringRepositoryRestResourceProvider springRepositoryRestResourceProvider(ResourceMappings mappings,
171-
Repositories repositories, Associations associations, DelegatingHandlerMapping delegatingHandlerMapping,
171+
Repositories repositories, Associations associations, ApplicationContext applicationContext,
172172
DataRestRouterOperationBuilder dataRestRouterOperationBuilder, PersistentEntities persistentEntities,
173173
ObjectMapper mapper) {
174-
return new SpringRepositoryRestResourceProvider(mappings,repositories, associations, delegatingHandlerMapping,
174+
return new SpringRepositoryRestResourceProvider(mappings,repositories, associations, applicationContext,
175175
dataRestRouterOperationBuilder, persistentEntities, mapper);
176176
}
177177

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

Lines changed: 64 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
package org.springdoc.data.rest;
2525

26+
import java.lang.reflect.InvocationTargetException;
2627
import java.util.ArrayList;
2728
import java.util.List;
2829
import java.util.Map;
@@ -31,13 +32,17 @@
3132

3233
import com.fasterxml.jackson.databind.ObjectMapper;
3334
import io.swagger.v3.oas.models.OpenAPI;
35+
import org.apache.commons.lang3.reflect.MethodUtils;
36+
import org.slf4j.Logger;
37+
import org.slf4j.LoggerFactory;
3438
import org.springdoc.api.AbstractOpenApiResource;
3539
import org.springdoc.core.RepositoryRestResourceProvider;
3640
import org.springdoc.core.fn.RouterOperation;
3741
import org.springdoc.data.rest.core.ControllerType;
3842
import org.springdoc.data.rest.core.DataRestRepository;
3943
import org.springdoc.data.rest.core.DataRestRouterOperationBuilder;
4044

45+
import org.springframework.context.ApplicationContext;
4146
import org.springframework.data.mapping.PersistentEntity;
4247
import org.springframework.data.mapping.PersistentProperty;
4348
import org.springframework.data.mapping.SimpleAssociationHandler;
@@ -53,7 +58,6 @@
5358
import org.springframework.data.rest.webmvc.alps.AlpsController;
5459
import org.springframework.data.rest.webmvc.json.JacksonMetadata;
5560
import org.springframework.data.rest.webmvc.mapping.Associations;
56-
import org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping;
5761
import org.springframework.web.method.HandlerMethod;
5862
import org.springframework.web.servlet.HandlerMapping;
5963
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
@@ -67,12 +71,12 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou
6771
/**
6872
* The constant REPOSITORY_ENTITY_CONTROLLER.
6973
*/
70-
public static final String REPOSITORY_ENTITY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryEntityController";
74+
private static final String REPOSITORY_ENTITY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryEntityController";
7175

7276
/**
7377
* The constant REPOSITORY_SERACH_CONTROLLER.
7478
*/
75-
public static final String REPOSITORY_SERACH_CONTROLLER = "org.springframework.data.rest.webmvc.RepositorySearchController";
79+
private static final String REPOSITORY_SERACH_CONTROLLER = "org.springframework.data.rest.webmvc.RepositorySearchController";
7680

7781
/**
7882
* The constant REPOSITORY_SCHEMA_CONTROLLER.
@@ -82,7 +86,22 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou
8286
/**
8387
* The constant REPOSITORY_PROPERTY_CONTROLLER.
8488
*/
85-
public static final String REPOSITORY_PROPERTY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController";
89+
private static final String REPOSITORY_PROPERTY_CONTROLLER = "org.springframework.data.rest.webmvc.RepositoryPropertyReferenceController";
90+
91+
/**
92+
* The Delegating handler mapping class.
93+
*/
94+
private static final String DELEGATING_HANDLER_MAPPING_CLASS = "org.springframework.data.rest.webmvc.config.DelegatingHandlerMapping";
95+
96+
/**
97+
* The Delegating handler mapping interface.
98+
*/
99+
private static final String DELEGATING_HANDLER_MAPPING_INTERFACE = "org.springframework.data.rest.webmvc.support.DelegatingHandlerMapping";
100+
101+
/**
102+
* The constant LOGGER.
103+
*/
104+
private static final Logger LOGGER = LoggerFactory.getLogger(SpringRepositoryRestResourceProvider.class);
86105

87106
/**
88107
* The Mappings.
@@ -99,11 +118,6 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou
99118
*/
100119
private Associations associations;
101120

102-
/**
103-
* The Delegating handler mapping.
104-
*/
105-
private DelegatingHandlerMapping delegatingHandlerMapping;
106-
107121
/**
108122
* The Data rest router operation builder.
109123
*/
@@ -119,30 +133,35 @@ public class SpringRepositoryRestResourceProvider implements RepositoryRestResou
119133
*/
120134
private ObjectMapper mapper;
121135

136+
/**
137+
* The Application context.
138+
*/
139+
private ApplicationContext applicationContext;
140+
122141
/**
123142
* Instantiates a new Spring repository rest resource provider.
124143
*
125144
* @param mappings the mappings
126145
* @param repositories the repositories
127146
* @param associations the associations
128-
* @param delegatingHandlerMapping the delegating handler mapping
147+
* @param applicationContext the application context
129148
* @param dataRestRouterOperationBuilder the data rest router operation builder
130149
* @param persistentEntities the persistent entities
131150
* @param mapper the mapper
132151
*/
133-
public SpringRepositoryRestResourceProvider(ResourceMappings mappings, Repositories repositories, Associations associations, DelegatingHandlerMapping delegatingHandlerMapping, DataRestRouterOperationBuilder dataRestRouterOperationBuilder, PersistentEntities persistentEntities, ObjectMapper mapper) {
152+
public SpringRepositoryRestResourceProvider(ResourceMappings mappings, Repositories repositories, Associations associations, ApplicationContext applicationContext, DataRestRouterOperationBuilder dataRestRouterOperationBuilder, PersistentEntities persistentEntities, ObjectMapper mapper) {
134153
this.mappings = mappings;
135154
this.repositories = repositories;
136155
this.associations = associations;
137-
this.delegatingHandlerMapping = delegatingHandlerMapping;
156+
this.applicationContext = applicationContext;
138157
this.dataRestRouterOperationBuilder = dataRestRouterOperationBuilder;
139158
this.persistentEntities = persistentEntities;
140159
this.mapper = mapper;
141160
}
142161

143162
public List<RouterOperation> getRouterOperations(OpenAPI openAPI) {
144163
List<RouterOperation> routerOperationList = new ArrayList<>();
145-
List<HandlerMapping> handlerMappingList = delegatingHandlerMapping.getDelegates();
164+
List<HandlerMapping> handlerMappingList = getHandlerMappingList();
146165
for (Class<?> domainType : repositories) {
147166
Class<?> repository = repositories.getRequiredRepositoryInformation(domainType).getRepositoryInterface();
148167
DataRestRepository dataRestRepository = new DataRestRepository(domainType, repository);
@@ -165,7 +184,7 @@ public List<RouterOperation> getRouterOperations(OpenAPI openAPI) {
165184
findControllers(routerOperationList, handlerMethodMapFiltered, resourceMetadata, dataRestRepository, openAPI);
166185

167186
Map<RequestMappingInfo, HandlerMethod> handlerMethodMapFilteredMethodMap = handlerMethodMap.entrySet().stream()
168-
.filter(requestMappingInfoHandlerMethodEntry -> REPOSITORY_PROPERTY_CONTROLLER.equals(requestMappingInfoHandlerMethodEntry
187+
.filter(requestMappingInfoHandlerMethodEntry -> REPOSITORY_PROPERTY_CONTROLLER.equals(requestMappingInfoHandlerMethodEntry
169188
.getValue().getBeanType().getName()))
170189
.filter(controller -> !AbstractOpenApiResource.isHiddenRestControllers(controller.getValue().getBeanType()))
171190
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1));
@@ -204,6 +223,37 @@ else if (handlerMapping instanceof BasePathAwareHandlerMapping) {
204223
return routerOperationList;
205224
}
206225

226+
/**
227+
* Gets handler mapping list.
228+
*
229+
* @return the handler mapping list
230+
*/
231+
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) {
238+
try {
239+
delegatingHandlerMappingClass = Class.forName(DELEGATING_HANDLER_MAPPING_INTERFACE);
240+
}
241+
catch (ClassNotFoundException exception) {
242+
LOGGER.warn(e.getMessage());
243+
}
244+
}
245+
if (delegatingHandlerMappingClass != null) {
246+
Object object = applicationContext.getBean(delegatingHandlerMappingClass);
247+
try {
248+
handlerMappingList = (List<HandlerMapping>) MethodUtils.invokeMethod(object, "getDelegates");
249+
}
250+
catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
251+
LOGGER.warn(e.getMessage());
252+
}
253+
}
254+
return handlerMappingList;
255+
}
256+
207257
/**
208258
* Find search resource mappings.
209259
*

0 commit comments

Comments
 (0)