This is an automated email from the ASF dual-hosted git repository.
mridulpathak pushed a commit to branch release24.09
in repository https://gitbox.apache.org/repos/asf/ofbiz-framework.git
The following commit(s) were added to refs/heads/release24.09 by this push:
new d2b1f10c8f Fixed: EntityEcaUtil cache-rebuild race under concurrent
Delegator construction (OFBIZ-13517)
d2b1f10c8f is described below
commit d2b1f10c8f62e52cf1576873446f1dc79b1d5e5f
Author: Mridul Pathak <[email protected]>
AuthorDate: Tue Sep 1 20:07:28 2026 +0530
Fixed: EntityEcaUtil cache-rebuild race under concurrent Delegator
construction (OFBIZ-13517)
Threads racing a cache miss on the same entity-eca-reader each
independently rebuilt the full cache before only one publish won. Added a lock
with double-checked re-verification around the check-then-build-then-publish
sequence, mirroring the sibling ServiceEcaUtil race fix in 485496ad3e (#1805).
---
.../org/apache/ofbiz/entityext/eca/EntityEcaUtil.java | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
diff --git
a/framework/entityext/src/main/java/org/apache/ofbiz/entityext/eca/EntityEcaUtil.java
b/framework/entityext/src/main/java/org/apache/ofbiz/entityext/eca/EntityEcaUtil.java
index 46e1350566..13c7dbba27 100644
---
a/framework/entityext/src/main/java/org/apache/ofbiz/entityext/eca/EntityEcaUtil.java
+++
b/framework/entityext/src/main/java/org/apache/ofbiz/entityext/eca/EntityEcaUtil.java
@@ -52,15 +52,25 @@ public final class EntityEcaUtil {
private static final UtilCache<String, Map<String, Map<String,
List<EntityEcaRule>>>> ENTITY_ECA_READERS =
UtilCache.createUtilCache("entity.EcaReaders", 0, 0, false);
+ // Guards getEntityEcaCache()'s check-then-build-then-publish sequence:
concurrent Delegator
+ // construction (see GenericDelegator.initEntityEcaHandler()) can race a
cache miss for the same
+ // reader name, each redundantly rebuilding before only one publish wins.
+ private static final Object CONFIG_LOCK = new Object();
+
private EntityEcaUtil() { }
public static Map<String, Map<String, List<EntityEcaRule>>>
getEntityEcaCache(String entityEcaReaderName) {
Map<String, Map<String, List<EntityEcaRule>>> ecaCache =
ENTITY_ECA_READERS.get(entityEcaReaderName);
if (ecaCache == null) {
- // FIXME: Collections are not thread safe
- ecaCache = new HashMap<>();
- readConfig(entityEcaReaderName, ecaCache);
- ecaCache =
ENTITY_ECA_READERS.putIfAbsentAndGet(entityEcaReaderName, ecaCache);
+ synchronized (CONFIG_LOCK) {
+ // Re-check: another thread may have already published this
while we waited for the lock.
+ ecaCache = ENTITY_ECA_READERS.get(entityEcaReaderName);
+ if (ecaCache == null) {
+ ecaCache = new HashMap<>();
+ readConfig(entityEcaReaderName, ecaCache);
+ ecaCache =
ENTITY_ECA_READERS.putIfAbsentAndGet(entityEcaReaderName, ecaCache);
+ }
+ }
}
return ecaCache;
}