First of all, since this is my first forum thread, I'd like to thank you for 
your excellent job in creating and maintaining Apache cayenne. It's a really 
good and practical piece of software. With the intention of making it better 
and helping as little as I can, I'd like to share with you an underlying issue 
we might have spotted.

We are seeing some ConcurrentModificationException, and after some examination 
we found out that the _registeredSubjects Map (WeakValueMap) in EventSubject 
class is static and not thread safe.

Every time a new context is created without SharedCacheEnabled (In the 
DataDomain), the EventSubject->getSubject method is called, and so it does some 
get/put in _registeredSubjects, which also consequently call 
ReferenceMap->checkReferenceQueue, which do a lot of non thread safe operations 
on the inner HashMap.

This could be a huge issue for highly concurrent applications.

For now, we are trying to make it work with a custom snapshot cache, which 
stores nothing, as we do not want to share or cache anything.

Please find the stack below:

StackTrace: 'java.util.ConcurrentModificationException
        at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1526)
        at java.base/java.util.HashMap$EntryIterator.next(HashMap.java:1524)
        at 
org.apache.cayenne.util.ReferenceMap.checkReferenceQueue(ReferenceMap.java:242)
        at org.apache.cayenne.util.ReferenceMap.get(ReferenceMap.java:138)
        at org.apache.cayenne.util.WeakValueMap.get(WeakValueMap.java:33)
        at 
org.apache.cayenne.event.EventSubject.getSubject(EventSubject.java:67)
        at 
org.apache.cayenne.access.DataRowStore.createSubject(DataRowStore.java:97)
        at org.apache.cayenne.access.DataRowStore.<init>(DataRowStore.java:91)
        at 
org.apache.cayenne.access.DefaultDataRowStoreFactory.createDataRowStore(DefaultDataRowStoreFactory.java:54)
        at 
org.apache.cayenne.configuration.server.DataContextFactory.createdFromDataDomain(DataContextFactory.java:115)
        at 
org.apache.cayenne.configuration.server.DataContextFactory.createContext(DataContextFactory.java:61)
        at 
org.apache.cayenne.configuration.CayenneRuntime.newContext(CayenneRuntime.java:124)


Thanks,

best,

Reply via email to