|
47 | 47 | import java.util.Set; |
48 | 48 | import java.util.TreeSet; |
49 | 49 | import java.util.concurrent.Executors; |
| 50 | +import java.util.concurrent.locks.Lock; |
| 51 | +import java.util.concurrent.locks.ReentrantLock; |
50 | 52 | import java.util.stream.Collectors; |
51 | 53 |
|
52 | 54 | import com.fasterxml.jackson.annotation.JsonView; |
@@ -200,6 +202,10 @@ public abstract class AbstractOpenApiResource extends SpecFilter { |
200 | 202 | */ |
201 | 203 | protected final SpringDocCustomizers springDocCustomizers; |
202 | 204 |
|
| 205 | + /** |
| 206 | + * The Reentrant lock. |
| 207 | + */ |
| 208 | + private final Lock reentrantLock = new ReentrantLock(); |
203 | 209 |
|
204 | 210 | /** |
205 | 211 | * Instantiates a new Abstract open api resource. |
@@ -319,73 +325,78 @@ private void getOpenApi() { |
319 | 325 | * @param locale the locale |
320 | 326 | * @return the open api |
321 | 327 | */ |
322 | | - protected synchronized OpenAPI getOpenApi(Locale locale) { |
323 | | - final OpenAPI openAPI; |
324 | | - final Locale finalLocale = locale == null ? Locale.getDefault() : locale; |
325 | | - if (openAPIService.getCachedOpenAPI(finalLocale) == null || springDocConfigProperties.isCacheDisabled()) { |
326 | | - Instant start = Instant.now(); |
327 | | - openAPI = openAPIService.build(finalLocale); |
328 | | - Map<String, Object> mappingsMap = openAPIService.getMappingsMap().entrySet().stream() |
329 | | - .filter(controller -> (AnnotationUtils.findAnnotation(controller.getValue().getClass(), |
330 | | - Hidden.class) == null)) |
331 | | - .filter(controller -> !isHiddenRestControllers(controller.getValue().getClass())) |
332 | | - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1)); |
333 | | - |
334 | | - Map<String, Object> findControllerAdvice = openAPIService.getControllerAdviceMap(); |
335 | | - if (OpenApiVersion.OPENAPI_3_1 == springDocConfigProperties.getApiDocs().getVersion()) |
336 | | - openAPI.openapi(OpenApiVersion.OPENAPI_3_1.getVersion()); |
337 | | - if (springDocConfigProperties.isDefaultOverrideWithGenericResponse()) { |
338 | | - if (!CollectionUtils.isEmpty(mappingsMap)) |
339 | | - findControllerAdvice.putAll(mappingsMap); |
340 | | - responseBuilder.buildGenericResponse(openAPI.getComponents(), findControllerAdvice, finalLocale); |
341 | | - } |
342 | | - getPaths(mappingsMap, finalLocale, openAPI); |
343 | | - |
344 | | - Optional<CloudFunctionProvider> cloudFunctionProviderOptional = springDocProviders.getSpringCloudFunctionProvider(); |
345 | | - cloudFunctionProviderOptional.ifPresent(cloudFunctionProvider -> { |
346 | | - List<RouterOperation> routerOperationList = cloudFunctionProvider.getRouterOperations(openAPI); |
347 | | - if (!CollectionUtils.isEmpty(routerOperationList)) |
348 | | - this.calculatePath(routerOperationList, locale, openAPI); |
349 | | - } |
350 | | - ); |
351 | | - if (!CollectionUtils.isEmpty(openAPI.getServers())) |
352 | | - openAPIService.setServersPresent(true); |
353 | | - else |
354 | | - openAPIService.setServersPresent(false); |
355 | | - openAPIService.updateServers(openAPI); |
356 | | - |
357 | | - if (springDocConfigProperties.isRemoveBrokenReferenceDefinitions()) |
358 | | - this.removeBrokenReferenceDefinitions(openAPI); |
| 328 | + protected OpenAPI getOpenApi(Locale locale) { |
| 329 | + this.reentrantLock.lock(); |
| 330 | + try { |
| 331 | + final OpenAPI openAPI; |
| 332 | + final Locale finalLocale = locale == null ? Locale.getDefault() : locale; |
| 333 | + if (openAPIService.getCachedOpenAPI(finalLocale) == null || springDocConfigProperties.isCacheDisabled()) { |
| 334 | + Instant start = Instant.now(); |
| 335 | + openAPI = openAPIService.build(finalLocale); |
| 336 | + Map<String, Object> mappingsMap = openAPIService.getMappingsMap().entrySet().stream() |
| 337 | + .filter(controller -> (AnnotationUtils.findAnnotation(controller.getValue().getClass(), |
| 338 | + Hidden.class) == null)) |
| 339 | + .filter(controller -> !isHiddenRestControllers(controller.getValue().getClass())) |
| 340 | + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a1, a2) -> a1)); |
| 341 | + |
| 342 | + Map<String, Object> findControllerAdvice = openAPIService.getControllerAdviceMap(); |
| 343 | + if (OpenApiVersion.OPENAPI_3_1 == springDocConfigProperties.getApiDocs().getVersion()) |
| 344 | + openAPI.openapi(OpenApiVersion.OPENAPI_3_1.getVersion()); |
| 345 | + if (springDocConfigProperties.isDefaultOverrideWithGenericResponse()) { |
| 346 | + if (!CollectionUtils.isEmpty(mappingsMap)) |
| 347 | + findControllerAdvice.putAll(mappingsMap); |
| 348 | + responseBuilder.buildGenericResponse(openAPI.getComponents(), findControllerAdvice, finalLocale); |
| 349 | + } |
| 350 | + getPaths(mappingsMap, finalLocale, openAPI); |
359 | 351 |
|
360 | | - // run the optional customisers |
361 | | - List<Server> servers = openAPI.getServers(); |
362 | | - List<Server> serversCopy = null; |
363 | | - try { |
364 | | - serversCopy = springDocProviders.jsonMapper() |
365 | | - .readValue(springDocProviders.jsonMapper().writeValueAsString(servers), new TypeReference<List<Server>>() {}); |
366 | | - } |
367 | | - catch (JsonProcessingException e) { |
368 | | - LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage()); |
369 | | - } |
| 352 | + Optional<CloudFunctionProvider> cloudFunctionProviderOptional = springDocProviders.getSpringCloudFunctionProvider(); |
| 353 | + cloudFunctionProviderOptional.ifPresent(cloudFunctionProvider -> { |
| 354 | + List<RouterOperation> routerOperationList = cloudFunctionProvider.getRouterOperations(openAPI); |
| 355 | + if (!CollectionUtils.isEmpty(routerOperationList)) |
| 356 | + this.calculatePath(routerOperationList, locale, openAPI); |
| 357 | + } |
| 358 | + ); |
| 359 | + if (!CollectionUtils.isEmpty(openAPI.getServers())) |
| 360 | + openAPIService.setServersPresent(true); |
| 361 | + else |
| 362 | + openAPIService.setServersPresent(false); |
| 363 | + openAPIService.updateServers(openAPI); |
| 364 | + |
| 365 | + if (springDocConfigProperties.isRemoveBrokenReferenceDefinitions()) |
| 366 | + this.removeBrokenReferenceDefinitions(openAPI); |
| 367 | + |
| 368 | + // run the optional customisers |
| 369 | + List<Server> servers = openAPI.getServers(); |
| 370 | + List<Server> serversCopy = null; |
| 371 | + try { |
| 372 | + serversCopy = springDocProviders.jsonMapper() |
| 373 | + .readValue(springDocProviders.jsonMapper().writeValueAsString(servers), new TypeReference<List<Server>>() {}); |
| 374 | + } |
| 375 | + catch (JsonProcessingException e) { |
| 376 | + LOGGER.warn("Json Processing Exception occurred: {}", e.getMessage()); |
| 377 | + } |
370 | 378 |
|
371 | | - openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class).values().forEach(openApiLocaleCustomizer -> openApiLocaleCustomizer.customise(openAPI, finalLocale)); |
372 | | - springDocCustomizers.getOpenApiCustomizers().ifPresent(apiCustomizers -> apiCustomizers.forEach(openApiCustomizer -> openApiCustomizer.customise(openAPI))); |
373 | | - if (!CollectionUtils.isEmpty(openAPI.getServers()) && !openAPI.getServers().equals(serversCopy)) |
374 | | - openAPIService.setServersPresent(true); |
| 379 | + openAPIService.getContext().getBeansOfType(OpenApiLocaleCustomizer.class).values().forEach(openApiLocaleCustomizer -> openApiLocaleCustomizer.customise(openAPI, finalLocale)); |
| 380 | + springDocCustomizers.getOpenApiCustomizers().ifPresent(apiCustomizers -> apiCustomizers.forEach(openApiCustomizer -> openApiCustomizer.customise(openAPI))); |
| 381 | + if (!CollectionUtils.isEmpty(openAPI.getServers()) && !openAPI.getServers().equals(serversCopy)) |
| 382 | + openAPIService.setServersPresent(true); |
375 | 383 |
|
376 | 384 |
|
377 | | - openAPIService.setCachedOpenAPI(openAPI, finalLocale); |
| 385 | + openAPIService.setCachedOpenAPI(openAPI, finalLocale); |
378 | 386 |
|
379 | | - LOGGER.info("Init duration for springdoc-openapi is: {} ms", |
380 | | - Duration.between(start, Instant.now()).toMillis()); |
381 | | - } |
382 | | - else { |
383 | | - LOGGER.debug("Fetching openApi document from cache"); |
384 | | - openAPI = openAPIService.getCachedOpenAPI(finalLocale); |
| 387 | + LOGGER.info("Init duration for springdoc-openapi is: {} ms", |
| 388 | + Duration.between(start, Instant.now()).toMillis()); |
| 389 | + } |
| 390 | + else { |
| 391 | + LOGGER.debug("Fetching openApi document from cache"); |
| 392 | + openAPI = openAPIService.getCachedOpenAPI(finalLocale); |
| 393 | + openAPIService.updateServers(openAPI); |
| 394 | + } |
385 | 395 | openAPIService.updateServers(openAPI); |
| 396 | + return openAPI; } |
| 397 | + finally { |
| 398 | + this.reentrantLock.unlock(); |
386 | 399 | } |
387 | | - openAPIService.updateServers(openAPI); |
388 | | - return openAPI; |
389 | 400 | } |
390 | 401 |
|
391 | 402 | /** |
|
0 commit comments