Dynamic cache configuration

Hey all,

I’ve been using Hibernate 5.4.2.Final with second-level caching using hibernate-jcache 5.4.2.Final and ehcache 3.7.1 in my Spring application, but I haven’t found a good way to dynamically configure the cache properties (such as time to live). I know that these properties can be configured using an ehcache.xml file, but this does not allow dynamic configuration, and it would be much more ideal if I could access and change the cache configuration when building the Hibernate session.

The only workaround I’ve found has been to extend another RegionFactory, copy the methods, and statically set the cache configuration and cache manager before building the Hibernate session factory and pointing the cache region factory to my custom region factory.

Eg.

MyCustomEhcacheRegionFactory.java

import org.hibernate.cache.jcache.internal.JCacheRegionFactory;
import javax.cache.configuration.Configuration;
...
public class MyCustomEhcacheRegionFactory extends JCacheRegionFactory {
    private static Configuration cacheConfiguration = null;

    public static void setCacheConfig(Configuration cacheConfiguration) {
        MyCustomEhcacheRegionFactory.cacheConfiguration = cacheConfiguration;
    }

    @Override
    protected Cache<Object, Object> createCache(String regionName) {
        switch(this.missingCacheStrategy) {
            case CREATE_WARN:
                SecondLevelCacheLogger.INSTANCE.missingCacheCreated(regionName, "hibernate.javax.cache.missing_cache_strategy", MissingCacheStrategy.CREATE.getExternalRepresentation());
                return MyCustomEhcacheRegionFactory.cacheManager.createCache(regionName, MyCustomEhcacheRegionFactory.cacheConfiguration);
            case CREATE:
                return MyCustomEhcacheRegionFactory.cacheManager.createCache(regionName, MyCustomEhcacheRegionFactory.cacheConfiguration);
            case FAIL:
                throw new CacheException("On-the-fly creation of JCache Cache objects is not supported [" + regionName + "]");
            default:
                throw new IllegalStateException("Unsupported missing cache strategy: " + this.missingCacheStrategy);
        }
    }
    ....
}

Then I can set the configuration dynamically:

// Logic to build cache config
MyCustomEhcacheRegionFactory.setCacheConfig(...)

…and then point to my custom class with

settings.put(Environment.CACHE_REGION_FACTORY,
                             "...MyCustomEhcacheRegionFactory");

This is of course not ideal…Is there a better or more supported way to do this? Will something be added in the future to allow dynamic cache configuration?

Thanks!

At €Day Job we have implemented this interface: org.hibernate.service.spi.ServiceContributor, and registered it using a file with our implementation class name in src/main/resources/META-INF/services/org.hibernate.service.spi.ServiceContributor. From there we use the StandardServiceRegistryBuilder from Hibernate to push the cache settings. This works quite wonderfully, since we are able to have different cache-configurations (i.e. sizes and idle times) per application next to our application and cache code. We are even able to modify the caches in production environment by providing our own overrides in a properties file that is read in the sevice contributor during startup.

It would be great if we could modify the size and other parameters of the caches at runtime without having to restart the node.