Skip to content

Commit

Permalink
Springdoc OpenApi Annotations @ExtensionProperty Not Evaluating Prope…
Browse files Browse the repository at this point in the history
…rties from application.yml. Fixes #2461
  • Loading branch information
bnasslahsen committed Feb 28, 2024
1 parent b88a3e4 commit 577938e
Show file tree
Hide file tree
Showing 16 changed files with 556 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,23 @@

package org.springdoc.core.customizers;

import io.swagger.v3.oas.models.*;
import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.StringUtils;

import org.springframework.core.env.PropertyResolver;
import org.springframework.util.CollectionUtils;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

import static org.springdoc.core.utils.Constants.SPRINGDOC_SPEC_PROPERTIES_PREFIX;

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,11 @@ public static class ApiDocs {
*/
private boolean resolveSchemaProperties;

/**
* The Resolve extensions properties.
*/
private boolean resolveExtensionsProperties;

/**
* The Groups.
*/
Expand Down Expand Up @@ -1370,6 +1375,24 @@ public String getVersion() {
return version;
}
}

/**
* Is resolve extensions properties boolean.
*
* @return the boolean
*/
public boolean isResolveExtensionsProperties() {
return resolveExtensionsProperties;
}

/**
* Sets resolve extensions properties.
*
* @param resolveExtensionsProperties the resolve extensions properties
*/
public void setResolveExtensionsProperties(boolean resolveExtensionsProperties) {
this.resolveExtensionsProperties = resolveExtensionsProperties;
}
}

