fix: make ApiTokenAttribute Serializable for Ehcache L2 cache#24002
Merged
Conversation
Ehcache 3.12.0 uses SerializingCopier which requires Java serialization. ApiTokenAttribute (and subclasses MethodAllowedList, IpAllowedList, RefererAllowedList) lacked Serializable, causing 500 errors on /api/me and /api/apiTokens when PATs exist. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
david-mackessy
approved these changes
May 27, 2026
jbee
approved these changes
May 27, 2026
This was referenced May 31, 2026
enricocolasante
added a commit
that referenced
this pull request
Jul 16, 2026
The Ehcache 3.12 bump (#23834 / #24002) switched the on-heap L2 store to the JSR-107 store-by-value default, implemented by SerializingCopier: a full Java serialize/deserialize round-trip on every cache get and putFromLoad. Profiling a production tracker import (DHIS2-21800) showed this dominates: ~50% of the thread profile serializing entities under the AbstractReadWriteAccess ReentrantReadWriteLock (READ_WRITE strategy), manifesting as long "waited" time (park on the lock, not blocked) and heavy transient allocation that drives frequent young-gen GC; it also made requests hold their DB connection for the whole duration, draining the pool. Configure an explicit IdentityCopier on defaultCacheTemplate so the mapped entity and query regions store by reference, overriding the JSR-107 by-value semantics (Ehcache logs "overwriting JSR-107 by-value semantics"). This restores the pre-3.12 (Ehcache 2.x) behaviour and eliminates the redundant copy: Hibernate's L2 contract already isolates callers at the type level - entity CacheEntry state is deep-copied on disassemble/assemble (e.g. JsonBinaryType.assemble -> deepCopy) and all immutable custom UserTypes share safely. Add EhcacheStoreByReferenceTest, which loads the real ehcache.xml through the JSR-107 path (as JCacheRegionFactory does, storeByValue=true) and asserts a get returns the same instance that was put. Update CachedEntityJsonbSerializableTest's Javadoc: the Serializable requirement still holds (UserType#disassemble returns Serializable and Hibernate stores a Serializable[]), and that test keeps running store-by-value via an empty cache config, so it remains a strict guard. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
ApiTokenAttributenow implementsSerializable, fixing 500 errors on/api/meand/api/apiTokenswhen PATs existSerializingCopierrequiring Java serializationApiTokenhas<cache usage="read-write"/>in its HBM mapping, so the L2 cache serialization path is hit on every insert/loadAI Assisted