Skip to content

Commit 00d8525

Browse files
committed
performance tunning
1 parent fba0114 commit 00d8525

File tree

11 files changed

+219
-136
lines changed

11 files changed

+219
-136
lines changed

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

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import org.springdoc.core.service.OpenAPIService;
110110
import org.springdoc.core.service.OperationService;
111111
import org.springdoc.core.utils.PropertyResolverUtils;
112+
import org.springdoc.core.utils.SpringDocAnnotationsUtils;
112113
import org.springdoc.core.utils.SpringDocUtils;
113114

114115
import org.springframework.aop.support.AopUtils;
@@ -131,6 +132,7 @@
131132
import static org.springdoc.core.utils.Constants.DOT;
132133
import static org.springdoc.core.utils.Constants.OPERATION_ATTRIBUTE;
133134
import static org.springdoc.core.utils.Constants.SPRING_MVC_SERVLET_PATH;
135+
import static org.springdoc.core.utils.SpringDocUtils.cloneViaJson;
134136
import static org.springframework.util.AntPathMatcher.DEFAULT_PATH_SEPARATOR;
135137

136138
/**
@@ -392,15 +394,8 @@ protected OpenAPI getOpenApi(String serverBaseUrl, Locale locale) {
392394

393395
// run the optional customizers
394396
List<Server> servers = openAPI.getServers();
395-
List<Server> serversCopy = null;
396-
try {
397-
serversCopy = springDocProviders.jsonMapper()
398-
.readValue(springDocProviders.jsonMapper().writeValueAsString(servers), new TypeReference<List<Server>>() {});
399-
}
400-
catch (JsonProcessingException e) {
401-
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
402-
}
403-
397+
List<Server> serversCopy = cloneViaJson(servers, new TypeReference<List<Server>>() {}, springDocProviders.jsonMapper());
398+
404399
openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class).values().forEach(openApiLocaleCustomizer -> openApiLocaleCustomizer.customise(openAPI, finalLocale));
405400
springDocCustomizers.getOpenApiCustomizers().ifPresent(apiCustomizers -> apiCustomizers.forEach(openApiCustomizer -> openApiCustomizer.customise(openAPI)));
406401
if (!CollectionUtils.isEmpty(openAPI.getServers()) && !openAPI.getServers().equals(serversCopy))
@@ -419,10 +414,7 @@ protected OpenAPI getOpenApi(String serverBaseUrl, Locale locale) {
419414
return openAPI;
420415
}
421416
finally {
422-
JavadocProvider javadocProvider = operationParser.getJavadocProvider();
423-
if (javadocProvider != null) {
424-
javadocProvider.clean();
425-
}
417+
SpringDocAnnotationsUtils.clearCache(operationParser.getJavadocProvider());
426418
this.reentrantLock.unlock();
427419
}
428420
}

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/converters/AdditionalModelsConverter.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import java.util.Iterator;
3131
import java.util.Map;
3232

33-
import com.fasterxml.jackson.core.JsonProcessingException;
3433
import com.fasterxml.jackson.core.type.TypeReference;
3534
import com.fasterxml.jackson.databind.JavaType;
3635
import io.swagger.v3.core.converter.AnnotatedType;
@@ -41,6 +40,7 @@
4140
import org.slf4j.LoggerFactory;
4241
import org.springdoc.core.providers.ObjectMapperProvider;
4342

43+
import static org.springdoc.core.utils.SpringDocUtils.cloneViaJson;
4444
import static org.springdoc.core.utils.SpringDocUtils.handleSchemaTypes;
4545

4646
/**
@@ -164,17 +164,12 @@ public Schema resolve(AnnotatedType type, ModelConverterContext context, Iterato
164164
JavaType javaType = springDocObjectMapper.jsonMapper().constructType(type.getType());
165165
if (javaType != null) {
166166
Class<?> cls = javaType.getRawClass();
167-
if (modelToSchemaMap.containsKey(cls))
168-
try {
169-
Schema schema = modelToSchemaMap.get(cls);
170-
if (springDocObjectMapper.isOpenapi31())
171-
handleSchemaTypes(schema);
172-
return springDocObjectMapper.jsonMapper()
173-
.readValue(springDocObjectMapper.jsonMapper().writeValueAsString(schema), new TypeReference<Schema>() {});
174-
}
175-
catch (JsonProcessingException e) {
176-
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
177-
}
167+
if (modelToSchemaMap.containsKey(cls)) {
168+
Schema schema = modelToSchemaMap.get(cls);
169+
if (springDocObjectMapper.isOpenapi31())
170+
handleSchemaTypes(schema);
171+
return cloneViaJson(schema, new TypeReference<Schema>() {}, springDocObjectMapper.jsonMapper());
172+
}
178173
if (modelToClassMap.containsKey(cls))
179174
type = new AnnotatedType(modelToClassMap.get(cls)).resolveAsRef(true);
180175
}

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/providers/JavadocProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,5 +106,5 @@ public interface JavadocProvider {
106106
/**
107107
* Clean the temp resources.
108108
*/
109-
default void clean() {}
109+
default void clearCache() {}
110110
}

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/providers/SpringDocJavadocProvider.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ private FieldJavadoc getJavadoc(Field field) {
208208
}
209209