/**
Expand Down Expand Up @@ -1722,4 +1745,6 @@ public boolean isOpenapi31() {
return true;
return false;
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ public Parameter buildParameterFromDoc(io.swagger.v3.oas.annotations.Parameter p
setSchema(parameterDoc, components, jsonView, parameter);

setExamples(parameterDoc, parameter);
setExtensions(parameterDoc, parameter);
setExtensions(parameterDoc, parameter, locale);
setParameterStyle(parameter, parameterDoc);
setParameterExplode(parameter, parameterDoc);

Expand Down Expand Up @@ -460,12 +460,19 @@ private void setExamples(io.swagger.v3.oas.annotations.Parameter parameterDoc, P
* Sets extensions.
*
* @param parameterDoc the parameter doc
* @param parameter the parameter
* @param parameter the parameter
* @param locale the locale
*/
private void setExtensions(io.swagger.v3.oas.annotations.Parameter parameterDoc, Parameter parameter) {
private void setExtensions(io.swagger.v3.oas.annotations.Parameter parameterDoc, Parameter parameter, Locale locale) {
if (parameterDoc.extensions().length > 0) {
Map<String, Object> extensionMap = AnnotationsUtils.getExtensions(propertyResolverUtils.isOpenapi31(), parameterDoc.extensions());
extensionMap.forEach(parameter::addExtension);
if (propertyResolverUtils.isResolveExtensionsProperties()) {
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, extensionMap);
extensionsResolved.forEach(parameter::addExtension);
}
else {
extensionMap.forEach(parameter::addExtension);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@
import org.springdoc.core.parsers.ReturnTypeParser;
import org.springdoc.core.properties.SpringDocConfigProperties;
import org.springdoc.core.providers.JavadocProvider;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.utils.PropertyResolverUtils;
import org.springdoc.core.utils.SpringDocAnnotationsUtils;

Expand Down Expand Up @@ -254,7 +253,7 @@ public ApiResponses build(Components components, HandlerMethod handlerMethod, Op
apiResponsesFromDoc.forEach(apiResponses::addApiResponse);
// for each one build ApiResponse and add it to existing responses
// Fill api Responses
computeResponseFromDoc(components, handlerMethod.getReturnType(), apiResponses, methodAttributes, springDocConfigProperties.isOpenapi31());
computeResponseFromDoc(components, handlerMethod.getReturnType(), apiResponses, methodAttributes, springDocConfigProperties.isOpenapi31(),methodAttributes.getLocale() );
buildApiResponses(components, handlerMethod.getReturnType(), apiResponses, methodAttributes);
return apiResponses;
}
Expand Down Expand Up @@ -329,7 +328,7 @@ public void buildGenericResponse(Components components, Map<String, Object> find
JavadocProvider javadocProvider = operationService.getJavadocProvider();
methodAttributes.setJavadocReturn(javadocProvider.getMethodJavadocReturn(methodParameter.getMethod()));
}
Map<String, ApiResponse> apiResponses = computeResponseFromDoc(components, methodParameter, apiResponsesOp, methodAttributes, springDocConfigProperties.isOpenapi31());
Map<String, ApiResponse> apiResponses = computeResponseFromDoc(components, methodParameter, apiResponsesOp, methodAttributes, springDocConfigProperties.isOpenapi31(), locale);
buildGenericApiResponses(components, methodParameter, apiResponsesOp, methodAttributes);
apiResponses.forEach(controllerAdviceInfoApiResponseMap::put);
}
Expand Down Expand Up @@ -363,10 +362,11 @@ private boolean isResponseEntityExceptionHandlerMethod(Method m) {
* @param apiResponsesOp the api responses op
* @param methodAttributes the method attributes
* @param openapi31 the openapi 31
* @param locale the locale
* @return the map
*/
private Map<String, ApiResponse> computeResponseFromDoc(Components components, MethodParameter methodParameter, ApiResponses apiResponsesOp,
MethodAttributes methodAttributes, boolean openapi31) {
MethodAttributes methodAttributes, boolean openapi31, Locale locale) {
// Parsing documentation, if present
Set<io.swagger.v3.oas.annotations.responses.ApiResponse> responsesArray = getApiResponses(Objects.requireNonNull(methodParameter.getMethod()));
if (!responsesArray.isEmpty()) {
Expand All @@ -382,8 +382,15 @@ private Map<String, ApiResponse> computeResponseFromDoc(Components components, M
apiResponse.setDescription(propertyResolverUtils.resolve(apiResponseAnnotations.description(), methodAttributes.getLocale()));
buildContentFromDoc(components, apiResponsesOp, methodAttributes, apiResponseAnnotations, apiResponse, openapi31);
Map<String, Object> extensions = AnnotationsUtils.getExtensions(propertyResolverUtils.isOpenapi31(), apiResponseAnnotations.extensions());
if (!CollectionUtils.isEmpty(extensions))
apiResponse.extensions(extensions);
if (!CollectionUtils.isEmpty(extensions)){
if (propertyResolverUtils.isResolveExtensionsProperties()) {
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, extensions);
extensionsResolved.forEach(apiResponse::addExtension);
}
else {
apiResponse.extensions(extensions);
}
}
AnnotationsUtils.getHeaders(apiResponseAnnotations.headers(), methodAttributes.getJsonViewAnnotation(), openapi31)
.ifPresent(apiResponse::headers);
apiResponsesOp.addApiResponse(httpCode, apiResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.core.jackson.TypeNameResolver;
Expand Down Expand Up @@ -71,7 +70,6 @@
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.properties.SpringDocConfigProperties;
import org.springdoc.core.providers.JavadocProvider;
import org.springdoc.core.providers.ObjectMapperProvider;
import org.springdoc.core.utils.PropertyResolverUtils;

import org.springframework.beans.BeansException;
Expand All @@ -97,6 +95,7 @@

/**
* The type Open api builder.
*
* @author bnasslahsen
*/
public class OpenAPIService implements ApplicationContextAware {
Expand Down Expand Up @@ -179,13 +178,13 @@ public class OpenAPIService implements ApplicationContextAware {
/**
* Instantiates a new Open api builder.
*
* @param openAPI the open api
* @param securityParser the security parser
* @param openAPI the open api
* @param securityParser the security parser
* @param springDocConfigProperties the spring doc config properties
* @param propertyResolverUtils the property resolver utils
* @param propertyResolverUtils the property resolver utils
* @param openApiBuilderCustomizers the open api builder customisers
* @param serverBaseUrlCustomizers the server base url customizers
* @param javadocProvider the javadoc provider
* @param serverBaseUrlCustomizers the server base url customizers
* @param javadocProvider the javadoc provider
*/
public OpenAPIService(Optional<OpenAPI> openAPI, SecurityService securityParser,
SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,
Expand Down Expand Up @@ -230,6 +229,7 @@ public static String splitCamelCase(String str) {

/**
* Build.
*
* @param locale the locale
* @return the open api
*/
Expand Down Expand Up @@ -317,9 +317,9 @@ public void setServersPresent(boolean serversPresent) {
* Build tags operation.
*
* @param handlerMethod the handler method
* @param operation the operation
* @param openAPI the open api
* @param locale the locale
* @param operation the operation
* @param openAPI the open api
* @param locale the locale
* @return the operation
*/
public Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) {
Expand Down Expand Up @@ -394,10 +394,10 @@ public Operation buildTags(HandlerMethod handlerMethod, Operation operation, Ope
/**
* Build tags from method.
*
* @param method the method
* @param tags the tags
* @param method the method
* @param tags the tags
* @param tagsStr the tags str
* @param locale the locale
* @param locale the locale
*/
private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {
// method tags
Expand All @@ -417,8 +417,8 @@ private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tag
* Add tags.
*
* @param sourceTags the source tags
* @param tags the tags
* @param locale the locale
* @param tags the tags
* @param locale the locale
*/
private void addTags(List<Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) {
Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils
Expand All @@ -437,9 +437,9 @@ private void addTags(List<Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag
* Build tags from class.
*
* @param beanType the bean type
* @param tags the tags
* @param tagsStr the tags str
* @param locale the locale
* @param tags the tags
* @param tagsStr the tags str
* @param locale the locale
*/
public void buildTagsFromClass(Class<?> beanType, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {
List<Tag> allTags = new ArrayList<>();
Expand Down Expand Up @@ -473,7 +473,7 @@ public Schema resolveProperties(Schema schema, Locale locale) {
if (!CollectionUtils.isEmpty(properties)) {
LinkedHashMap<String, Schema> resolvedSchemas = properties.entrySet().stream().map(es -> {
es.setValue(resolveProperties(es.getValue(), locale));
if(es.getValue() instanceof ArraySchema arraySchema){
if (es.getValue() instanceof ArraySchema arraySchema) {
resolveProperties(arraySchema.getItems(), locale);
}
return es;
Expand Down Expand Up @@ -539,8 +539,8 @@ private Optional<OpenAPIDefinition> getOpenAPIDefinition() {
* Build open api with open api definition.
*
* @param openAPI the open api
* @param apiDef the api def
* @param locale the locale
* @param apiDef the api def
* @param locale the locale
*/
private void buildOpenAPIWithOpenAPIDefinition(OpenAPI openAPI, OpenAPIDefinition apiDef, Locale locale) {
// info
Expand Down Expand Up @@ -568,7 +568,7 @@ private void buildOpenAPIWithOpenAPIDefinition(OpenAPI openAPI, OpenAPIDefinitio
* Resolve properties info.
*
* @param servers the servers
* @param locale the locale
* @param locale the locale
* @return the servers
*/
private List<Server> resolveProperties(List<Server> servers, Locale locale) {
Expand All @@ -584,7 +584,7 @@ private List<Server> resolveProperties(List<Server> servers, Locale locale) {
/**
* Resolve properties info.
*
* @param info the info
* @param info the info
* @param locale the locale
* @return the info
*/
Expand All @@ -606,16 +606,24 @@ private Info resolveProperties(Info info, Locale locale) {
resolveProperty(contact::getEmail, contact::email, propertyResolverUtils, locale);
resolveProperty(contact::getUrl, contact::url, propertyResolverUtils, locale);
}

if(propertyResolverUtils.isResolveExtensionsProperties()){
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, info.getExtensions());
info.setExtensions(extensionsResolved);
}

return info;
}



/**
* Resolve property.
*
* @param getProperty the get property
* @param setProperty the set property
* @param getProperty the get property
* @param setProperty the set property
* @param propertyResolverUtils the property resolver utils
* @param locale the locale
* @param locale the locale
*/
private void resolveProperty(Supplier<String> getProperty, Consumer<String> setProperty,
PropertyResolverUtils propertyResolverUtils, Locale locale) {
Expand All @@ -629,7 +637,7 @@ private void resolveProperty(Supplier<String> getProperty, Consumer<String> setP
* Calculate security schemes.
*
* @param components the components
* @param locale the locale
* @param locale the locale
*/
private void calculateSecuritySchemes(Components components, Locale locale) {
// Look for SecurityScheme in a spring managed bean
Expand Down Expand Up @@ -664,8 +672,8 @@ private void calculateSecuritySchemes(Components components, Locale locale) {
* Add security scheme.
*
* @param apiSecurityScheme the api security scheme
* @param components the components
* @param locale the locale
* @param components the components
* @param locale the locale
*/
private void addSecurityScheme(Set<io.swagger.v3.oas.annotations.security.SecurityScheme> apiSecurityScheme,
Components components, Locale locale) {
Expand All @@ -689,7 +697,7 @@ private void addSecurityScheme(Set<io.swagger.v3.oas.annotations.security.Securi
/**
* Gets api def class.
*
* @param scanner the scanner
* @param scanner the scanner
* @param packagesToScan the packages to scan
* @return the api def class
*/
Expand Down Expand Up @@ -723,7 +731,7 @@ public boolean isAutoTagClasses(Operation operation) {
/**
* Gets security schemes classes.
*
* @param scanner the scanner
* @param scanner the scanner
* @param packagesToScan the packages to scan
* @return the security schemes classes
*/
Expand Down Expand Up @@ -752,7 +760,7 @@ private Set<io.swagger.v3.oas.annotations.security.SecurityScheme> getSecuritySc
* Add tag.
*
* @param handlerMethods the handler methods
* @param tag the tag
* @param tag the tag
*/
public void addTag(Set<HandlerMethod> handlerMethods, io.swagger.v3.oas.models.tags.Tag tag) {
handlerMethods.forEach(handlerMethod -> springdocTags.put(handlerMethod, tag));
Expand Down Expand Up @@ -802,7 +810,7 @@ public OpenAPI getCachedOpenAPI(Locale locale) {
* Sets cached open api.
*
* @param cachedOpenAPI the cached open api
* @param locale associated the the cache entry
* @param locale associated the the cache entry
*/
public void setCachedOpenAPI(OpenAPI cachedOpenAPI, Locale locale) {
this.cachedOpenAPI.put(locale.toLanguageTag(), cachedOpenAPI);
Expand Down

0 comments on commit 577938e

Please sign in to comment.