camel-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Piotr Klimczak (JIRA)" <j...@apache.org>
Subject [jira] [Commented] (CAMEL-3686) Allow to share cache between bundles, and only clear cache when no more bundles access that cache
Date Thu, 05 May 2011 18:41:03 GMT

    [ https://issues.apache.org/jira/browse/CAMEL-3686?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13029489#comment-13029489
] 

Piotr Klimczak commented on CAMEL-3686:
---------------------------------------

Things have change a litle since february.

Let's start from cache sharing across bundles problem. It will not work as default. This is
because CacheManager in DefaultCacheManagerFactory class is created like (since always):

{code}
protected CacheManager createCacheManagerInstance() {
    return CacheManager.create(
            getClass().getResourceAsStream("/ehcache.xml"));
}
{code}

Then take a look at CacheManager.create method:

{code}
/**
 * The Singleton Instance.
 */
private static volatile CacheManager singleton;

//some code...

public static CacheManager create(InputStream inputStream) throws CacheException {
    if (singleton != null) {
        return singleton;
    }
    synchronized (CacheManager.class) {
        if (singleton == null) {
            LOG.debug("Creating new CacheManager with InputStream");
            singleton = new CacheManager(inputStream);
        }
        return singleton;
    }
}
{code}

As you can see CacheManager is creating its own instance as a singleton stored in static field.
This is good for one bundle. But remember that each bundle is running in separate ClassLoader.
It means that static fields of one bundle are not visible straight to any other. This is fine
for daily usage as cache have to be separated by default.

Please also note, that CacheManager instance is as default disposed/destroyed during bundle
shutdown. So stopping one bundle will close your default CacheManager which is implemented
in DefaultCacheManagerFactory of camel-cache component:

{code}
@Override
protected void doStop() throws Exception {
    // shutdown cache manager when stopping
    if (cacheManager != null) {
        cacheManager.shutdown();
    }
}
{code}

Please note that due to my last changes to camel-cache component, cache is not deleted from
CacheManager during route shutdown anymore as it was before (which was extremely bad for people
like you and me).

So in my opinion the best what you can do is to create a separate bundle where you can instantiate
the CacheManager and expose it under some getter method of your own interface through OSGi
service.

As you have your own CacheManager singleton accesible through OSGi service reference, you
can implement (for each bundle using that cache) your own CacheManagerFactory with constructor
which expect to get that referenced CachemManager as a parameter, like this:
{code}
public class YourCacheManagerFactory extends CacheManagerFactory {
    private CacheManager cacheManager;

    public YourCacheManagerFactory(CacheManager cacheManager) {
        if (cacheManager == null) {
            throw new RuntimeCamelException("cacheManager should never be null");
        }
        this.cacheManager = cacheManager;
    }

    @Override
    protected synchronized CacheManager createCacheManagerInstance() {
        return cacheManager;
    }
{code}

Then it could be referenced to the endpoint like this:

{code:xml}
<camelContext xmlns="http://camel.apache.org/schema/spring">
        <endpoint id="fooCache" uri="cache:foo?cacheManagerFactory=#yourReferencedCacheManagerFactory"
/>
</camelContext>
{code}

This should solve all your problems.

Please let me know if it works fine for you. If not, then i will do my best to help you.

Have a FUN! :)


> Allow to share cache between bundles, and only clear cache when no more bundles access
that cache
> -------------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-3686
>                 URL: https://issues.apache.org/jira/browse/CAMEL-3686
>             Project: Camel
>          Issue Type: Improvement
>          Components: camel-cache
>    Affects Versions: 2.4.0
>         Environment: camel-cache 2.4.0-fuse-01-00
>            Reporter: Justas
>             Fix For: 2.8.0
>
>         Attachments: camel-cache.zip, diff.txt
>
>
> I am using camel-cache component in serviceMix. Cache endpoint uri is 
> "cache://elements?maxElementsInMemory=2&memoryStoreEvictionPolicy=MemoryStoreEvictionPolicy.FIFO&overflowToDisk=false&eternal=false&timeToLiveSeconds=800"

> I have 2 bundles (core.jar, services.jar). Inside those bundles I use 
> @EndpointInject(uri = Constants.CACHE_URI) 
> ProducerTemplate cacheTemplate; 
> cacheTemplate.requestBodyAndHeaders(...) 
> core.jar puts and reads elements from cache. 
> services.jar only reads elements from cache. 
> After deploying both bundles it works fine, but if i uninstall services.jar, cache is
"destroyed". core.jar (and all others) can't put objects into cache anymore. 
> How could I make all bundles to "share" the same cache? 

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

Mime
View raw message