Skip to content

Commit b9afaa9

Browse files
committed
OperationCustomizer is not working with Spring Data REST. Fixes #2062
1 parent a33e929 commit b9afaa9

File tree

19 files changed

+427
-342
lines changed

19 files changed

+427
-342
lines changed

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

+37-53
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@
8484
import org.springdoc.core.SpringDocConfigProperties.GroupConfig;
8585
import org.springdoc.core.SpringDocProviders;
8686
import org.springdoc.core.annotations.RouterOperations;
87-
import org.springdoc.core.customizers.OpenApiCustomiser;
87+
import org.springdoc.core.customizers.DataRestRouterOperationCustomizer;
8888
import org.springdoc.core.customizers.OpenApiLocaleCustomizer;
8989
import org.springdoc.core.customizers.OperationCustomizer;
9090
import org.springdoc.core.customizers.RouterOperationCustomizer;
91-
import org.springdoc.core.filters.OpenApiMethodFilter;
91+
import org.springdoc.core.customizers.SpringDocCustomizers;
9292
import org.springdoc.core.fn.AbstractRouterFunctionVisitor;
9393
import org.springdoc.core.fn.RouterFunctionData;
9494
import org.springdoc.core.fn.RouterOperation;
@@ -113,7 +113,6 @@
113113

114114
import static org.springdoc.core.Constants.ACTUATOR_DEFAULT_GROUP;
115115
import static org.springdoc.core.Constants.DOT;
116-
import static org.springdoc.core.Constants.LINKS_SCHEMA_CUSTOMISER;
117116
import static org.springdoc.core.Constants.OPERATION_ATTRIBUTE;
118117
import static org.springdoc.core.Constants.SPRING_MVC_SERVLET_PATH;
119118
import static org.springdoc.core.converters.SchemaPropertyDeprecatingConverter.isDeprecated;
@@ -182,84 +181,51 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
182181
*/
183182
private final OperationService operationParser;
184183

185-
/**
186-
* The Open api customizers.
187-
*/
188-
private final Optional<List<OpenApiCustomiser>> openApiCustomisers;
189-
190-
/**
191-
* The Operation customizers.
192-
*/
193-
private final Optional<List<OperationCustomizer>> operationCustomizers;
194-
195-
/**
196-
* The RouterOperation customizers.
197-
*/
198-
private final Optional<List<RouterOperationCustomizer>> routerOperationCustomizers;
199-
200-
/**
201-
* The method filters to use.
202-
*/
203-
private final Optional<List<OpenApiMethodFilter>> methodFilters;
204-
205184
/**
206185
* The Ant path matcher.
207186
*/
208187
private final AntPathMatcher antPathMatcher = new AntPathMatcher();
209188

210-
/**
211-
* The OpenApi with locale customizers.
212-
*/
213-
private final Map<String, OpenApiLocaleCustomizer> openApiLocaleCustomizers;
214189

215190
/**
216191
* The Open api builder.
217192
*/
218193
protected OpenAPIService openAPIService;
219194

195+
/**
196+
* The Spring doc customizers.
197+
*/
198+
protected final SpringDocCustomizers springDocCustomizers;
199+
220200
/**
221201
* Instantiates a new Abstract open api resource.
202+
*
222203
* @param groupName the group name
223204
* @param openAPIBuilderObjectFactory the open api builder object factory
224205
* @param requestBuilder the request builder
225206
* @param responseBuilder the response builder
226207
* @param operationParser the operation parser
227-
* @param operationCustomizers the operation customizers
228-
* @param openApiCustomisers the open api customisers
229-
* @param routerOperationCustomizers the router operation customisers
230-
* @param methodFilters the method filters
231208
* @param springDocConfigProperties the spring doc config properties
232209
* @param springDocProviders the spring doc providers
210+
* @param springDocCustomizers the spring doc customizers
233211
*/
234212
protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory,
235213
AbstractRequestService requestBuilder,
236214
GenericResponseService responseBuilder, OperationService operationParser,
237-
Optional<List<OperationCustomizer>> operationCustomizers,
238-
Optional<List<OpenApiCustomiser>> openApiCustomisers,
239-
Optional<List<RouterOperationCustomizer>> routerOperationCustomizers,
240-
Optional<List<OpenApiMethodFilter>> methodFilters,
241-
SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
215+
SpringDocConfigProperties springDocConfigProperties,
216+
SpringDocProviders springDocProviders, SpringDocCustomizers springDocCustomizers) {
242217
super();
243218
this.groupName = Objects.requireNonNull(groupName, "groupName");
244219
this.openAPIBuilderObjectFactory = openAPIBuilderObjectFactory;
245220
this.openAPIService = openAPIBuilderObjectFactory.getObject();
246221
this.requestBuilder = requestBuilder;
247222
this.responseBuilder = responseBuilder;
248223
this.operationParser = operationParser;
249-
this.openApiCustomisers = openApiCustomisers;
250-
this.routerOperationCustomizers = routerOperationCustomizers;
251-
this.methodFilters = methodFilters;
252224
this.springDocProviders = springDocProviders;
253-
//add the default customizers
254-
Map<String, OpenApiCustomiser> existingOpenApiCustomisers = openAPIService.getContext().getBeansOfType(OpenApiCustomiser.class);
255-
if (!CollectionUtils.isEmpty(existingOpenApiCustomisers) && existingOpenApiCustomisers.containsKey(LINKS_SCHEMA_CUSTOMISER))
256-
openApiCustomisers.ifPresent(openApiCustomisersList -> openApiCustomisersList.add(existingOpenApiCustomisers.get(LINKS_SCHEMA_CUSTOMISER)));
257225
this.springDocConfigProperties = springDocConfigProperties;
258-
operationCustomizers.ifPresent(customizers -> customizers.removeIf(Objects::isNull));
259-
this.operationCustomizers = operationCustomizers;
226+
this.springDocCustomizers=springDocCustomizers;
260227
if (springDocConfigProperties.isPreLoadingEnabled())
261228
Executors.newSingleThreadExecutor().execute(this::getOpenApi);
262-
this.openApiLocaleCustomizers = openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class);
263229
}
264230

265231
/**
@@ -389,8 +355,8 @@ protected synchronized OpenAPI getOpenApi(Locale locale) {
389355
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
390356
}
391357

392-
openApiLocaleCustomizers.values().forEach(openApiLocaleCustomizer -> openApiLocaleCustomizer.customise(openAPI, finalLocale));
393-
openApiCustomisers.ifPresent(apiCustomisers -> apiCustomisers.forEach(openApiCustomiser -> openApiCustomiser.customise(openAPI)));
358+
openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class).values().forEach(openApiLocaleCustomizer -> openApiLocaleCustomizer.customise(openAPI, finalLocale));
359+
springDocCustomizers.getOpenApiCustomizers().ifPresent(apiCustomisers -> apiCustomisers.forEach(openApiCustomiser -> openApiCustomiser.customise(openAPI)));
394360
if (!CollectionUtils.isEmpty(openAPI.getServers()) && !openAPI.getServers().equals(serversCopy))
395361
openAPIService.setServersPresent(true);
396362

@@ -608,6 +574,8 @@ else if (routerOperation.getOperationModel() != null && StringUtils.isNotBlank(r
608574
* @param locale the locale
609575
*/
610576
protected void calculatePath(RouterOperation routerOperation, Locale locale, OpenAPI openAPI) {
577+
routerOperation = customizeDataRestRouterOperation(routerOperation);
578+
611579
String operationPath = routerOperation.getPath();
612580
io.swagger.v3.oas.annotations.Operation apiOperation = routerOperation.getOperation();
613581
String[] methodConsumes = routerOperation.getConsumes();
@@ -728,7 +696,7 @@ && isPackageToScan(handlerMethod.getBeanType().getPackage())
728696
* @return whether the method should be included in the current OpenAPI definition
729697
*/
730698
protected boolean isMethodToFilter(HandlerMethod handlerMethod) {
731-
return this.methodFilters
699+
return this.springDocCustomizers.getMethodFilters()
732700
.map(Collection::stream)
733701
.map(stream -> stream.allMatch(m -> m.isMethodToInclude(handlerMethod.getMethod())))
734702
.orElse(true);
@@ -868,8 +836,8 @@ protected Set<RequestMethod> getDefaultAllowedHttpMethods() {
868836
* @return the operation
869837
*/
870838
protected Operation customizeOperation(Operation operation, HandlerMethod handlerMethod) {
871-
if (operationCustomizers.isPresent()) {
872-
List<OperationCustomizer> operationCustomizerList = operationCustomizers.get();
839+
if (springDocCustomizers.getOperationCustomizers().isPresent()) {
840+
List<OperationCustomizer> operationCustomizerList = springDocCustomizers.getOperationCustomizers().get();
873841
for (OperationCustomizer operationCustomizer : operationCustomizerList)
874842
operation = operationCustomizer.customize(operation, handlerMethod);
875843
}
@@ -883,8 +851,8 @@ protected Operation customizeOperation(Operation operation, HandlerMethod handle
883851
* @return the router operation
884852
*/
885853
protected RouterOperation customizeRouterOperation(RouterOperation routerOperation, HandlerMethod handlerMethod) {
886-
if (routerOperationCustomizers.isPresent()) {
887-
List<RouterOperationCustomizer> routerOperationCustomizerList = routerOperationCustomizers.get();
854+
if (springDocCustomizers.getRouterOperationCustomizers().isPresent()) {
855+
List<RouterOperationCustomizer> routerOperationCustomizerList = springDocCustomizers.getRouterOperationCustomizers().get();
888856
for (RouterOperationCustomizer routerOperationCustomizer : routerOperationCustomizerList) {
889857
routerOperation = routerOperationCustomizer.customize(routerOperation, handlerMethod);
890858
}
@@ -1380,4 +1348,20 @@ enum ConditionType {
13801348
*/
13811349
HEADERS
13821350
}
1351+
1352+
/**
1353+
* Customize data rest router operation router operation.
1354+
*
1355+
* @param routerOperation the router operation
1356+
* @return the router operation
1357+
*/
1358+
private RouterOperation customizeDataRestRouterOperation(RouterOperation routerOperation) {
1359+
if (springDocCustomizers.getDataRestRouterOperationCustomizers().isPresent()) {
1360+
List<DataRestRouterOperationCustomizer> dataRestRouterOperationCustomizerList = springDocCustomizers.getDataRestRouterOperationCustomizers().get();
1361+
for (DataRestRouterOperationCustomizer dataRestRouterOperationCustomizer : dataRestRouterOperationCustomizerList) {
1362+
routerOperation = dataRestRouterOperationCustomizer.customize(routerOperation);
1363+
}
1364+
}
1365+
return routerOperation;
1366+
}
13831367
}

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

+31
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,18 @@
5252
import org.springdoc.core.customizers.ActuatorOpenApiCustomizer;
5353
import org.springdoc.core.customizers.ActuatorOperationCustomizer;
5454
import org.springdoc.core.customizers.DataRestDelegatingMethodParameterCustomizer;
55+
import org.springdoc.core.customizers.DataRestRouterOperationCustomizer;
5556
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
5657
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
5758
import org.springdoc.core.customizers.GlobalOperationCustomizer;
5859
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
60+
import org.springdoc.core.customizers.OpenApiCustomiser;
61+
import org.springdoc.core.customizers.OperationCustomizer;
5962
import org.springdoc.core.customizers.PropertyCustomizer;
63+
import org.springdoc.core.customizers.RouterOperationCustomizer;
6064
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
65+
import org.springdoc.core.customizers.SpringDocCustomizers;
66+
import org.springdoc.core.filters.OpenApiMethodFilter;
6167
import org.springdoc.core.providers.ActuatorProvider;
6268
import org.springdoc.core.providers.CloudFunctionProvider;
6369
import org.springdoc.core.providers.JavadocProvider;
@@ -670,4 +676,29 @@ public ResponseEntity<ErrorMessage> handleNoHandlerFound(OpenApiResourceNotFound
670676
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(new ErrorMessage(e.getMessage()));
671677
}
672678
}
679+
680+
/**
681+
* Spring doc customizers spring doc customizers.
682+
*
683+
* @param openApiCustomizers the open api customizers
684+
* @param operationCustomizers the operation customizers
685+
* @param routerOperationCustomizers the router operation customizers
686+
* @param dataRestRouterOperationCustomizers the data rest router operation customizers
687+
* @param methodFilters the method filters
688+
* @return the spring doc customizers
689+
*/
690+
@Bean
691+
@ConditionalOnMissingBean
692+
@Lazy(false)
693+
public SpringDocCustomizers springDocCustomizers(Optional<List<OpenApiCustomiser>> openApiCustomizers,
694+
Optional<List<OperationCustomizer>> operationCustomizers,
695+
Optional<List<RouterOperationCustomizer>> routerOperationCustomizers,
696+
Optional<List<DataRestRouterOperationCustomizer>> dataRestRouterOperationCustomizers,
697+
Optional<List<OpenApiMethodFilter>> methodFilters){
698+
return new SpringDocCustomizers(openApiCustomizers,
699+
operationCustomizers,
700+
routerOperationCustomizers,
701+
dataRestRouterOperationCustomizers,
702+
methodFilters);
703+
}
673704
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.springdoc.core.customizers;
2+
3+
import org.springdoc.core.fn.RouterOperation;
4+
5+
/**
6+
* The interface Data rest router operation customizer.
7+
*
8+
* @author bnasslahsen
9+
*/
10+
@FunctionalInterface
11+
public interface DataRestRouterOperationCustomizer {
12+
13+
/**
14+
* Customize router operation.
15+
*
16+
* @param routerOperation input operation
17+
* @return customized router operation
18+
*/
19+
RouterOperation customize(RouterOperation routerOperation);
20+
21+
}

0 commit comments

Comments
 (0)