fix: make JsonSchemaGenerator thread-safe with caching and synchronized generation (GH-6207)#6223
Closed
suryateja-g13 wants to merge 1 commit into
Closed
Conversation
…ed generation (spring-projectsGH-6207) The shared static SchemaGenerator instances were not protected against concurrent access. victools' JacksonSchemaModule (RESPECT_JSONPROPERTY_ORDER) maintains internal sorted state that throws ConcurrentModificationException when multiple threads call generateSchema() simultaneously. Two-layer fix: 1. ConcurrentHashMap caches per (Type, Set<SchemaOption>) and (Method, Set<SchemaOption>) — once a schema is generated it is returned instantly for all subsequent callers of the same type, eliminating repeated concurrent calls entirely. 2. synchronized blocks around generateSchema() calls — protects the first-time concurrent generation for distinct types before the cached value is available. Signed-off-by: Gorre Surya <suryateja.g13@gmail.com>
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Fixes #6207 — concurrent calls to
JsonSchemaGenerator.generateForType()/generateForMethodInput()throwConcurrentModificationExceptionfromJsonPropertySorterinside victools'JacksonSchemaModule.Root cause: The static
SchemaGeneratorinstances (TYPE_SCHEMA_GENERATOR,SUBTYPE_SCHEMA_GENERATOR) are shared across threads but are not thread-safe.JacksonSchemaModulewithRESPECT_JSONPROPERTY_ORDERuses a sorted property list that throwsConcurrentModificationExceptionunder concurrent access.Fix — two-layer defense:
ConcurrentHashMapcaches — one per(Type, Set<SchemaOption>)forgenerateForType, one per(Method, Set<SchemaOption>)forgenerateForMethodInput. Once a schema is generated for a type it is served instantly from cache for all subsequent callers, eliminating the bulk of concurrent generator invocations.synchronizedblocks aroundgenerateSchema()calls — protects the first-time generation of any given type before the result lands in cache (prevents the race for concurrent first-callers for distinct types).The caching also provides a meaningful performance improvement:
BeanOutputConverteris instantiated on everyChatClient.ResponseSpec.entity()call and invokesJsonSchemaGenerator.generateForType()each time — with this fix the expensive victools generation runs only once per type per JVM.Test plan
JsonSchemaGeneratorTests.generateForTypeConcurrently— 20 virtual threads concurrently generate the same type, no CME, all results equalJsonSchemaGeneratorTests.generateForMethodInputConcurrently— 20 virtual threads concurrently generate the same method schema, no CME, all results equalJsonSchemaGeneratorTestscontinue to pass