210210
@Override
211-
public void clean() {
211+
public void clearCache() {
212212
classJavadocCache.clear();
213213
}
214214
}

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import org.springdoc.core.models.RequestBodyInfo;
7878
import org.springdoc.core.properties.SpringDocConfigProperties.ApiDocs.OpenApiVersion;
7979
import org.springdoc.core.providers.JavadocProvider;
80+
import org.springdoc.core.providers.ObjectMapperProvider;
8081
import org.springdoc.core.utils.SchemaUtils;
8182
import org.springdoc.core.utils.SpringDocAnnotationsUtils;
8283

@@ -102,6 +103,7 @@
102103

103104
import static org.springdoc.core.converters.SchemaPropertyDeprecatingConverter.containsDeprecatedAnnotation;
104105
import static org.springdoc.core.service.GenericParameterService.isFile;
106+
import static org.springdoc.core.utils.SpringDocUtils.cloneViaJson;
105107
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
106108
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
107109
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE;
@@ -664,7 +666,9 @@ public void applyBeanValidatorAnnotations(final MethodParameter methodParameter,
664666
java.lang.reflect.AnnotatedType[] typeArgs = paramType.getAnnotatedActualTypeArguments();
665667
for (java.lang.reflect.AnnotatedType typeArg : typeArgs) {
666668
List<Annotation> genericAnnotations = Arrays.stream(typeArg.getAnnotations()).toList();
667-
SchemaUtils.applyValidationsToSchema(schema.getItems(), genericAnnotations, openapiVersion);
669+
Schema schemaItemsClone = cloneViaJson(schema.getItems(), Schema.class, ObjectMapperProvider.createJson(parameterBuilder.getPropertyResolverUtils().getSpringDocConfigProperties()));
670+
schema.items(schemaItemsClone);
671+
SchemaUtils.applyValidationsToSchema(schemaItemsClone, genericAnnotations, openapiVersion);
668672
}
669673
}
670674
}

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@
5151
import java.util.stream.Stream;
5252

5353
import com.fasterxml.jackson.annotation.JsonView;
54-
import com.fasterxml.jackson.core.JsonProcessingException;
55-
import com.fasterxml.jackson.databind.ObjectMapper;
5654
import io.swagger.v3.core.util.AnnotationsUtils;
5755
import io.swagger.v3.oas.models.Components;
5856
import io.swagger.v3.oas.models.Operation;
@@ -99,6 +97,7 @@
9997
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.extractSchema;
10098
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.getContent;
10199
import static org.springdoc.core.utils.SpringDocAnnotationsUtils.mergeSchema;
100+
import static org.springdoc.core.utils.SpringDocUtils.cloneViaJson;
102101
import static org.springdoc.core.utils.SpringDocUtils.getParameterAnnotations;
103102

