From 8aa0b07768a105cb9f6852c0887f3115fa028552 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Sat, 20 Jul 2019 15:05:07 +0200 Subject: [PATCH] Consistent early eviction tests in regular and transactional scenarios See gh-23192 --- .../aspectj/AspectJCacheAnnotationTests.java | 2 +- .../AnnotatedClassCacheableService.java | 52 ++- .../cache/config/CacheableService.java | 15 +- .../cache/config/DefaultCacheableService.java | 63 ++-- .../jcache/JCacheEhCacheAnnotationTests.java | 31 +- .../config/AbstractCacheAnnotationTests.java | 309 ++++++++++-------- .../AnnotatedClassCacheableService.java | 21 +- .../config/CacheAdviceNamespaceTests.java | 2 +- .../cache/config/CacheableService.java | 12 +- .../cache/config/DefaultCacheableService.java | 19 +- .../cache/config/cache-advice.xml | 3 +- 11 files changed, 288 insertions(+), 241 deletions(-) diff --git a/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJCacheAnnotationTests.java b/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJCacheAnnotationTests.java index b7873c4c375..acf2d5255a2 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJCacheAnnotationTests.java +++ b/spring-aspects/src/test/java/org/springframework/cache/aspectj/AspectJCacheAnnotationTests.java @@ -38,7 +38,7 @@ public class AspectJCacheAnnotationTests extends AbstractCacheAnnotationTests { } @Test - public void testKeyStrategy() throws Exception { + public void testKeyStrategy() { AnnotationCacheAspect aspect = ctx.getBean( "org.springframework.cache.config.internalCacheAspect", AnnotationCacheAspect.class); assertThat(aspect.getKeyGenerator()).isSameAs(ctx.getBean("keyGenerator")); diff --git a/spring-aspects/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java b/spring-aspects/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java index 0cfe0d2538c..5872dffc780 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java +++ b/spring-aspects/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,11 +33,13 @@ import org.springframework.cache.annotation.Caching; public class AnnotatedClassCacheableService implements CacheableService { private final AtomicLong counter = new AtomicLong(); + public static final AtomicLong nullInvocations = new AtomicLong(); + @Override public Object cache(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -48,7 +50,7 @@ public class AnnotatedClassCacheableService implements CacheableService @Override @Cacheable(cacheNames = "testCache", sync = true) public Object cacheSync(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -68,13 +70,14 @@ public class AnnotatedClassCacheableService implements CacheableService } @Override + @Cacheable(cacheNames = "testCache", unless = "#result > 10") public Object unless(int arg) { return arg; } @Override - @CacheEvict("testCache") - public void invalidate(Object arg1) { + @CacheEvict(cacheNames = "testCache", key = "#p0") + public void evict(Object arg1, Object arg2) { } @Override @@ -83,11 +86,6 @@ public class AnnotatedClassCacheableService implements CacheableService throw new RuntimeException("exception thrown - evict should NOT occur"); } - @Override - @CacheEvict(cacheNames = "testCache", allEntries = true) - public void evictAll(Object arg1) { - } - @Override @CacheEvict(cacheNames = "testCache", beforeInvocation = true) public void evictEarly(Object arg1) { @@ -95,68 +93,68 @@ public class AnnotatedClassCacheableService implements CacheableService } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0") - public void evict(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true) + public void evictAll(Object arg1) { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0", beforeInvocation = true) - public void invalidateEarly(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true, beforeInvocation = true) + public void evictAllEarly(Object arg1) { throw new RuntimeException("exception thrown - evict should still occur"); } @Override @Cacheable(cacheNames = "testCache", key = "#p0") public Object key(Object arg1, Object arg2) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable("testCache") public Object varArgsKey(Object... args) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", key = "#root.methodName + #root.caches[0].name") public Object name(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target") public Object rootVars(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", keyGenerator = "customKyeGenerator") public Object customKeyGenerator(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", keyGenerator = "unknownBeanName") public Object unknownCustomKeyGenerator(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", cacheManager = "customCacheManager") public Object customCacheManager(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", cacheManager = "unknownBeanName") public Object unknownCustomCacheManager(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @CachePut("testCache") public Object update(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -203,25 +201,25 @@ public class AnnotatedClassCacheableService implements CacheableService @Override @Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") }) public Object multiCache(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#a0"), @CacheEvict(cacheNames = "primary", key = "#p0 + 'A'") }) public Object multiEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(cacheable = { @Cacheable(cacheNames = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") }) public Object multiCacheAndEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(cacheable = { @Cacheable(cacheNames = "primary", condition = "#a0 == 3") }, evict = { @CacheEvict("secondary") }) public Object multiConditionalCacheAndEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override diff --git a/spring-aspects/src/test/java/org/springframework/cache/config/CacheableService.java b/spring-aspects/src/test/java/org/springframework/cache/config/CacheableService.java index 24b825b70b8..e5ab4a5f94c 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/config/CacheableService.java +++ b/spring-aspects/src/test/java/org/springframework/cache/config/CacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ package org.springframework.cache.config; /** - * Basic service interface. + * Basic service interface for caching tests. * * @author Costin Leau * @author Phillip Webb @@ -33,17 +33,15 @@ public interface CacheableService { T cacheSyncNull(Object arg1); - void invalidate(Object arg1); + void evict(Object arg1, Object arg2); + + void evictWithException(Object arg1); void evictEarly(Object arg1); void evictAll(Object arg1); - void evictWithException(Object arg1); - - void evict(Object arg1, Object arg2); - - void invalidateEarly(Object arg1, Object arg2); + void evictAllEarly(Object arg1); T conditional(int field); @@ -83,7 +81,6 @@ public interface CacheableService { T throwUncheckedSync(Object arg1); - // multi annotations T multiCache(Object arg1); T multiEvict(Object arg1); diff --git a/spring-aspects/src/test/java/org/springframework/cache/config/DefaultCacheableService.java b/spring-aspects/src/test/java/org/springframework/cache/config/DefaultCacheableService.java index 882c9275fea..7df2bb4ea27 100644 --- a/spring-aspects/src/test/java/org/springframework/cache/config/DefaultCacheableService.java +++ b/spring-aspects/src/test/java/org/springframework/cache/config/DefaultCacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,7 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.cache.annotation.Caching; /** - * Simple cacheable service + * Simple cacheable service. * * @author Costin Leau * @author Phillip Webb @@ -34,12 +34,14 @@ import org.springframework.cache.annotation.Caching; public class DefaultCacheableService implements CacheableService { private final AtomicLong counter = new AtomicLong(); + private final AtomicLong nullInvocations = new AtomicLong(); + @Override @Cacheable("testCache") public Long cache(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -51,7 +53,7 @@ public class DefaultCacheableService implements CacheableService { @Override @Cacheable(cacheNames = "testCache", sync = true) public Long cacheSync(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -61,8 +63,8 @@ public class DefaultCacheableService implements CacheableService { } @Override - @CacheEvict("testCache") - public void invalidate(Object arg1) { + @CacheEvict(cacheNames = "testCache", key = "#p0") + public void evict(Object arg1, Object arg2) { } @Override @@ -71,11 +73,6 @@ public class DefaultCacheableService implements CacheableService { throw new RuntimeException("exception thrown - evict should NOT occur"); } - @Override - @CacheEvict(cacheNames = "testCache", allEntries = true) - public void evictAll(Object arg1) { - } - @Override @CacheEvict(cacheNames = "testCache", beforeInvocation = true) public void evictEarly(Object arg1) { @@ -83,26 +80,26 @@ public class DefaultCacheableService implements CacheableService { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0") - public void evict(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true) + public void evictAll(Object arg1) { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0", beforeInvocation = true) - public void invalidateEarly(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true, beforeInvocation = true) + public void evictAllEarly(Object arg1) { throw new RuntimeException("exception thrown - evict should still occur"); } @Override @Cacheable(cacheNames = "testCache", condition = "#p0 == 3") public Long conditional(int classField) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", sync = true, condition = "#p0 == 3") - public Long conditionalSync(int field) { - return counter.getAndIncrement(); + public Long conditionalSync(int classField) { + return this.counter.getAndIncrement(); } @Override @@ -114,55 +111,55 @@ public class DefaultCacheableService implements CacheableService { @Override @Cacheable(cacheNames = "testCache", key = "#p0") public Long key(Object arg1, Object arg2) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache") public Long varArgsKey(Object... args) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", key = "#root.methodName") public Long name(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", key = "#root.methodName + #root.method.name + #root.targetClass + #root.target") public Long rootVars(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", keyGenerator = "customKeyGenerator") public Long customKeyGenerator(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", keyGenerator = "unknownBeanName") public Long unknownCustomKeyGenerator(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", cacheManager = "customCacheManager") public Long customCacheManager(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Cacheable(cacheNames = "testCache", cacheManager = "unknownBeanName") public Long unknownCustomCacheManager(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @CachePut("testCache") public Long update(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @@ -174,13 +171,13 @@ public class DefaultCacheableService implements CacheableService { @Override @Cacheable("testCache") public Long nullValue(Object arg1) { - nullInvocations.incrementAndGet(); + this.nullInvocations.incrementAndGet(); return null; } @Override public Number nullInvocations() { - return nullInvocations.get(); + return this.nullInvocations.get(); } @Override @@ -212,25 +209,25 @@ public class DefaultCacheableService implements CacheableService { @Override @Caching(cacheable = { @Cacheable("primary"), @Cacheable("secondary") }) public Long multiCache(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames = "secondary", key = "#p0"), @CacheEvict(cacheNames = "primary", key = "#p0 + 'A'") }) public Long multiEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(cacheable = { @Cacheable(cacheNames = "primary", key = "#root.methodName") }, evict = { @CacheEvict("secondary") }) public Long multiCacheAndEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override @Caching(cacheable = { @Cacheable(cacheNames = "primary", condition = "#p0 == 3") }, evict = { @CacheEvict("secondary") }) public Long multiConditionalCacheAndEvict(Object arg1) { - return counter.getAndIncrement(); + return this.counter.getAndIncrement(); } @Override diff --git a/spring-context-support/src/test/java/org/springframework/cache/jcache/JCacheEhCacheAnnotationTests.java b/spring-context-support/src/test/java/org/springframework/cache/jcache/JCacheEhCacheAnnotationTests.java index b367b25273a..5e6d6db6be9 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/jcache/JCacheEhCacheAnnotationTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/jcache/JCacheEhCacheAnnotationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,12 +39,17 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.tests.transaction.CallCountingTransactionManager; +import org.springframework.transaction.support.TransactionTemplate; /** * @author Stephane Nicoll + * @author Juergen Hoeller */ public class JCacheEhCacheAnnotationTests extends AbstractCacheAnnotationTests { + private final TransactionTemplate txTemplate = new TransactionTemplate(new CallCountingTransactionManager()); + private CacheManager jCacheManager; @@ -76,6 +81,26 @@ public class JCacheEhCacheAnnotationTests extends AbstractCacheAnnotationTests { public void testCustomCacheManager() { } + @Test + public void testEvictWithTransaction() { + txTemplate.execute(() -> testEvict(this.cs, false)); + } + + @Test + public void testEvictEarlyWithTransaction() { + txTemplate.execute(() -> testEvictEarly(this.cs)); + } + + @Test + public void testEvictAllWithTransaction() { + txTemplate.execute(() -> testEvictAll(this.cs, false)); + } + + @Test + public void testEvictAllEarlyWithTransaction() { + txTemplate.execute(() -> testEvictAllEarly(this.cs)); + } + @Configuration @EnableCaching @@ -87,7 +112,9 @@ public class JCacheEhCacheAnnotationTests extends AbstractCacheAnnotationTests { @Override @Bean public org.springframework.cache.CacheManager cacheManager() { - return new JCacheCacheManager(jCacheManager()); + JCacheCacheManager cm = new JCacheCacheManager(jCacheManager()); + cm.setTransactionAware(true); + return cm; } @Bean diff --git a/spring-context/src/test/java/org/springframework/cache/config/AbstractCacheAnnotationTests.java b/spring-context/src/test/java/org/springframework/cache/config/AbstractCacheAnnotationTests.java index f532b992449..9023df7aef7 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/AbstractCacheAnnotationTests.java +++ b/spring-context/src/test/java/org/springframework/cache/config/AbstractCacheAnnotationTests.java @@ -79,7 +79,7 @@ public abstract class AbstractCacheAnnotationTests { } - public void testCacheable(CacheableService service) throws Exception { + public void testCacheable(CacheableService service) { Object o1 = new Object(); Object r1 = service.cache(o1); @@ -90,9 +90,9 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r3).isSameAs(r1); } - public void testCacheableNull(CacheableService service) throws Exception { + public void testCacheableNull(CacheableService service) { Object o1 = new Object(); - assertThat((Object) this.cm.getCache("testCache").get(o1)).isNull(); + assertThat(this.cm.getCache("testCache").get(o1)).isNull(); Object r1 = service.cacheNull(o1); Object r2 = service.cacheNull(o1); @@ -105,7 +105,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r3).as("Cached value should be null").isNull(); } - public void testCacheableSync(CacheableService service) throws Exception { + public void testCacheableSync(CacheableService service) { Object o1 = new Object(); Object r1 = service.cacheSync(o1); @@ -116,9 +116,9 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r3).isSameAs(r1); } - public void testCacheableSyncNull(CacheableService service) throws Exception { + public void testCacheableSyncNull(CacheableService service) { Object o1 = new Object(); - assertThat((Object) this.cm.getCache("testCache").get(o1)).isNull(); + assertThat(this.cm.getCache("testCache").get(o1)).isNull(); Object r1 = service.cacheSyncNull(o1); Object r2 = service.cacheSyncNull(o1); @@ -131,47 +131,53 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r3).as("Cached value should be null").isNull(); } - public void testEvict(CacheableService service) throws Exception { - Object o1 = new Object(); + public void testEvict(CacheableService service, boolean successExpected) { + Cache cache = this.cm.getCache("testCache"); + Object o1 = new Object(); + cache.putIfAbsent(o1, -1L); Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - assertThat(r2).isSameAs(r1); - service.invalidate(o1); - Object r3 = service.cache(o1); - Object r4 = service.cache(o1); - assertThat(r3).isNotSameAs(r1); - assertThat(r4).isSameAs(r3); + service.evict(o1, null); + if (successExpected) { + assertThat(cache.get(o1)).isNull(); + } + else { + assertThat(cache.get(o1)).isNotNull(); + } + + Object r2 = service.cache(o1); + if (successExpected) { + assertThat(r2).isNotSameAs(r1); + } + else { + assertThat(r2).isSameAs(r1); + } } - public void testEvictEarly(CacheableService service) throws Exception { - Object o1 = new Object(); + public void testEvictEarly(CacheableService service) { + Cache cache = this.cm.getCache("testCache"); + Object o1 = new Object(); + cache.putIfAbsent(o1, -1L); Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - assertThat(r2).isSameAs(r1); try { service.evictEarly(o1); } catch (RuntimeException ex) { // expected } + assertThat(cache.get(o1)).isNull(); - Object r3 = service.cache(o1); - Object r4 = service.cache(o1); - assertThat(r3).isNotSameAs(r1); - assertThat(r4).isSameAs(r3); + Object r2 = service.cache(o1); + assertThat(r2).isNotSameAs(r1); } - public void testEvictException(CacheableService service) throws Exception { + public void testEvictException(CacheableService service) { Object o1 = new Object(); - Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - assertThat(r2).isSameAs(r1); try { service.evictWithException(o1); } @@ -179,67 +185,95 @@ public abstract class AbstractCacheAnnotationTests { // expected } // exception occurred, eviction skipped, data should still be in the cache - Object r3 = service.cache(o1); - assertThat(r3).isSameAs(r1); + Object r2 = service.cache(o1); + assertThat(r2).isSameAs(r1); } - public void testEvictWKey(CacheableService service) throws Exception { + public void testEvictWithKey(CacheableService service) { Object o1 = new Object(); - Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - assertThat(r2).isSameAs(r1); service.evict(o1, null); - Object r3 = service.cache(o1); - Object r4 = service.cache(o1); - assertThat(r3).isNotSameAs(r1); - assertThat(r4).isSameAs(r3); + Object r2 = service.cache(o1); + assertThat(r2).isNotSameAs(r1); } - public void testEvictWKeyEarly(CacheableService service) throws Exception { + public void testEvictWithKeyEarly(CacheableService service) { Object o1 = new Object(); - Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - - assertThat(r2).isSameAs(r1); try { - service.invalidateEarly(o1, null); + service.evictEarly(o1); } catch (Exception ex) { // expected } - Object r3 = service.cache(o1); - Object r4 = service.cache(o1); - assertThat(r3).isNotSameAs(r1); - assertThat(r4).isSameAs(r3); + Object r2 = service.cache(o1); + assertThat(r2).isNotSameAs(r1); } - public void testEvictAll(CacheableService service) throws Exception { + public void testEvictAll(CacheableService service, boolean successExpected) { + Cache cache = this.cm.getCache("testCache"); + Object o1 = new Object(); + Object o2 = new Object(); + cache.putIfAbsent(o1, -1L); + cache.putIfAbsent(o2, -2L); Object r1 = service.cache(o1); - Object r2 = service.cache(o1); - - Object o2 = new Object(); - Object r10 = service.cache(o2); + Object r2 = service.cache(o2); + assertThat(r2).isNotSameAs(r1); - assertThat(r2).isSameAs(r1); - assertThat(r10).isNotSameAs(r1); service.evictAll(new Object()); + if (successExpected) { + assertThat(cache.get(o1)).isNull(); + assertThat(cache.get(o2)).isNull(); + } + else { + assertThat(cache.get(o1)).isNotNull(); + assertThat(cache.get(o2)).isNotNull(); + } + + Object r3 = service.cache(o1); + Object r4 = service.cache(o2); + if (successExpected) { + assertThat(r3).isNotSameAs(r1); + assertThat(r4).isNotSameAs(r2); + } + else { + assertThat(r3).isSameAs(r1); + assertThat(r4).isSameAs(r2); + } + } + + public void testEvictAllEarly(CacheableService service) { Cache cache = this.cm.getCache("testCache"); - assertThat((Object) cache.get(o1)).isNull(); - assertThat((Object) cache.get(o2)).isNull(); + + Object o1 = new Object(); + Object o2 = new Object(); + cache.putIfAbsent(o1, -1L); + cache.putIfAbsent(o2, -2L); + + Object r1 = service.cache(o1); + Object r2 = service.cache(o2); + assertThat(r2).isNotSameAs(r1); + + try { + service.evictAllEarly(new Object()); + } + catch (Exception ex) { + // expected + } + assertThat(cache.get(o1)).isNull(); + assertThat(cache.get(o2)).isNull(); Object r3 = service.cache(o1); - Object r4 = service.cache(o1); + Object r4 = service.cache(o2); assertThat(r3).isNotSameAs(r1); - assertThat(r4).isSameAs(r3); + assertThat(r4).isNotSameAs(r2); } - public void testConditionalExpression(CacheableService service) throws Exception { + public void testConditionalExpression(CacheableService service) { Object r1 = service.conditional(4); Object r2 = service.conditional(4); @@ -251,7 +285,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r4).isSameAs(r3); } - public void testConditionalExpressionSync(CacheableService service) throws Exception { + public void testConditionalExpressionSync(CacheableService service) { Object r1 = service.conditionalSync(4); Object r2 = service.conditionalSync(4); @@ -263,7 +297,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r4).isSameAs(r3); } - public void testUnlessExpression(CacheableService service) throws Exception { + public void testUnlessExpression(CacheableService service) { Cache cache = this.cm.getCache("testCache"); cache.clear(); service.unless(10); @@ -272,7 +306,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(cache.get(11)).isNull(); } - public void testKeyExpression(CacheableService service) throws Exception { + public void testKeyExpression(CacheableService service) { Object r1 = service.key(5, 1); Object r2 = service.key(5, 2); @@ -284,7 +318,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r4).isNotSameAs(r3); } - public void testVarArgsKey(CacheableService service) throws Exception { + public void testVarArgsKey(CacheableService service) { Object r1 = service.varArgsKey(1, 2, 3); Object r2 = service.varArgsKey(1, 2, 3); @@ -297,7 +331,7 @@ public abstract class AbstractCacheAnnotationTests { } - public void testNullValue(CacheableService service) throws Exception { + public void testNullValue(CacheableService service) { Object key = new Object(); assertThat(service.nullValue(key)).isNull(); int nr = service.nullInvocations().intValue(); @@ -307,7 +341,7 @@ public abstract class AbstractCacheAnnotationTests { assertThat(service.nullInvocations().intValue()).isEqualTo(nr + 1); } - public void testMethodName(CacheableService service, String keyName) throws Exception { + public void testMethodName(CacheableService service, String keyName) { Object key = new Object(); Object r1 = service.name(key); assertThat(service.name(key)).isSameAs(r1); @@ -326,27 +360,27 @@ public abstract class AbstractCacheAnnotationTests { assertThat(cache.get(expectedKey)).isNotNull(); } - public void testCheckedThrowable(CacheableService service) throws Exception { + public void testCheckedThrowable(CacheableService service) { String arg = UUID.randomUUID().toString(); assertThatIOException().isThrownBy(() -> service.throwChecked(arg)) .withMessage(arg); } - public void testUncheckedThrowable(CacheableService service) throws Exception { + public void testUncheckedThrowable(CacheableService service) { assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> service.throwUnchecked(1L)) .withMessage("1"); } - public void testCheckedThrowableSync(CacheableService service) throws Exception { + public void testCheckedThrowableSync(CacheableService service) { String arg = UUID.randomUUID().toString(); assertThatIOException().isThrownBy(() -> service.throwCheckedSync(arg)) .withMessage(arg); } - public void testUncheckedThrowableSync(CacheableService service) throws Exception { + public void testUncheckedThrowableSync(CacheableService service) { assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> service.throwUncheckedSync(1L)) .withMessage("1"); @@ -360,12 +394,12 @@ public abstract class AbstractCacheAnnotationTests { public void testCacheUpdate(CacheableService service) { Object o = new Object(); Cache cache = this.cm.getCache("testCache"); - assertThat((Object) cache.get(o)).isNull(); + assertThat(cache.get(o)).isNull(); Object r1 = service.update(o); assertThat(cache.get(o).get()).isSameAs(r1); o = new Object(); - assertThat((Object) cache.get(o)).isNull(); + assertThat(cache.get(o)).isNull(); Object r2 = service.update(o); assertThat(cache.get(o).get()).isSameAs(r2); } @@ -389,8 +423,8 @@ public abstract class AbstractCacheAnnotationTests { Cache primary = this.cm.getCache("primary"); Cache secondary = this.cm.getCache("secondary"); - assertThat((Object) primary.get(o1)).isNull(); - assertThat((Object) secondary.get(o1)).isNull(); + assertThat(primary.get(o1)).isNull(); + assertThat(secondary.get(o1)).isNull(); Object r1 = service.multiCache(o1); assertThat(primary.get(o1).get()).isSameAs(r1); assertThat(secondary.get(o1).get()).isSameAs(r1); @@ -401,8 +435,8 @@ public abstract class AbstractCacheAnnotationTests { assertThat(r2).isSameAs(r1); assertThat(r3).isSameAs(r1); - assertThat((Object) primary.get(o2)).isNull(); - assertThat((Object) secondary.get(o2)).isNull(); + assertThat(primary.get(o2)).isNull(); + assertThat(secondary.get(o2)).isNull(); Object r4 = service.multiCache(o2); assertThat(primary.get(o2).get()).isSameAs(r4); assertThat(secondary.get(o2).get()).isSameAs(r4); @@ -425,9 +459,9 @@ public abstract class AbstractCacheAnnotationTests { assertThat(secondary.get(o1).get()).isSameAs(r1); service.multiEvict(o1); - assertThat((Object) primary.get(o1)).isNull(); - assertThat((Object) secondary.get(o1)).isNull(); - assertThat((Object) primary.get(o2)).isNull(); + assertThat(primary.get(o1)).isNull(); + assertThat(secondary.get(o1)).isNull(); + assertThat(primary.get(o2)).isNull(); Object r3 = service.multiCache(o1); Object r4 = service.multiCache(o1); @@ -444,26 +478,26 @@ public abstract class AbstractCacheAnnotationTests { Cache primary = this.cm.getCache("primary"); Cache secondary = this.cm.getCache("secondary"); - assertThat((Object) primary.get(o)).isNull(); - assertThat((Object) secondary.get(o)).isNull(); + assertThat(primary.get(o)).isNull(); + assertThat(secondary.get(o)).isNull(); Object r1 = service.multiUpdate(o); assertThat(primary.get(o).get()).isSameAs(r1); assertThat(secondary.get(o).get()).isSameAs(r1); o = 2; - assertThat((Object) primary.get(o)).isNull(); - assertThat((Object) secondary.get(o)).isNull(); + assertThat(primary.get(o)).isNull(); + assertThat(secondary.get(o)).isNull(); Object r2 = service.multiUpdate(o); assertThat(primary.get(o).get()).isSameAs(r2); assertThat(secondary.get(o).get()).isSameAs(r2); } - public void testPutRefersToResult(CacheableService service) throws Exception { + public void testPutRefersToResult(CacheableService service) { Long id = Long.MIN_VALUE; TestEntity entity = new TestEntity(); Cache primary = this.cm.getCache("primary"); - assertThat((Object) primary.get(id)).isNull(); - assertThat((Object) entity.getId()).isNull(); + assertThat(primary.get(id)).isNull(); + assertThat(entity.getId()).isNull(); service.putRefersToResult(entity); assertThat(primary.get(id).get()).isSameAs(entity); } @@ -503,7 +537,7 @@ public abstract class AbstractCacheAnnotationTests { Object r3 = service.multiConditionalCacheAndEvict(key); assertThat(!r1.equals(r3)).isTrue(); - assertThat((Object) primary.get(key)).isNull(); + assertThat(primary.get(key)).isNull(); Object key2 = 3; Object r2 = service.multiConditionalCacheAndEvict(key2); @@ -515,127 +549,132 @@ public abstract class AbstractCacheAnnotationTests { } @Test - public void testCacheable() throws Exception { + public void testCacheable() { testCacheable(this.cs); } @Test - public void testCacheableNull() throws Exception { + public void testCacheableNull() { testCacheableNull(this.cs); } @Test - public void testCacheableSync() throws Exception { + public void testCacheableSync() { testCacheableSync(this.cs); } @Test - public void testCacheableSyncNull() throws Exception { + public void testCacheableSyncNull() { testCacheableSyncNull(this.cs); } @Test - public void testInvalidate() throws Exception { - testEvict(this.cs); + public void testEvict() { + testEvict(this.cs, true); } @Test - public void testEarlyInvalidate() throws Exception { + public void testEvictEarly() { testEvictEarly(this.cs); } @Test - public void testEvictWithException() throws Exception { + public void testEvictWithException() { testEvictException(this.cs); } @Test - public void testEvictAll() throws Exception { - testEvictAll(this.cs); + public void testEvictAll() { + testEvictAll(this.cs, true); + } + + @Test + public void testEvictAllEarly() { + testEvictAllEarly(this.cs); } @Test - public void testInvalidateWithKey() throws Exception { - testEvictWKey(this.cs); + public void testEvictWithKey() { + testEvictWithKey(this.cs); } @Test - public void testEarlyInvalidateWithKey() throws Exception { - testEvictWKeyEarly(this.cs); + public void testEvictWithKeyEarly() { + testEvictWithKeyEarly(this.cs); } @Test - public void testConditionalExpression() throws Exception { + public void testConditionalExpression() { testConditionalExpression(this.cs); } @Test - public void testConditionalExpressionSync() throws Exception { + public void testConditionalExpressionSync() { testConditionalExpressionSync(this.cs); } @Test - public void testUnlessExpression() throws Exception { + public void testUnlessExpression() { testUnlessExpression(this.cs); } @Test - public void testClassCacheUnlessExpression() throws Exception { + public void testClassCacheUnlessExpression() { testUnlessExpression(this.cs); } @Test - public void testKeyExpression() throws Exception { + public void testKeyExpression() { testKeyExpression(this.cs); } @Test - public void testVarArgsKey() throws Exception { + public void testVarArgsKey() { testVarArgsKey(this.cs); } @Test - public void testClassCacheCacheable() throws Exception { + public void testClassCacheCacheable() { testCacheable(this.ccs); } @Test - public void testClassCacheInvalidate() throws Exception { - testEvict(this.ccs); + public void testClassCacheEvict() { + testEvict(this.ccs, true); } @Test - public void testClassEarlyInvalidate() throws Exception { + public void testClassEvictEarly() { testEvictEarly(this.ccs); } @Test - public void testClassEvictAll() throws Exception { - testEvictAll(this.ccs); + public void testClassEvictAll() { + testEvictAll(this.ccs, true); } @Test - public void testClassEvictWithException() throws Exception { + public void testClassEvictWithException() { testEvictException(this.ccs); } @Test - public void testClassCacheInvalidateWKey() throws Exception { - testEvictWKey(this.ccs); + public void testClassCacheEvictWithWKey() { + testEvictWithKey(this.ccs); } @Test - public void testClassEarlyInvalidateWithKey() throws Exception { - testEvictWKeyEarly(this.ccs); + public void testClassEvictWithKeyEarly() { + testEvictWithKeyEarly(this.ccs); } @Test - public void testNullValue() throws Exception { + public void testNullValue() { testNullValue(this.cs); } @Test - public void testClassNullValue() throws Exception { + public void testClassNullValue() { Object key = new Object(); assertThat(this.ccs.nullValue(key)).isNull(); int nr = this.ccs.nullInvocations().intValue(); @@ -648,22 +687,22 @@ public abstract class AbstractCacheAnnotationTests { } @Test - public void testMethodName() throws Exception { + public void testMethodName() { testMethodName(this.cs, "name"); } @Test - public void testClassMethodName() throws Exception { + public void testClassMethodName() { testMethodName(this.ccs, "nametestCache"); } @Test - public void testRootVars() throws Exception { + public void testRootVars() { testRootVars(this.cs); } @Test - public void testClassRootVars() throws Exception { + public void testClassRootVars() { testRootVars(this.ccs); } @@ -704,52 +743,52 @@ public abstract class AbstractCacheAnnotationTests { } @Test - public void testNullArg() throws Exception { + public void testNullArg() { testNullArg(this.cs); } @Test - public void testClassNullArg() throws Exception { + public void testClassNullArg() { testNullArg(this.ccs); } @Test - public void testCheckedException() throws Exception { + public void testCheckedException() { testCheckedThrowable(this.cs); } @Test - public void testClassCheckedException() throws Exception { + public void testClassCheckedException() { testCheckedThrowable(this.ccs); } @Test - public void testCheckedExceptionSync() throws Exception { + public void testCheckedExceptionSync() { testCheckedThrowableSync(this.cs); } @Test - public void testClassCheckedExceptionSync() throws Exception { + public void testClassCheckedExceptionSync() { testCheckedThrowableSync(this.ccs); } @Test - public void testUncheckedException() throws Exception { + public void testUncheckedException() { testUncheckedThrowable(this.cs); } @Test - public void testClassUncheckedException() throws Exception { + public void testClassUncheckedException() { testUncheckedThrowable(this.ccs); } @Test - public void testUncheckedExceptionSync() throws Exception { + public void testUncheckedExceptionSync() { testUncheckedThrowableSync(this.cs); } @Test - public void testClassUncheckedExceptionSync() throws Exception { + public void testClassUncheckedExceptionSync() { testUncheckedThrowableSync(this.ccs); } @@ -804,12 +843,12 @@ public abstract class AbstractCacheAnnotationTests { } @Test - public void testPutRefersToResult() throws Exception { + public void testPutRefersToResult() { testPutRefersToResult(this.cs); } @Test - public void testClassPutRefersToResult() throws Exception { + public void testClassPutRefersToResult() { testPutRefersToResult(this.ccs); } diff --git a/spring-context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java b/spring-context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java index 3f1ae52f6f5..5872dffc780 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java +++ b/spring-context/src/test/java/org/springframework/cache/config/AnnotatedClassCacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ public class AnnotatedClassCacheableService implements CacheableService public static final AtomicLong nullInvocations = new AtomicLong(); + @Override public Object cache(Object arg1) { return this.counter.getAndIncrement(); @@ -75,8 +76,8 @@ public class AnnotatedClassCacheableService implements CacheableService } @Override - @CacheEvict("testCache") - public void invalidate(Object arg1) { + @CacheEvict(cacheNames = "testCache", key = "#p0") + public void evict(Object arg1, Object arg2) { } @Override @@ -85,11 +86,6 @@ public class AnnotatedClassCacheableService implements CacheableService throw new RuntimeException("exception thrown - evict should NOT occur"); } - @Override - @CacheEvict(cacheNames = "testCache", allEntries = true) - public void evictAll(Object arg1) { - } - @Override @CacheEvict(cacheNames = "testCache", beforeInvocation = true) public void evictEarly(Object arg1) { @@ -97,13 +93,13 @@ public class AnnotatedClassCacheableService implements CacheableService } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0") - public void evict(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true) + public void evictAll(Object arg1) { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0", beforeInvocation = true) - public void invalidateEarly(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true, beforeInvocation = true) + public void evictAllEarly(Object arg1) { throw new RuntimeException("exception thrown - evict should still occur"); } @@ -238,4 +234,5 @@ public class AnnotatedClassCacheableService implements CacheableService arg1.setId(Long.MIN_VALUE); return arg1; } + } diff --git a/spring-context/src/test/java/org/springframework/cache/config/CacheAdviceNamespaceTests.java b/spring-context/src/test/java/org/springframework/cache/config/CacheAdviceNamespaceTests.java index eb9eed2c196..43ae4ded6d2 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/CacheAdviceNamespaceTests.java +++ b/spring-context/src/test/java/org/springframework/cache/config/CacheAdviceNamespaceTests.java @@ -37,7 +37,7 @@ public class CacheAdviceNamespaceTests extends AbstractCacheAnnotationTests { } @Test - public void testKeyStrategy() throws Exception { + public void testKeyStrategy() { CacheInterceptor bean = this.ctx.getBean("cacheAdviceClass", CacheInterceptor.class); assertThat(bean.getKeyGenerator()).isSameAs(this.ctx.getBean("keyGenerator")); } diff --git a/spring-context/src/test/java/org/springframework/cache/config/CacheableService.java b/spring-context/src/test/java/org/springframework/cache/config/CacheableService.java index df14c3d7dd9..e5ab4a5f94c 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/CacheableService.java +++ b/spring-context/src/test/java/org/springframework/cache/config/CacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,17 +33,15 @@ public interface CacheableService { T cacheSyncNull(Object arg1); - void invalidate(Object arg1); + void evict(Object arg1, Object arg2); + + void evictWithException(Object arg1); void evictEarly(Object arg1); void evictAll(Object arg1); - void evictWithException(Object arg1); - - void evict(Object arg1, Object arg2); - - void invalidateEarly(Object arg1, Object arg2); + void evictAllEarly(Object arg1); T conditional(int field); diff --git a/spring-context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java b/spring-context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java index 4726400b56d..7df2bb4ea27 100644 --- a/spring-context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java +++ b/spring-context/src/test/java/org/springframework/cache/config/DefaultCacheableService.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2017 the original author or authors. + * Copyright 2002-2019 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,8 +63,8 @@ public class DefaultCacheableService implements CacheableService { } @Override - @CacheEvict("testCache") - public void invalidate(Object arg1) { + @CacheEvict(cacheNames = "testCache", key = "#p0") + public void evict(Object arg1, Object arg2) { } @Override @@ -73,11 +73,6 @@ public class DefaultCacheableService implements CacheableService { throw new RuntimeException("exception thrown - evict should NOT occur"); } - @Override - @CacheEvict(cacheNames = "testCache", allEntries = true) - public void evictAll(Object arg1) { - } - @Override @CacheEvict(cacheNames = "testCache", beforeInvocation = true) public void evictEarly(Object arg1) { @@ -85,13 +80,13 @@ public class DefaultCacheableService implements CacheableService { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0") - public void evict(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true) + public void evictAll(Object arg1) { } @Override - @CacheEvict(cacheNames = "testCache", key = "#p0", beforeInvocation = true) - public void invalidateEarly(Object arg1, Object arg2) { + @CacheEvict(cacheNames = "testCache", allEntries = true, beforeInvocation = true) + public void evictAllEarly(Object arg1) { throw new RuntimeException("exception thrown - evict should still occur"); } diff --git a/spring-context/src/test/resources/org/springframework/cache/config/cache-advice.xml b/spring-context/src/test/resources/org/springframework/cache/config/cache-advice.xml index fa9af8d6375..2c57ad3f822 100644 --- a/spring-context/src/test/resources/org/springframework/cache/config/cache-advice.xml +++ b/spring-context/src/test/resources/org/springframework/cache/config/cache-advice.xml @@ -27,12 +27,11 @@ - - +