Fix concurrent problems when initializing multiple GroupedOpenApi parallelly #1707
+3
−2
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem
Continuation of #1641
If a project has multiple
GroupedOpenApi
bean, they will be initialized parallelly. This lead to concurrent read and write ofAbstractOpenApiResource#HIDDEN_REST_CONTROLLERS
.Since the list is not correctly synchronized, concurrent read and write might cause
ConcurrentModificationException
(Collections#synchronizedList
isn't thread-safe on iteration):Solution
There are 3 possible solutions:
Synchronize on the list before every read and write:
Use an fully thread-safe implementation for list, such as
CopyOnWriteArrayList
GroupedOpenApi
only triggers two write operations forHIDDEN_REST_CONTROLLERS
, and the list is generally small, so the trade-off is acceptable.Reactor the initialization to eliminate concurrent write
Each
GroupedOpenApi
will try to add the same controllers toHIDDEN_REST_CONTROLLERS
inOpenAPIService#initializeHiddenRestController
, since the controllers are obtained from the sameApplicationContext
.It's better to write to
HIDDEN_REST_CONTROLLERS
only once before parallel initialization. This can not only eliminate concurrent write but also avoid duplication.However, this refactoring requires more familiarity of Springdoc's code base, and it's beyond my powers at present.
This PR implements solution 2.
I also replaced
ADDITIONAL_REST_CONTROLLERS
,HIDDEN_REST_CONTROLLERS
with set to avoid duplication. This will reduce the number of elements to iterate thus improving performance.