2

I'm working with spring based application (not spring boot) and I'm trying to introduce cache2k as a spring cache manager.

Currently cache2k is used as a Hibernate second level cache by setting the following properties

hibernate.cache.use_second_level_cache = true
hibernate.cache.region.factory_class = org.hibernate.cache.jcache.JCacheRegionFactory
hibernate.javax.cache.provider = org.cache2k.jcache.provider.JCacheProvider

with the following cache2k.xml configuration file (only the relevant part related to the example)

<cache2k xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
     xmlns='https://cache2k.org/schema/v1.x'
     xsi:schemaLocation="https://cache2k.org/schema/v1.x https://cache2k.org/schema/cache2k-core-v1.x.xsd">
<!-- The configuration example for the documentation -->
<version>1.0</version>

<skipCheckOnStartup>true</skipCheckOnStartup>
<ignoreMissingCacheConfiguration>true</ignoreMissingCacheConfiguration>

<defaults>
    <cache>
        <entryCapacity>100</entryCapacity>
    </cache>
</defaults>

<templates>
    <cache>
        <name>lookupTable</name>
        <expireAfterWrite>1d</expireAfterWrite>
        <entryCapacity>50_000</entryCapacity>
    </cache>
</templates>

<caches>

    <cache>
        <name>AdvertisingCategoryCache</name>
        <include>lookupTable</include>
    </cache>

</caches>

Now I want to introduce a Spring cache manager and in the cache2k documentation there're enough information in order to introduce it as a spring cache manager also with the following code

@EnableCaching
...
...

@Bean
public CacheManager cacheManager() {
    return new SpringCache2kCacheManager();
}

The final goal is to reuse the existing hibernate second level cache also in the spring caching layer when needed but when calling the following method

@Cacheable(cacheNames = "AdvertisingCategoryCache")
@Override
public AdvertisingCategory findById(Long id) {
    // call to the repository
}

I get the following error

Cache already created: 'AdvertisingCategoryCache'

The point is that I know that the cache is already created. My need is to reuse the existing one.

How can I do that?

P.S. The example is very easy and for sure I can directly remove the @Cacheable method, but I've used that in order to provide an easy explanation of my situation.

Gavi
  • 1,300
  • 1
  • 19
  • 39

1 Answers1

2

Edit: since you are not using Spring Boot, you need to make sure to set the property that links the cache manager with Hibernate.

First of all you need to use JCache so you'll have to replace your custom cache configuration to use JCache (Hibernate does not provide a cache abstraction implementation for cache2k).

You should have some sort of custom JPA setup that configures the EntityManagerFactory. In that setup, makes sure to inject the CacheManager that you've created. If you have an injection point, the context will make sure to fully resolve the CacheManager before attempting to configure Hibernate (which is definitely what you want here).

Once you've done that, add the following Hibernate property:

hibernateProperties.put(ConfigSettings.CACHE_MANAGER, cacheManager.getCacheManager());

Where cacheManager is the JCacheCacheManager (the Spring implementation wrapping the native javax.cache.CacheManager).

Things are easier if you use Spring Boot. First of all, you should make sure to let Spring Boot configure the cache manager rather than doing it yourself. Since you are using JCache for Hibernate, just use the same mechanism in Spring Boot as it is totally transparent anyway (we'll wrap the JCache CacheManager in the right abstraction behind the scenes).

If you do that, Spring Boot will make sure to boostrap the JCache cache manager before hibernate starts. There is also a dediced how-to that explains how to configure the integration between the two.

Once you've done that, the same cache manager will be shared.

Stephane Nicoll
  • 31,977
  • 9
  • 97
  • 89
  • Hello Stephane, thank you for your answer. It's exactly what I need but your answer refers to a Spring Boot application, but as said before, unfortunately mine is not a spring boot application. – Gavi Dec 29 '18 at 11:45
  • Sorry, I missed that. Then you need to do in your custom JPA setup what I've indicated already. Make sure in particular to remove the last two properties there so that Hibernate does not attempt to lookup the cache infrastructure on its own. I've edited my answer with non Spring Boot advices – Stephane Nicoll Dec 29 '18 at 13:11