104103
/**
@@ -753,17 +752,7 @@ private Map<String, ApiResponse> getGenericMapResponse(HandlerMethod handlerMeth
753752
}
754753
}
755754
}
756-
757-
LinkedHashMap<String, ApiResponse> genericApiResponsesClone;
758-
try {
759-
ObjectMapper objectMapper = ObjectMapperProvider.createJson(springDocConfigProperties);
760-
genericApiResponsesClone = objectMapper.readValue(objectMapper.writeValueAsString(genericApiResponseMap), ApiResponses.class);
761-
return genericApiResponsesClone;
762-
}
763-
catch (JsonProcessingException e) {
764-
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
765-
return genericApiResponseMap;
766-
}
755+
return cloneViaJson(genericApiResponseMap, ApiResponses.class, ObjectMapperProvider.createJson(springDocConfigProperties));
767756
}
768757
finally {
769758
reentrantLock.unlock();

springdoc-openapi-starter-common/src/main/java/org/springdoc/core/service/OpenAPIService.java

Lines changed: 68 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@
4747
import java.util.stream.Collectors;
4848
import java.util.stream.Stream;
4949

50-
import com.fasterxml.jackson.core.JsonProcessingException;
5150
import com.fasterxml.jackson.databind.ObjectMapper;
5251
import io.swagger.v3.core.jackson.TypeNameResolver;
5352
import io.swagger.v3.core.util.AnnotationsUtils;
@@ -98,6 +97,7 @@
9897
import static org.springdoc.core.utils.Constants.DEFAULT_SERVER_DESCRIPTION;
9998
import static org.springdoc.core.utils.Constants.DEFAULT_TITLE;
10099
import static org.springdoc.core.utils.Constants.DEFAULT_VERSION;
100+
import static org.springdoc.core.utils.SpringDocUtils.cloneViaJson;
101101
import static org.springdoc.core.utils.SpringDocUtils.getConfig;
102102

103103
/**
@@ -246,14 +246,7 @@ public OpenAPI build(Locale locale) {
246246
calculatedOpenAPI.setPaths(new Paths());
247247
}
248248
else {
249-
try {
250-
ObjectMapper objectMapper = new ObjectMapper();
251-
calculatedOpenAPI = objectMapper.readValue(objectMapper.writeValueAsString(openAPI), OpenAPI.class);
252-
}
253-
catch (JsonProcessingException e) {
254-
LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage());
255-
calculatedOpenAPI = openAPI;
256-
}
249+
calculatedOpenAPI = cloneViaJson(openAPI, OpenAPI.class, new ObjectMapper());
257250
}
258251

259252
if (apiDef.isPresent()) {
@@ -539,71 +532,71 @@ private Optional<OpenAPIDefinition> getOpenAPIDefinition() {
539532
}
540533

541534

542-
/**
543-
* Gets webhooks from given classes.
544-
*
545-
* @param classes Array of classes to scan for webhooks.
546-
* @return An array of {@link Webhooks} annotations found in the given classes.
547-
*/
548-
public Webhooks[] getWebhooks(Class<?>[] classes) {
549-
List<Webhooks> allWebhooks = new ArrayList<>();
550-
551-
for (Class<?> clazz : classes) {
552-
// Class-level annotations
553-
collectWebhooksFromElement(clazz, allWebhooks);
554-
555-
// Method-level annotations
556-
for (Method method : clazz.getDeclaredMethods()) {
557-
collectWebhooksFromElement(method, allWebhooks);
558-
}
559-
}
560-
561-
return allWebhooks.toArray(new Webhooks[0]);
562-
}
563-
564-
565-
/**
566-
* Retrieves all classes related to webhooks.
567-
* This method scans for classes annotated with {@link Webhooks} or {@link Webhook},
568-
* first checking Spring-managed beans and then falling back to classpath scanning
569-
* if no annotated beans are found.
570-
*
571-
* @return An array of classes related to webhooks.
572-
*/
573-
public Class<?>[] getWebhooksClasses() {
574-
Set<Class<?>> allWebhookClassesToScan = new HashSet<>();
575-
576-
// First: scan Spring-managed beans
577-
Map<String, Object> beans = context.getBeansWithAnnotation(Webhooks.class);
578-
579-
for (Object bean : beans.values()) {
580-
Class<?> beanClass = bean.getClass();
581-
allWebhookClassesToScan.add(beanClass);
582-
}
583-
584-
// Fallback: classpath scanning
585-
ClassPathScanningCandidateComponentProvider scanner =
586-
new ClassPathScanningCandidateComponentProvider(false);
587-
scanner.addIncludeFilter(new AnnotationTypeFilter(Webhooks.class));
588-
scanner.addIncludeFilter(new AnnotationTypeFilter(Webhook.class));
589-
590-
if (AutoConfigurationPackages.has(context)) {
591-
for (String basePackage : AutoConfigurationPackages.get(context)) {
592-
Set<BeanDefinition> candidates = scanner.findCandidateComponents(basePackage);
593-
for (BeanDefinition bd : candidates) {
594-
try {
595-
Class<?> clazz = Class.forName(bd.getBeanClassName());
596-
allWebhookClassesToScan.add(clazz);
597-
}
598-
catch (ClassNotFoundException e) {
599-
LOGGER.error("Class not found in classpath: {}", e.getMessage());
600-
}
601-
}
602-
}
603-
}
604-
605-
return allWebhookClassesToScan.toArray(new Class<?>[0]);
606-
}
535+
/**
536+
* Gets webhooks from given classes.
537+
*
538+
* @param classes Array of classes to scan for webhooks.
539+
* @return An array of {@link Webhooks} annotations found in the given classes.
540+
*/
541+
public Webhooks[] getWebhooks(Class<?>[] classes) {
542+
List<Webhooks> allWebhooks = new ArrayList<>();
543+
544+
for (Class<?> clazz : classes) {
545+
// Class-level annotations
546+
collectWebhooksFromElement(clazz, allWebhooks);
547+
548+
// Method-level annotations
549+
for (Method method : clazz.getDeclaredMethods()) {
550+
collectWebhooksFromElement(method, allWebhooks);
551+
}
552+
}
553+
554+
return allWebhooks.toArray(new Webhooks[0]);
555+
}
556+
557+
558+
/**
559+
* Retrieves all classes related to webhooks.
560+
* This method scans for classes annotated with {@link Webhooks} or {@link Webhook},
561+
* first checking Spring-managed beans and then falling back to classpath scanning
562+
* if no annotated beans are found.
563+
*
564+
* @return An array of classes related to webhooks.
565+
*/
566+
public Class<?>[] getWebhooksClasses() {
567+
Set<Class<?>> allWebhookClassesToScan = new HashSet<>();
568+
569+
// First: scan Spring-managed beans
570+
Map<String, Object> beans = context.getBeansWithAnnotation(Webhooks.class);
571+
572+
for (Object bean : beans.values()) {
573+
Class<?> beanClass = bean.getClass();
574+
allWebhookClassesToScan.add(beanClass);
575+
}
576+
577+
// Fallback: classpath scanning
578+
ClassPathScanningCandidateComponentProvider scanner =
579+
new ClassPathScanningCandidateComponentProvider(false);
580+
scanner.addIncludeFilter(new AnnotationTypeFilter(Webhooks.class));
581+
scanner.addIncludeFilter(new AnnotationTypeFilter(Webhook.class));
582+
583+
if (AutoConfigurationPackages.has(context)) {
584+
for (String basePackage : AutoConfigurationPackages.get(context)) {
585+
Set<BeanDefinition> candidates = scanner.findCandidateComponents(basePackage);
586+
for (BeanDefinition bd : candidates) {
587+
try {
588+
Class<?> clazz = Class.forName(bd.getBeanClassName());
589+
allWebhookClassesToScan.add(clazz);
590+
}
591+
catch (ClassNotFoundException e) {
592+
LOGGER.error("Class not found in classpath: {}", e.getMessage());
593+
}
594+
}
595+
}
596+
}
597+
598+
return allWebhookClassesToScan.toArray(new Class<?>[0]);
599+
}
607600

608601

609602
/**
@@ -716,7 +709,7 @@ private Info resolveProperties(Info info, Map<String, Object> extensions, Locale
716709

717710
if (extensions != null) {
718711
Map<String, Object> extensionsResolved = propertyResolverUtils.resolveExtensions(locale, extensions);
719-
if (propertyResolverUtils.isOpenapi31()){
712+
if (propertyResolverUtils.isOpenapi31()) {
720713
extensionsResolved.forEach(info::addExtension31);
721714
info.setExtensions(extensionsResolved);
722715
}

0 commit comments

Comments
 (0)