Skip to content

Commit aaeb6d0

Browse files
committed
First attempt for fixing bug
See spring-projects#28554
1 parent 2269c00 commit aaeb6d0

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

spring-context-support/src/main/java/org/springframework/cache/transaction/AbstractTransactionSupportingCacheManager.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
package org.springframework.cache.transaction;
1818

1919
import org.springframework.cache.Cache;
20+
import org.springframework.cache.interceptor.CacheErrorHandler;
2021
import org.springframework.cache.support.AbstractCacheManager;
22+
import org.springframework.lang.Nullable;
2123

2224
/**
2325
* Base class for CacheManager implementations that want to support built-in
@@ -33,7 +35,8 @@
3335
public abstract class AbstractTransactionSupportingCacheManager extends AbstractCacheManager {
3436

3537
private boolean transactionAware = false;
36-
38+
@Nullable
39+
private CacheErrorHandler cacheErrorHandler;
3740

3841
/**
3942
* Set whether this CacheManager should expose transaction-aware Cache objects.
@@ -52,10 +55,15 @@ public boolean isTransactionAware() {
5255
return this.transactionAware;
5356
}
5457

58+
// TODO How to integrate org.springframework.cache.annotation.CachingConfigurer's errorHandler here?
59+
public void setCacheErrorHandler(@Nullable CacheErrorHandler cacheErrorHandler) {
60+
this.cacheErrorHandler = cacheErrorHandler;
61+
}
5562

5663
@Override
5764
protected Cache decorateCache(Cache cache) {
58-
return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache) : cache);
65+
return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache, cacheErrorHandler) : cache);
5966
}
6067

68+
6169
}

spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@
1616

1717
package org.springframework.cache.transaction;
1818

19-
import java.util.concurrent.Callable;
20-
2119
import org.springframework.cache.Cache;
20+
import org.springframework.cache.interceptor.CacheErrorHandler;
2221
import org.springframework.lang.Nullable;
2322
import org.springframework.transaction.support.TransactionSynchronization;
2423
import org.springframework.transaction.support.TransactionSynchronizationManager;
2524
import org.springframework.util.Assert;
2625

26+
import java.util.concurrent.Callable;
27+
2728
/**
2829
* Cache decorator which synchronizes its {@link #put}, {@link #evict} and
2930
* {@link #clear} operations with Spring-managed transactions (through Spring's
@@ -39,21 +40,32 @@
3940
* @author Juergen Hoeller
4041
* @author Stephane Nicoll
4142
* @author Stas Volsky
42-
* @since 3.2
4343
* @see TransactionAwareCacheManagerProxy
44+
* @since 3.2
4445
*/
4546
public class TransactionAwareCacheDecorator implements Cache {
4647

4748
private final Cache targetCache;
4849

50+
@Nullable
51+
private final CacheErrorHandler cacheErrorHandler;
52+
53+
54+
public TransactionAwareCacheDecorator(Cache targetCache) {
55+
this(targetCache, null);
56+
}
57+
4958

5059
/**
5160
* Create a new TransactionAwareCache for the given target Cache.
52-
* @param targetCache the target Cache to decorate
61+
*
62+
* @param targetCache the target Cache to decorate
63+
* @param cacheErrorHandler error handler used when deferred cache action fails (can be null)
5364
*/
54-
public TransactionAwareCacheDecorator(Cache targetCache) {
65+
public TransactionAwareCacheDecorator(Cache targetCache, @Nullable CacheErrorHandler cacheErrorHandler) {
5566
Assert.notNull(targetCache, "Target Cache must not be null");
5667
this.targetCache = targetCache;
68+
this.cacheErrorHandler = cacheErrorHandler;
5769
}
5870

5971

@@ -81,6 +93,7 @@ public ValueWrapper get(Object key) {
8193
}
8294

8395
@Override
96+
@Nullable
8497
public <T> T get(Object key, @Nullable Class<T> type) {
8598
return this.targetCache.get(key, type);
8699
}
@@ -97,7 +110,14 @@ public void put(final Object key, @Nullable final Object value) {
97110
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
98111
@Override
99112
public void afterCommit() {
100-
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
113+
try {
114+
TransactionAwareCacheDecorator.this.targetCache.put(key, value);
115+
} catch (RuntimeException e) {
116+
if (cacheErrorHandler != null) {
117+
cacheErrorHandler.handleCachePutError(e, targetCache, key, value);
118+
}
119+
throw e;
120+
}
101121
}
102122
});
103123
}
@@ -118,7 +138,14 @@ public void evict(final Object key) {
118138
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
119139
@Override
120140
public void afterCommit() {
121-
TransactionAwareCacheDecorator.this.targetCache.evict(key);
141+
try {
142+
TransactionAwareCacheDecorator.this.targetCache.evict(key);
143+
} catch (RuntimeException e) {
144+
if (cacheErrorHandler != null) {
145+
cacheErrorHandler.handleCacheEvictError(e, targetCache, key);
146+
}
147+
throw e;
148+
}
122149
}
123150
});
124151
}
@@ -138,7 +165,14 @@ public void clear() {
138165
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() {
139166
@Override
140167
public void afterCommit() {
141-
targetCache.clear();
168+
try {
169+
targetCache.clear();
170+
} catch (RuntimeException e) {
171+
if (cacheErrorHandler != null) {
172+
cacheErrorHandler.handleCacheClearError(e, targetCache);
173+
}
174+
throw e;
175+
}
142176
}
143177
});
144178
}

0 commit comments

Comments
 (0)