Skip to content

Commit 2545498

Browse files
committed
Add support for Spring Cloud Function Web. Fixes #1299
1 parent f3df88d commit 2545498

File tree

71 files changed

+1853
-360
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1853
-360
lines changed

pom.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
<jjwt.version>0.9.1</jjwt.version>
8080
<spring-native.version>0.11.0</spring-native.version>
8181
<therapi-runtime-javadoc.version>0.12.0</therapi-runtime-javadoc.version>
82+
<spring-cloud.version>2021.0.0</spring-cloud.version>
8283
</properties>
8384

8485
<dependencyManagement>
@@ -211,6 +212,13 @@
211212
<artifactId>springdoc-openapi-javadoc</artifactId>
212213
<version>${version}</version>
213214
</dependency>
215+
<dependency>
216+
<groupId>org.springframework.cloud</groupId>
217+
<artifactId>spring-cloud-dependencies</artifactId>
218+
<version>${spring-cloud.version}</version>
219+
<type>pom</type>
220+
<scope>import</scope>
221+
</dependency>
214222
</dependencies>
215223
</dependencyManagement>
216224
<dependencies>

springdoc-openapi-common/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@
5252
<artifactId>spring-data-commons</artifactId>
5353
<optional>true</optional>
5454
</dependency>
55+
<!-- For Spring Cloud Function Support -->
56+
<dependency>
57+
<groupId>org.springframework.cloud</groupId>
58+
<artifactId>spring-cloud-function-web</artifactId>
59+
<optional>true</optional>
60+
</dependency>
5561
</dependencies>
5662
<build>
5763
<plugins>

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

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,22 +76,23 @@
7676
import org.springdoc.api.mixins.SortedOpenAPIMixin;
7777
import org.springdoc.api.mixins.SortedSchemaMixin;
7878
import org.springdoc.core.AbstractRequestService;
79-
import org.springdoc.core.ActuatorProvider;
8079
import org.springdoc.core.GenericParameterService;
8180
import org.springdoc.core.GenericResponseService;
82-
import org.springdoc.core.JavadocProvider;
8381
import org.springdoc.core.MethodAttributes;
8482
import org.springdoc.core.OpenAPIService;
8583
import org.springdoc.core.OperationService;
8684
import org.springdoc.core.SpringDocConfigProperties;
8785
import org.springdoc.core.SpringDocConfigProperties.GroupConfig;
86+
import org.springdoc.core.SpringDocProviders;
8887
import org.springdoc.core.annotations.RouterOperations;
8988
import org.springdoc.core.customizers.OpenApiCustomiser;
9089
import org.springdoc.core.customizers.OpenApiLocaleCustomizer;
9190
import org.springdoc.core.customizers.OperationCustomizer;
9291
import org.springdoc.core.fn.AbstractRouterFunctionVisitor;
9392
import org.springdoc.core.fn.RouterFunctionData;
9493
import org.springdoc.core.fn.RouterOperation;
94+
import org.springdoc.core.providers.ActuatorProvider;
95+
import org.springdoc.core.providers.JavadocProvider;
9596

9697
import org.springframework.aop.support.AopUtils;
9798
import org.springframework.beans.factory.ObjectFactory;
@@ -152,11 +153,6 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
152153
*/
153154
protected final SpringDocConfigProperties springDocConfigProperties;
154155

155-
/**
156-
* The Actuator provider.
157-
*/
158-
protected final Optional<ActuatorProvider> optionalActuatorProvider;
159-
160156
/**
161157
* The Request builder.
162158
*/
@@ -202,6 +198,11 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
202198
*/
203199
private final Map<String, OpenApiLocaleCustomizer> openApiLocaleCustomizers;
204200

