shashank created CAMEL-26287:
--------------------------------

             Summary: camel-jcache - stopping a jcache endpoint closes the 
caching provider, so removing one route breaks the caches of every other jcache 
endpoint
                 Key: CAMEL-26287
                 URL: https://issues.apache.org/jira/browse/CAMEL-26287
             Project: Camel
          Issue Type: Bug
          Components: camel-jcache
            Reporter: shashank
            Assignee: shashank


{{JCacheEndpoint.doStop}} calls {{JCacheManager.close()}}, which closes the 
cache, the cache manager and the caching provider of the endpoint (main 
36bebb520a63, {{JCacheManager}} lines 88-106). The provider comes from 
{{Caching.getCachingProvider()}}, a JVM singleton, and the JCache API gives the 
same cache manager for the same uri and the same cache for the same name: all 
jcache endpoints of the JVM (and the jcache idempotent, aggregation and 
key-value repositories, which use {{JCacheManager}} too) share them. Closing 
the provider closes all its cache managers and caches.

An endpoint is stopped when the only route that uses it is removed (a reload, a 
route template removed, JMX/controlbus), and when its CamelContext stops. 
Afterwards every operation of every other jcache endpoint fails with 
{{IllegalStateException: Cache operations can not be performed. The cache 
closed}} (Hazelcast provider), for good: {{JCacheManager}} keeps the closed 
cache. Examples:
* two routes {{to("jcache://orders")}} and {{to("jcache://sessions")}}; the 
second route is removed: the first fails;
* a consumer route {{from("jcache://orders?filteredEvents=...")}} and a 
producer route {{to("jcache://orders")}} (two endpoints, one cache); the 
consumer route is removed: the producer fails;
* two CamelContexts in one JVM: stopping one breaks the jcache endpoints of the 
other (read, not run); the same for a stopped jcache repository.

*Fix*: {{JCacheManager}} counts (JVM-wide) the managers that use each provider, 
cache manager and cache it got in {{getCache()}}; {{close()}} closes each of 
them only when it is the last manager that uses it, and forgets them, so a 
closed manager no longer hands out a closed cache. Each manager releases only 
what it counted: one whose {{getCache()}} failed (a missing cache with 
{{createCacheIfNotExists=false}}) does not close the provider and cache manager 
while others use them. A single endpoint still closes all three when it stops, 
as before. A cache given to the {{JCacheManager(Cache)}} constructor is still 
not closed. Users of the provider outside Camel's {{JCacheManager}} 
(application code, {{JCachePolicy}}) are not counted, so they still see it 
closed when the last jcache endpoint or repository stops.

*Tests*: new {{JCacheRemoveRouteTest}} (Hazelcast JCache provider, as the 
module tests), 3 tests, all fail on main (3 runs): 
{{removingARouteKeepsTheCachesOfTheOtherRoutes}} and 
{{removingTheConsumerRouteOfACacheKeepsItsProducer}} with the exception above, 
{{theLastManagerOfACacheClosesIt}} ({{expected: <false> but was: <true>}}: the 
first of two managers closed the shared cache); and 
{{JCacheManagerTest.aManagerThatCouldNotGetItsCacheDoesNotCloseTheCacheManagerOfTheOthers}},
 which fails on main the same way. With the fix camel-jcache has 95 tests, 0 
failures.

*How it was found*: a code sweep for endpoints whose {{doStop}} releases 
something other endpoints still use, after a random lifecycle-sequence harness 
found the same kind of defect in camel-disruptor.

*Affected*: main, camel-4.22.x, camel-4.18.x and camel-4.14.x (same 
{{JCacheManager.close()}}; read, not run).

_Filed with Claude Code on behalf of allthingssecurity._



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to