Reputation: 12081
I have tried to implement caching on Spring boot app several ways and this seems to be the right approach but it just logs that
CacheStatistics,CacheManager=urn.X-ehcache.jsr107-default-config,Cache=studentCache
Registering Ehcache MBean javax.cache:type=CacheStatistics,CacheManager=urn.X-ehcache.jsr107-default-config,Cache=studentCache
I have a event logger but I do not see any output from it:
@Component
public class EventLogger implements CacheEventListener<Object, Object> {
private static final Logger LOGGER = LoggerFactory.getLogger(EventLogger.class);
@Override
public void onEvent(CacheEvent<?, ?> event) {
LOGGER.info("Event: " + event.getType() + " Key: " + event.getKey() + " old value: " + event.getOldValue() + " new value: " + event.getNewValue());
}
}
CacheConfig
@Configuration
public class CacheConfig {
@Bean
public JCacheManagerCustomizer cacheManagerCustomizer() {
return new JCacheManagerCustomizer() {
@Override
public void customize(CacheManager cacheManager) {
cacheManager.createCache("studentCache", new MutableConfiguration<>()
.setExpiryPolicyFactory(CreatedExpiryPolicy.factoryOf(new Duration(TimeUnit.MINUTES, 5)))
.setStoreByValue(false)
.setStatisticsEnabled(true));
}
};
}
}
Cache on method
@RequestMapping(method = GET)
@ResponseBody
Cacheable(value = "studetNode")
public List<StudentNodeDto> findAll(HttpServletResponse response) {
val studentNodes = service.findAll();
ehcache.xml located under resources
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'>
<service>
<jsr107:defaults>
<jsr107:cache name="studentCache" template="heap-cache"/>
</jsr107:defaults>
</service>
<cache-template name="heap-cache">
<listeners>
<listener>
<class>org.terracotta.ehcache.EventLogger</class>
<event-firing-mode>ASYNCHRONOUS</event-firing-mode>
<event-ordering-mode>UNORDERED</event-ordering-mode>
<events-to-fire-on>CREATED</events-to-fire-on>
<events-to-fire-on>UPDATED</events-to-fire-on>
<events-to-fire-on>EXPIRED</events-to-fire-on>
<events-to-fire-on>REMOVED</events-to-fire-on>
<events-to-fire-on>EVICTED</events-to-fire-on>
</listener>
</listeners>
<resources>
<heap unit="entries">2000</heap>
<offheap unit="MB">100</offheap>
</resources>
</cache-template>
</config>
Gradle dependencies springBootVersion = '2.0.2.RELEASE'
compile group: 'org.springframework.boot', name: 'spring-boot-starter', version: springBootVersion
compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: springBootVersion
//Cache
compile group: 'org.springframework.boot', name: 'spring-boot-starter-cache', version: '2.1.1.RELEASE'
compile group: 'org.ehcache', name: 'ehcache', version: '3.4.0'
compile group: 'javax.cache', name: 'cache-api', version: '1.1.0'
I have looked over many post and blogs and it appears I am doing this correctl but I have to be wrong somewhere.
@Cacheable key on multiple method arguments
https://docs.spring.io/spring/docs/current/spring-framework-reference/integration.html#cache
https://www.baeldung.com/spring-cache-tutorial
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-caching.html
https://www.baeldung.com/hibernate-second-level-cache
https://medium.com/@igorkosandyak/spring-boot-caching-d74591abe117
Advice?
---------------Update 1-----------------
I am getting an error saying:
Error creating bean with name 'cacheManager' defined in class path
resource
[org/springframework/boot/autoconfigure/cache/JCacheCacheConfiguration.class]: Unsatisfied dependency expressed through method 'cacheManager' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jCacheCacheManager' defined in class path resource [org/springframework/boot/autoconfigure/cache/JCacheCacheConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [javax.cache.CacheManager]: Factory method 'jCacheCacheManager' threw exception; nested exception is org.ehcache.jsr107.MultiCacheException: [Exception 0] org.terracotta.ehcache.EventLogger
I get this when I added:
# caching
spring.cache.jcache.provider=org.ehcache.jsr107.EhcacheCachingProvider
spring.cache.jcache.config=classpath:ehcache.xml
Trace
restartedMain] heConfiguration$JCacheAvailableCondition : Condition JCacheCacheConfiguration.JCacheAvailableCondition on org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration matched due to AnyNestedCondition 1 matched 1 did not; NestedCondition on JCacheCacheConfiguration.JCacheAvailableCondition.CustomJCacheCacheManager @ConditionalOnSingleCandidate (types: javax.cache.CacheManager; SearchStrategy: all) did not find any beans; NestedCondition on JCacheCacheConfiguration.JCacheAvailableCondition.JCacheProvider JCache JCache provider specified
-------------- update 2------------------
I added the following to my gradle file
task showJarLocations {
doLast {
configurations.compile.resolve().each { file ->
println file.canonicalPath
}
}
}
and the only jar showing with ehcache is:
/org.ehcache/ehcache/3.4.0/cac1f0840af0040a81401dfa55fa31a4ccc17932/ehcache-3.4.0.jar
and
javax.cache/cache-api/1.1.0/77bdcff7814076dfa61611b0db88487c515150b6/cache-api-1.1.0.jar
I have
spring.cache.jcache.provider=org.ehcache.jsr107.EhcacheCachingProvider
spring.cache.jcache.config=classpath:ehcache.xml
in application.properties
too. This should explain why it fails when I add spring.cache.jcache.config=classpath:ehcache.xml.
Butin intellij it is in my project structure:
+--- org.springframework.boot:spring-boot-starter-cache:2.1.1.RELEASE
| +--- org.springframework.boot:spring-boot-starter:2.1.1.RELEASE -> 2.0.2.RELEASE (*)
| \--- org.springframework:spring-context-support:5.1.3.RELEASE -> 5.0.6.RELEASE
| +--- org.springframework:spring-beans:5.0.6.RELEASE (*)
| +--- org.springframework:spring-context:5.0.6.RELEASE (*)
| \--- org.springframework:spring-core:5.0.6.RELEASE (*)
+--- org.ehcache:ehcache:3.4.0
| \--- org.slf4j:slf4j-api:1.7.7 -> 1.7.25
+--- javax.cache:cache-api:1.1.0
+--- org.apache.tika:tika-core:1.19.1
+--- org.mapstruct:mapstruct-jdk8:1.2.0.Final
+--- org.projectlombok:lombok:1.18.2
Upvotes: 4
Views: 16397
Reputation: 13
Make your entity or dto implement Serializable. Worked in my case.
Upvotes: 0
Reputation: 2307
@EnableCaching
Ensure the name in @Cacheable
matches your cache name (you have a mismatch in what you posted.)
@Cacheable(value = "studentCache")
Remove your CacheConfig
Place your ehcache.xml file in a subfolder of resources to make sure you're not picking up one from some other jar
e.g. `resources/myconfig/ehcache.xml`
Set the property in application.properties to tell spring where to find the config file
spring.cache.jcache.config=classpath:myconfig/ehcache.xml
Use a simplified ehcache.xml. e.g.
<config
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns='http://www.ehcache.org/v3'
xmlns:jsr107='http://www.ehcache.org/v3/jsr107'
xsi:schemaLocation="
http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd
http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd">
<cache alias="studentCache" uses-template="heap-cache" />
<cache-template name="heap-cache">
<resources>
<heap unit="entries">2000</heap>
<offheap unit="MB">100</offheap>
</resources>
</cache-template>
</config>
If it still fails, post the results showing how you know it fails.
The reason you need the CacheConfig when using the <jsr107:cache
elements is that ehcache will just associate the template with the cache name. It doesn't create the cache. The template will be used when you create the cache programatically (i.e. in your CacheConfig). So if you try an ehcache.xml which defines the cache you don't need the CacheConfig
Upvotes: 0
Reputation: 43
I found that using the spring-boot-starter-cache can create some subtle problems. If your ehcache.xml isn't found or you misname the cache name, Spring appears to fallback to a generic cache implementation thus hiding the problem. Try removing spring-boot-starter-cache as a dependency and add:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
also add ehcache as an explicit dependency then see if that helps. You shouldn't need to even access a CacheManager since you are using ehcache.xml; the whole point of the xml is to make your configuration declarative and outside the code.
Upvotes: 3