Browse Source
In the course of this enhancement, the "cache.ehcache" and "cache.jcache" packages moved from spring-context to the spring-context-support module, expecting further transaction-related functionality. Also aligns with the presence of Spring's Quartz support in the spring-context-support module, since Quartz and EHCache are sort of sister projects at Terracotta now. Issue: SPR-9966pull/188/head
20 changed files with 404 additions and 101 deletions
@ -0,0 +1,61 @@
@@ -0,0 +1,61 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.transaction; |
||||
|
||||
import org.springframework.cache.Cache; |
||||
import org.springframework.cache.support.AbstractCacheManager; |
||||
|
||||
/** |
||||
* Base class for CacheManager implementations that want to support built-in |
||||
* awareness of Spring-managed transactions. This usually needs to be switched |
||||
* on explicitly through the {@link #setTransactionAware} bean property. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 3.2 |
||||
* @see #setTransactionAware |
||||
* @see TransactionAwareCacheDecorator |
||||
* @see TransactionAwareCacheManagerProxy |
||||
*/ |
||||
public abstract class AbstractTransactionSupportingCacheManager extends AbstractCacheManager { |
||||
|
||||
private boolean transactionAware = false; |
||||
|
||||
|
||||
/** |
||||
* Set whether this CacheManager should expose transaction-aware Cache objects. |
||||
* <p>Default is "false". Set this to "true" to synchronize cache put/evict |
||||
* operations with ongoing Spring-managed transactions, performing the actual cache |
||||
* put/evict operation only in the after-commit phase of a successful transaction. |
||||
*/ |
||||
public void setTransactionAware(boolean transactionAware) { |
||||
this.transactionAware = transactionAware; |
||||
} |
||||
|
||||
/** |
||||
* Return whether this CacheManager has been configured to be transaction-aware. |
||||
*/ |
||||
public boolean isTransactionAware() { |
||||
return this.transactionAware; |
||||
} |
||||
|
||||
|
||||
@Override |
||||
protected Cache decorateCache(Cache cache) { |
||||
return (isTransactionAware() ? new TransactionAwareCacheDecorator(cache) : cache); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,94 @@
@@ -0,0 +1,94 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.transaction; |
||||
|
||||
import org.springframework.cache.Cache; |
||||
import org.springframework.transaction.support.TransactionSynchronizationAdapter; |
||||
import org.springframework.transaction.support.TransactionSynchronizationManager; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Cache decorator which synchronizes its {@link #put} and {@link #evict} operations with |
||||
* Spring-managed transactions (through Spring's {@link TransactionSynchronizationManager}, |
||||
* performing the actual cache put/evict operation only in the after-commit phase of a |
||||
* successful transaction. If no transaction is active, {@link #put} and {@link #evict} |
||||
* operations will be performed immediately, as usual. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 3.2 |
||||
* @see TransactionAwareCacheManagerProxy |
||||
*/ |
||||
public class TransactionAwareCacheDecorator implements Cache { |
||||
|
||||
private final Cache targetCache; |
||||
|
||||
|
||||
/** |
||||
* Create a new TransactionAwareCache for the given target Cache. |
||||
* @param targetCache the target Cache to decorate |
||||
*/ |
||||
public TransactionAwareCacheDecorator(Cache targetCache) { |
||||
Assert.notNull(targetCache, "Target Cache must not be null"); |
||||
this.targetCache = targetCache; |
||||
} |
||||
|
||||
|
||||
public String getName() { |
||||
return this.targetCache.getName(); |
||||
} |
||||
|
||||
public Object getNativeCache() { |
||||
return this.targetCache.getNativeCache(); |
||||
} |
||||
|
||||
public ValueWrapper get(Object key) { |
||||
return this.targetCache.get(key); |
||||
} |
||||
|
||||
public void put(final Object key, final Object value) { |
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) { |
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { |
||||
@Override |
||||
public void afterCommit() { |
||||
targetCache.put(key, value); |
||||
} |
||||
}); |
||||
} |
||||
else { |
||||
this.targetCache.put(key, value); |
||||
} |
||||
} |
||||
|
||||
public void evict(final Object key) { |
||||
if (TransactionSynchronizationManager.isSynchronizationActive()) { |
||||
TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { |
||||
@Override |
||||
public void afterCommit() { |
||||
targetCache.evict(key); |
||||
} |
||||
}); |
||||
} |
||||
else { |
||||
this.targetCache.evict(key); |
||||
} |
||||
} |
||||
|
||||
public void clear() { |
||||
this.targetCache.clear(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,83 @@
@@ -0,0 +1,83 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.transaction; |
||||
|
||||
import java.util.Collection; |
||||
|
||||
import org.springframework.beans.factory.InitializingBean; |
||||
import org.springframework.cache.Cache; |
||||
import org.springframework.cache.CacheManager; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* Proxy for a target {@link CacheManager}, exposing transaction-aware {@link Cache} objects |
||||
* which synchronize their {@link Cache#put} operations with Spring-managed transactions |
||||
* (through Spring's {@link org.springframework.transaction.support.TransactionSynchronizationManager}, |
||||
* performing the actual cache put operation only in the after-commit phase of a successful transaction. |
||||
* If no transaction is active, {@link Cache#put} operations will be performed immediately, as usual. |
||||
* |
||||
* @author Juergen Hoeller |
||||
* @since 3.2 |
||||
* @see #setTargetCacheManager |
||||
* @see TransactionAwareCacheDecorator |
||||
* @see org.springframework.transaction.support.TransactionSynchronizationManager |
||||
*/ |
||||
public class TransactionAwareCacheManagerProxy implements CacheManager, InitializingBean { |
||||
|
||||
private CacheManager targetCacheManager; |
||||
|
||||
|
||||
/** |
||||
* Create a new TransactionAwareCacheManagerProxy, setting the target CacheManager |
||||
* through the {@link #setTargetCacheManager} bean property. |
||||
*/ |
||||
public TransactionAwareCacheManagerProxy() { |
||||
} |
||||
|
||||
/** |
||||
* Create a new TransactionAwareCacheManagerProxy for the given target CacheManager. |
||||
* @param targetCacheManager the target CacheManager to proxy |
||||
*/ |
||||
public TransactionAwareCacheManagerProxy(CacheManager targetCacheManager) { |
||||
Assert.notNull(targetCacheManager, "Target CacheManager must not be null"); |
||||
this.targetCacheManager = targetCacheManager; |
||||
} |
||||
|
||||
|
||||
/** |
||||
* Set the target CacheManager to proxy. |
||||
*/ |
||||
public void setTargetCacheManager(CacheManager targetCacheManager) { |
||||
this.targetCacheManager = targetCacheManager; |
||||
} |
||||
|
||||
public void afterPropertiesSet() { |
||||
if (this.targetCacheManager == null) { |
||||
throw new IllegalStateException("'targetCacheManager' is required"); |
||||
} |
||||
} |
||||
|
||||
|
||||
public Cache getCache(String name) { |
||||
return new TransactionAwareCacheDecorator(this.targetCacheManager.getCache(name)); |
||||
} |
||||
|
||||
public Collection<String> getCacheNames() { |
||||
return this.targetCacheManager.getCacheNames(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,5 @@
@@ -0,0 +1,5 @@
|
||||
/** |
||||
* Transaction-aware decorators for the the org.springframework.cache package. |
||||
* Provides synchronization of put operations with Spring-managed transactions. |
||||
*/ |
||||
package org.springframework.cache.transaction; |
||||
@ -1,62 +0,0 @@
@@ -1,62 +0,0 @@
|
||||
/* |
||||
* Copyright 2010-2011 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.cache.ehcache; |
||||
|
||||
import static org.junit.Assert.*; |
||||
import net.sf.ehcache.Ehcache; |
||||
import net.sf.ehcache.Element; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.cache.Cache; |
||||
import org.springframework.cache.vendor.AbstractNativeCacheTests; |
||||
|
||||
/** |
||||
* Integration test for EhCache cache. |
||||
* |
||||
* @author Costin Leau |
||||
*/ |
||||
public class EhCacheCacheTests extends AbstractNativeCacheTests<Ehcache> { |
||||
|
||||
@Override |
||||
protected Ehcache createNativeCache() throws Exception { |
||||
EhCacheFactoryBean fb = new EhCacheFactoryBean(); |
||||
fb.setBeanName(CACHE_NAME); |
||||
fb.setCacheName(CACHE_NAME); |
||||
fb.afterPropertiesSet(); |
||||
return fb.getObject(); |
||||
} |
||||
|
||||
@Override |
||||
protected Cache createCache(Ehcache nativeCache) { |
||||
return new EhCacheCache(nativeCache); |
||||
} |
||||
|
||||
@Test |
||||
public void testExpiredElements() throws Exception { |
||||
String key = "brancusi"; |
||||
String value = "constantin"; |
||||
Element brancusi = new Element(key, value); |
||||
// ttl = 10s
|
||||
brancusi.setTimeToLive(3); |
||||
nativeCache.put(brancusi); |
||||
|
||||
assertEquals(value, cache.get(key).get()); |
||||
// wait for the entry to expire
|
||||
Thread.sleep(5 * 1000); |
||||
assertNull(cache.get(key)); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue