Skip to content

Commit 5d29794

Browse files
author
bnasslahsen
committed
Initial WebMvc.fn support
1 parent e9daa50 commit 5d29794

File tree

12 files changed

+380
-55
lines changed

12 files changed

+380
-55
lines changed

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

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
import io.swagger.v3.oas.models.PathItem.HttpMethod;
4646
import io.swagger.v3.oas.models.Paths;
4747
import io.swagger.v3.oas.models.responses.ApiResponses;
48+
import org.apache.commons.lang3.ArrayUtils;
49+
import org.apache.commons.lang3.StringUtils;
4850
import org.slf4j.Logger;
4951
import org.slf4j.LoggerFactory;
5052
import org.springdoc.core.AbstractRequestBuilder;
@@ -54,9 +56,11 @@
5456
import org.springdoc.core.OperationBuilder;
5557
import org.springdoc.core.SpringDocConfigProperties;
5658
import org.springdoc.core.SpringDocConfigProperties.GroupConfig;
59+
import org.springdoc.core.annotations.RouterOperation;
5760
import org.springdoc.core.customizers.OpenApiCustomiser;
5861
import org.springdoc.core.customizers.OperationCustomizer;
5962

63+
import org.springframework.context.ApplicationContext;
6064
import org.springframework.core.annotation.AnnotatedElementUtils;
6165
import org.springframework.core.annotation.AnnotationUtils;
6266
import org.springframework.util.AntPathMatcher;
@@ -237,7 +241,6 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
237241
protected void calculatePath(String operationPath, Set<RequestMethod> requestMethods, io.swagger.v3.oas.annotations.Operation apiOperation, String[] methodConsumes, String[] methodProduces) {
238242
OpenAPI openAPI = openAPIBuilder.getCalculatedOpenAPI();
239243
Paths paths = openAPI.getPaths();
240-
241244
for (RequestMethod requestMethod : requestMethods) {
242245
MethodAttributes methodAttributes = new MethodAttributes(springDocConfigProperties.getDefaultConsumesMediaType(), springDocConfigProperties.getDefaultProducesMediaType(), methodConsumes, methodProduces);
243246
Operation operation = new Operation();
@@ -252,6 +255,43 @@ protected void calculatePath(HandlerMethod handlerMethod, String operationPath,
252255
this.calculatePath(handlerMethod, operationPath,requestMethods,null, null);
253256
}
254257

258+
protected void calculatePath(List<RouterOperation> routerOperationList) {
259+
ApplicationContext applicationContext = openAPIBuilder.getContext();
260+
if (!CollectionUtils.isEmpty(routerOperationList)) {
261+
for (RouterOperation routerOperation : routerOperationList) {
262+
if (!Void.class.equals(routerOperation.beanClass())) {
263+
Object handlerBean = applicationContext.getBean(routerOperation.beanClass());
264+
HandlerMethod handlerMethod = null;
265+
if (StringUtils.isNotBlank(routerOperation.beanMethod())) {
266+
try {
267+
if (ArrayUtils.isEmpty(routerOperation.parameterTypes())) {
268+
Optional<Method> methodOptional = Arrays.stream(handlerBean.getClass().getDeclaredMethods())
269+
.filter(method -> routerOperation.beanMethod().equals(method.getName()) && method.getParameters().length == 0)
270+
.findAny();
271+
if (!methodOptional.isPresent())
272+
methodOptional = Arrays.stream(handlerBean.getClass().getDeclaredMethods())
273+
.filter(method1 -> routerOperation.beanMethod().equals(method1.getName()))
274+
.findAny();
275+
if (methodOptional.isPresent())
276+
handlerMethod = new HandlerMethod(handlerBean, methodOptional.get());
277+
}
278+
else
279+
handlerMethod = new HandlerMethod(handlerBean, routerOperation.beanMethod(), routerOperation.parameterTypes());
280+
}
281+
catch (NoSuchMethodException e) {
282+
LOGGER.error(e.getMessage());
283+
}
284+
if (handlerMethod != null && isPackageToScan(handlerMethod.getBeanType().getPackage().getName()) && isPathToMatch(routerOperation.path()))
285+
calculatePath(handlerMethod, routerOperation.path(), new HashSet<>(Arrays.asList(routerOperation.method())), routerOperation.consumes(), routerOperation.produces());
286+
}
287+
}
288+
else if (StringUtils.isNotBlank(routerOperation.operation().operationId())) {
289+
calculatePath(routerOperation.path(), new HashSet<>(Arrays.asList(routerOperation.method())), routerOperation.operation(), routerOperation.consumes(), routerOperation.produces());
290+
}
291+
}
292+
}
293+
}
294+
255295
private void calculateJsonView(io.swagger.v3.oas.annotations.Operation apiOperation,
256296
MethodAttributes methodAttributes, Method method) {
257297
JsonView jsonViewAnnotation;

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,4 +462,8 @@ public OpenAPI getCalculatedOpenAPI() {
462462
public void resetCalculatedOpenAPI() {
463463
this.calculatedOpenAPI = null;
464464
}
465+
466+
public ApplicationContext getContext() {
467+
return context;
468+
}
465469
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*/
1818

19-
package org.springdoc.webflux.annotations;
19+
package org.springdoc.core.annotations;
2020

2121

2222
import java.lang.annotation.ElementType;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*
1717
*/
1818

19-
package org.springdoc.webflux.annotations;
19+
package org.springdoc.core.annotations;
2020

2121
import java.lang.annotation.Inherited;
2222
import java.lang.annotation.Retention;

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

Lines changed: 3 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,8 @@
1818

1919
package org.springdoc.webflux.api;
2020

21-
import java.lang.reflect.Method;
2221
import java.util.ArrayList;
2322
import java.util.Arrays;
24-
import java.util.HashSet;
2523
import java.util.LinkedHashMap;
2624
import java.util.List;
2725
import java.util.Map;
@@ -34,28 +32,23 @@
3432
import io.swagger.v3.core.util.Yaml;
3533
import io.swagger.v3.oas.annotations.Operation;
3634
import io.swagger.v3.oas.models.OpenAPI;
37-
import org.apache.commons.lang3.ArrayUtils;
38-
import org.apache.commons.lang3.StringUtils;
39-
import org.slf4j.Logger;
40-
import org.slf4j.LoggerFactory;
4135
import org.springdoc.api.AbstractOpenApiResource;
4236
import org.springdoc.core.AbstractRequestBuilder;
4337
import org.springdoc.core.GenericResponseBuilder;
4438
import org.springdoc.core.OpenAPIBuilder;
4539
import org.springdoc.core.OperationBuilder;
4640
import org.springdoc.core.SpringDocConfigProperties;
41+
import org.springdoc.core.annotations.RouterOperation;
42+
import org.springdoc.core.annotations.RouterOperations;
4743
import org.springdoc.core.customizers.OpenApiCustomiser;
4844
import org.springdoc.core.customizers.OperationCustomizer;
49-
import org.springdoc.webflux.annotations.RouterOperation;
50-
import org.springdoc.webflux.annotations.RouterOperations;
5145
import reactor.core.publisher.Mono;
5246

5347
import org.springframework.beans.factory.annotation.Autowired;
5448
import org.springframework.beans.factory.annotation.Value;
5549
import org.springframework.context.ApplicationContext;
5650
import org.springframework.http.MediaType;
5751
import org.springframework.http.server.reactive.ServerHttpRequest;
58-
import org.springframework.util.CollectionUtils;
5952
import org.springframework.web.bind.annotation.GetMapping;
6053
import org.springframework.web.bind.annotation.RequestMethod;
6154
import org.springframework.web.bind.annotation.RestController;
@@ -76,8 +69,6 @@
7669
@RestController
7770
public class OpenApiResource extends AbstractOpenApiResource {
7871

79-
private static final Logger LOGGER = LoggerFactory.getLogger(OpenApiResource.class);
80-
8172
private final RequestMappingInfoHandlerMapping requestMappingHandlerMapping;
8273

8374
@Autowired
@@ -148,7 +139,6 @@ protected void getPaths(Map<String, Object> restControllers) {
148139
private void getRouterFunctionPaths() {
149140
ApplicationContext applicationContext = requestMappingHandlerMapping.getApplicationContext();
150141
Map<String, RouterFunction> routerBeans = applicationContext.getBeansOfType(RouterFunction.class);
151-
152142
for (Map.Entry<String, RouterFunction> entry : routerBeans.entrySet()) {
153143
List<RouterOperation> routerOperationList = new ArrayList<>();
154144
RouterOperations routerOperations = applicationContext.findAnnotationOnBean(entry.getKey(), RouterOperations.class);
@@ -158,40 +148,7 @@ private void getRouterFunctionPaths() {
158148
}
159149
else
160150
routerOperationList.addAll(Arrays.asList(routerOperations.value()));
161-
162-
if (!CollectionUtils.isEmpty(routerOperationList)) {
163-
for (RouterOperation routerOperation : routerOperationList) {
164-
if (!Void.class.equals(routerOperation.beanClass())) {
165-
Object handlerBean = applicationContext.getBean(routerOperation.beanClass());
166-
HandlerMethod handlerMethod = null;
167-
if (StringUtils.isNotBlank(routerOperation.beanMethod())) {
168-
try {
169-
if (ArrayUtils.isEmpty(routerOperation.parameterTypes())) {
170-
Optional<Method> methodOptional = Arrays.stream(handlerBean.getClass().getDeclaredMethods())
171-
.filter(method1 -> routerOperation.beanMethod().equals(method1.getName()) && method1.getParameters().length == 0)
172-
.findAny();
173-
if (!methodOptional.isPresent())
174-
methodOptional = Arrays.stream(handlerBean.getClass().getDeclaredMethods())
175-
.filter(method1 -> routerOperation.beanMethod().equals(method1.getName()))
176-
.findAny();
177-
if (methodOptional.isPresent())
178-
handlerMethod = new HandlerMethod(handlerBean, methodOptional.get());
179-
}
180-
else
181-
handlerMethod = new HandlerMethod(handlerBean, routerOperation.beanMethod(), routerOperation.parameterTypes());
182-
}
183-
catch (NoSuchMethodException e) {
184-
LOGGER.error(e.getMessage());
185-
}
186-
if (handlerMethod != null && isPackageToScan(handlerMethod.getBeanType().getPackage().getName()) && isPathToMatch(routerOperation.path()))
187-
calculatePath(handlerMethod, routerOperation.path(), new HashSet<>(Arrays.asList(routerOperation.method())), routerOperation.consumes(), routerOperation.produces());
188-
}
189-
}
190-
else if (StringUtils.isNotBlank(routerOperation.operation().operationId())) {
191-
calculatePath(routerOperation.path(), new HashSet<>(Arrays.asList(routerOperation.method())), routerOperation.operation(), routerOperation.consumes(), routerOperation.produces());
192-
}
193-
}
194-
}
151+
calculatePath(routerOperationList);
195152
}
196153
}
197154

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app69/RoutingConfiguration.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package test.org.springdoc.api.app69;
22

3-
import org.springdoc.webflux.annotations.RouterOperation;
4-
import org.springdoc.webflux.annotations.RouterOperations;
3+
import org.springdoc.core.annotations.RouterOperation;
4+
import org.springdoc.core.annotations.RouterOperations;
55

66
import org.springframework.context.annotation.Bean;
77
import org.springframework.context.annotation.Configuration;

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app70/RouteConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package test.org.springdoc.api.app70;
22

3-
import org.springdoc.webflux.annotations.RouterOperation;
4-
import org.springdoc.webflux.annotations.RouterOperations;
3+
import org.springdoc.core.annotations.RouterOperation;
4+
import org.springdoc.core.annotations.RouterOperations;
55
import reactor.core.publisher.Mono;
66

77
import org.springframework.context.annotation.Bean;

springdoc-openapi-webflux-core/src/test/java/test/org/springdoc/api/app71/EmployeeFunctionalConfig.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
import io.swagger.v3.oas.annotations.media.Content;
77
import io.swagger.v3.oas.annotations.media.Schema;
88
import io.swagger.v3.oas.annotations.responses.ApiResponse;
9-
import org.springdoc.webflux.annotations.RouterOperation;
10-
import org.springdoc.webflux.annotations.RouterOperations;
9+
import org.springdoc.core.annotations.RouterOperation;
10+
import org.springdoc.core.annotations.RouterOperations;
1111

1212
import org.springframework.context.annotation.Bean;
1313
import org.springframework.context.annotation.Configuration;

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
package org.springdoc.webmvc.api;
2020

21+
import java.util.ArrayList;
22+
import java.util.Arrays;
2123
import java.util.HashSet;
2224
import java.util.LinkedHashMap;
2325
import java.util.List;
@@ -40,11 +42,14 @@
4042
import org.springdoc.core.OperationBuilder;
4143
import org.springdoc.core.SecurityOAuth2Provider;
4244
import org.springdoc.core.SpringDocConfigProperties;
45+
import org.springdoc.core.annotations.RouterOperation;
46+
import org.springdoc.core.annotations.RouterOperations;
4347
import org.springdoc.core.customizers.OpenApiCustomiser;
4448
import org.springdoc.core.customizers.OperationCustomizer;
4549

4650
import org.springframework.beans.factory.annotation.Autowired;
4751
import org.springframework.beans.factory.annotation.Value;
52+
import org.springframework.context.ApplicationContext;
4853
import org.springframework.core.annotation.AnnotationUtils;
4954
import org.springframework.http.MediaType;
5055
import org.springframework.web.bind.annotation.GetMapping;
@@ -53,6 +58,7 @@
5358
import org.springframework.web.bind.annotation.RestController;
5459
import org.springframework.web.method.HandlerMethod;
5560
import org.springframework.web.servlet.ModelAndView;
61+
import org.springframework.web.servlet.function.RouterFunction;
5662
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
5763
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
5864
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
@@ -160,6 +166,23 @@ && isPathToMatch(operationPath)) {
160166
}
161167
}
162168
}
169+
getRouterFunctionPaths();
170+
}
171+
172+
private void getRouterFunctionPaths() {
173+
ApplicationContext applicationContext = requestMappingHandlerMapping.getApplicationContext();
174+
Map<String, RouterFunction> routerBeans = applicationContext.getBeansOfType(RouterFunction.class);
175+
for (Map.Entry<String, RouterFunction> entry : routerBeans.entrySet()) {
176+
List<RouterOperation> routerOperationList = new ArrayList<>();
177+
RouterOperations routerOperations = applicationContext.findAnnotationOnBean(entry.getKey(), RouterOperations.class);
178+
if (routerOperations == null) {
179+
RouterOperation routerOperation = applicationContext.findAnnotationOnBean(entry.getKey(), RouterOperation.class);
180+
routerOperationList.add(routerOperation);
181+
}
182+
else
183+
routerOperationList.addAll(Arrays.asList(routerOperations.value()));
184+
calculatePath(routerOperationList);
185+
}
163186
}
164187

165188
protected boolean isRestController(Map<String, Object> restControllers, HandlerMethod handlerMethod,

0 commit comments

Comments
 (0)