201+
/**
202+
* The Spring doc providers.
203+
*/
204+
protected final SpringDocProviders springDocProviders;
205+
205206
static {
206207
try {
207208
modelAndViewClass = Class.forName("org.springframework.web.servlet.ModelAndView");
@@ -213,7 +214,6 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
213214

214215
/**
215216
* Instantiates a new Abstract open api resource.
216-
*
217217
* @param groupName the group name
218218
* @param openAPIBuilderObjectFactory the open api builder object factory
219219
* @param requestBuilder the request builder
@@ -222,15 +222,14 @@ public abstract class AbstractOpenApiResource extends SpecFilter {
222222
* @param operationCustomizers the operation customizers
223223
* @param openApiCustomisers the open api customisers
224224
* @param springDocConfigProperties the spring doc config properties
225-
* @param actuatorProvider the actuator provider
225+
* @param springDocProviders the spring doc providers
226226
*/
227227
protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService> openAPIBuilderObjectFactory,
228228
AbstractRequestService requestBuilder,
229229
GenericResponseService responseBuilder, OperationService operationParser,
230230
Optional<List<OperationCustomizer>> operationCustomizers,
231231
Optional<List<OpenApiCustomiser>> openApiCustomisers,
232-
SpringDocConfigProperties springDocConfigProperties,
233-
Optional<ActuatorProvider> actuatorProvider) {
232+
SpringDocConfigProperties springDocConfigProperties, SpringDocProviders springDocProviders) {
234233
super();
235234
this.groupName = Objects.requireNonNull(groupName, "groupName");
236235
this.openAPIBuilderObjectFactory = openAPIBuilderObjectFactory;
@@ -239,14 +238,14 @@ protected AbstractOpenApiResource(String groupName, ObjectFactory<OpenAPIService
239238
this.responseBuilder = responseBuilder;
240239
this.operationParser = operationParser;
241240
this.openApiCustomisers = openApiCustomisers;
241+
this.springDocProviders = springDocProviders;
242242
//add the default customizers
243243
Map<String, OpenApiCustomiser> existingOpenApiCustomisers = openAPIService.getContext().getBeansOfType(OpenApiCustomiser.class);
244244
if (!CollectionUtils.isEmpty(existingOpenApiCustomisers) && existingOpenApiCustomisers.containsKey(LINKS_SCHEMA_CUSTOMISER))
245245
openApiCustomisers.ifPresent(openApiCustomisersList -> openApiCustomisersList.add(existingOpenApiCustomisers.get(LINKS_SCHEMA_CUSTOMISER)));
246246
this.springDocConfigProperties = springDocConfigProperties;
247247
operationCustomizers.ifPresent(customizers -> customizers.removeIf(Objects::isNull));
248248
this.operationCustomizers = operationCustomizers;
249-
this.optionalActuatorProvider = actuatorProvider;
250249
if (springDocConfigProperties.isPreLoadingEnabled())
251250
Executors.newSingleThreadExecutor().execute(this::getOpenApi);
252251
this.openApiLocaleCustomizers = openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class);
@@ -321,6 +320,13 @@ protected synchronized OpenAPI getOpenApi(Locale locale) {
321320
responseBuilder.buildGenericResponse(openApi.getComponents(), findControllerAdvice, finalLocale);
322321
}
323322
getPaths(mappingsMap, finalLocale);
323+
324+
if (springDocProviders.getSpringCloudFunctionProvider().isPresent()) {
325+
List<RouterOperation> routerOperationList = springDocProviders.getSpringCloudFunctionProvider().get().getRouterOperations(openApi);
326+
if (!CollectionUtils.isEmpty(routerOperationList))
327+
this.calculatePath(routerOperationList, locale);
328+
}
329+
324330
if (!CollectionUtils.isEmpty(openApi.getServers()))
325331
openAPIService.setServersPresent(true);
326332
openAPIService.updateServers(openApi);
@@ -1117,6 +1123,7 @@ else if (existingOperation != null) {
11171123

11181124
/**
11191125
* Init open api builder.
1126+
* @param locale the locale
11201127
*/
11211128
protected void initOpenAPIBuilder(Locale locale) {
11221129
locale = locale == null ? Locale.getDefault() : locale;
@@ -1157,8 +1164,8 @@ protected URI getActuatorURI(String scheme, String host) {
11571164
int port;
11581165
String path;
11591166
URI uri = null;
1160-
if (optionalActuatorProvider.isPresent()) {
1161-
ActuatorProvider actuatorProvider = optionalActuatorProvider.get();
1167+
if (springDocProviders.getActuatorProvider().isPresent()) {
1168+
ActuatorProvider actuatorProvider = springDocProviders.getActuatorProvider().get();
11621169
if (ACTUATOR_DEFAULT_GROUP.equals(this.groupName)) {
11631170
port = actuatorProvider.getActuatorPort();
11641171
path = actuatorProvider.getActuatorPath();
@@ -1187,7 +1194,7 @@ protected URI getActuatorURI(String scheme, String host) {
11871194
* @return the boolean
11881195
*/
11891196
protected boolean isShowActuator() {
1190-
return springDocConfigProperties.isShowActuator() && optionalActuatorProvider.isPresent();
1197+
return springDocConfigProperties.isShowActuator() && springDocProviders.getActuatorProvider().isPresent();
11911198
}
11921199

11931200
/**
@@ -1198,7 +1205,7 @@ protected boolean isShowActuator() {
11981205
* @return the boolean
11991206
*/
12001207
protected boolean isActuatorRestController(String operationPath, HandlerMethod handlerMethod) {
1201-
return isShowActuator() && optionalActuatorProvider.get().isRestController(operationPath, handlerMethod);
1208+
return isShowActuator() && springDocProviders.getActuatorProvider().get().isRestController(operationPath, handlerMethod);
12021209
}
12031210

12041211
/**
@@ -1281,6 +1288,11 @@ enum ConditionType {
12811288
HEADERS
12821289
}
12831290

1291+
/**
1292+
* Sort output.
1293+
*
1294+
* @param objectMapper the object mapper
1295+
*/
12841296
private void sortOutput(ObjectMapper objectMapper) {
12851297
objectMapper.configure(SerializationFeature.ORDER_MAP_ENTRIES_BY_KEYS, true);
12861298
objectMapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
import org.apache.commons.lang3.StringUtils;
6262
import org.apache.commons.lang3.reflect.FieldUtils;
6363
import org.springdoc.core.customizers.ParameterCustomizer;
64+
import org.springdoc.core.providers.JavadocProvider;
6465

6566
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
6667
import org.springframework.core.MethodParameter;
@@ -249,7 +250,7 @@ public Operation build(HandlerMethod handlerMethod, RequestMethod requestMethod,
249250
io.swagger.v3.oas.annotations.Parameter.class);
250251

251252
final String pName = methodParameter.getParameterName();
252-
ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder, methodAttributes.getLocale());
253+
ParameterInfo parameterInfo = new ParameterInfo(pName, methodParameter, parameterBuilder);
253254

254255
if (parameterDoc == null)
255256
parameterDoc = parametersDocMap.get(parameterInfo.getpName());

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.slf4j.Logger;
5151
import org.slf4j.LoggerFactory;
5252
import org.springdoc.core.customizers.DelegatingMethodParameterCustomizer;
53+
import org.springdoc.core.providers.WebConversionServiceProvider;
5354

5455
import org.springframework.beans.factory.config.BeanExpressionContext;
5556
import org.springframework.beans.factory.config.BeanExpressionResolver;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
import org.apache.commons.lang3.StringUtils;
5050
import org.slf4j.Logger;
5151
import org.slf4j.LoggerFactory;
52+
import org.springdoc.core.providers.JavadocProvider;
5253

5354
import org.springframework.core.MethodParameter;
5455
import org.springframework.core.ResolvableType;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import io.swagger.v3.oas.models.responses.ApiResponse;
4949
import io.swagger.v3.oas.models.responses.ApiResponses;
5050
import org.apache.commons.lang3.StringUtils;
51+
import org.springdoc.core.providers.JavadocProvider;
5152

5253
import org.springframework.core.annotation.AnnotationUtils;
5354
import org.springframework.util.CollectionUtils;

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
package org.springdoc.core;
2222

2323
import java.lang.reflect.Parameter;
24-
import java.util.Locale;
2524

2625
import io.swagger.v3.oas.annotations.enums.ParameterIn;
2726
import org.apache.commons.lang3.StringUtils;
@@ -87,9 +86,8 @@ public class ParameterInfo {
8786
* @param pName the parameter name
8887
* @param methodParameter the method parameter
8988
* @param genericParameterService the parameter builder
90-
* @param locale the locale
9189
*/
92-
public ParameterInfo(String pName, MethodParameter methodParameter, GenericParameterService genericParameterService, Locale locale) {
90+
public ParameterInfo(String pName, MethodParameter methodParameter, GenericParameterService genericParameterService) {
9391
RequestHeader requestHeader = methodParameter.getParameterAnnotation(RequestHeader.class);
9492
RequestParam requestParam = methodParameter.getParameterAnnotation(RequestParam.class);
9593
PathVariable pathVar = methodParameter.getParameterAnnotation(PathVariable.class);

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

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@
5151
import org.springdoc.core.customizers.OpenApiCustomiser;
5252
import org.springdoc.core.customizers.OperationCustomizer;
5353
import org.springdoc.core.customizers.PropertyCustomizer;
54+
import org.springdoc.core.providers.ActuatorProvider;
55+
import org.springdoc.core.providers.CloudFunctionProvider;
56+
import org.springdoc.core.providers.JavadocProvider;
57+
import org.springdoc.core.providers.RepositoryRestResourceProvider;
58+
import org.springdoc.core.providers.RouterFunctionProvider;
59+
import org.springdoc.core.providers.SecurityOAuth2Provider;
60+
import org.springdoc.core.providers.WebConversionServiceProvider;
61+
import org.springdoc.core.providers.impl.SpringCloudFunctionProvider;
5462

5563
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
5664
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@@ -63,6 +71,8 @@
6371
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
6472
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
6573
import org.springframework.boot.autoconfigure.web.format.WebConversionService;
74+
import org.springframework.cloud.function.context.FunctionCatalog;
75+
import org.springframework.cloud.function.web.function.FunctionEndpointInitializer;
6676
import org.springframework.context.ApplicationContext;
6777
import org.springframework.context.MessageSource;
6878
import org.springframework.context.annotation.Bean;
@@ -351,6 +361,24 @@ static BeanFactoryPostProcessor springdocBeanFactoryPostProcessor2() {
351361
return SpringdocBeanFactoryConfigurer::initBeanFactoryPostProcessor;
352362
}
353363

364+
365+
/**
366+
* Spring doc providers spring doc providers.
367+
*
368+
* @param actuatorProvider the actuator provider
369+
* @param springCloudFunctionProvider the spring cloud function provider
370+
* @param springSecurityOAuth2Provider the spring security o auth 2 provider
371+
* @param repositoryRestResourceProvider the repository rest resource provider
372+
* @param routerFunctionProvider the router function provider
373+
* @return the spring doc providers
374+
*/
375+
@Bean
376+
@ConditionalOnMissingBean
377+
@Lazy(false)
378+
SpringDocProviders springDocProviders(Optional<ActuatorProvider> actuatorProvider, Optional<CloudFunctionProvider> springCloudFunctionProvider, Optional<SecurityOAuth2Provider> springSecurityOAuth2Provider, Optional<RepositoryRestResourceProvider> repositoryRestResourceProvider, Optional<RouterFunctionProvider> routerFunctionProvider) {
379+
return new SpringDocProviders(actuatorProvider, springCloudFunctionProvider, springSecurityOAuth2Provider, repositoryRestResourceProvider, routerFunctionProvider);
380+
}
381+
354382
/**
355383
* The type Open api resource advice.
356384
* @author bnasslashen
@@ -462,4 +490,27 @@ PageableOpenAPIConverter pageableOpenAPIConverter() {
462490
}
463491
}
464492

493+
/**
494+
* The type Spring doc function catalog configuration.
495+
*/
496+
@ConditionalOnClass(FunctionEndpointInitializer.class)
497+
static class SpringDocFunctionCatalogConfiguration {
498+
499+
/**
500+
* Spring cloud function provider spring cloud function provider.
501+
*
502+
* @param functionCatalog the function catalog
503+
* @param genericResponseService the generic response service
504+
* @param springDocConfigProperties the spring doc config properties
505+
* @param applicationContext the application context
506+
* @return the spring cloud function provider
507+
*/
508+
@Bean
509+
@ConditionalOnMissingBean
510+
@ConditionalOnWebApplication
511+
@Lazy(false)
512+
CloudFunctionProvider springCloudFunctionProvider(Optional<FunctionCatalog> functionCatalog, GenericResponseService genericResponseService, SpringDocConfigProperties springDocConfigProperties, ApplicationContext applicationContext) {
513+
return new SpringCloudFunctionProvider(functionCatalog, genericResponseService, springDocConfigProperties, applicationContext);
514+
}
515+
}
465516
}

0 commit comments

Comments
 (0)