# Spring cache fixes
Project: http://git-wip-us.apache.org/repos/asf/incubator-ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-ignite/commit/1a2d2ca1 Tree: http://git-wip-us.apache.org/repos/asf/incubator-ignite/tree/1a2d2ca1 Diff: http://git-wip-us.apache.org/repos/asf/incubator-ignite/diff/1a2d2ca1 Branch: refs/heads/ignite-99 Commit: 1a2d2ca1e5b008b5dbab1e73513ac61bd9bbcdd9 Parents: b7db215 Author: Valentin Kulichenko <vkuliche...@gridgain.com> Authored: Tue Jan 20 23:24:59 2015 -0800 Committer: Valentin Kulichenko <vkuliche...@gridgain.com> Committed: Tue Jan 20 23:24:59 2015 -0800 ---------------------------------------------------------------------- .../grid/cache/spring/GridSpringCache.java | 185 +++++++++++ .../cache/spring/GridSpringCacheManager.java | 190 ++--------- .../spring/GridSpringDynamicCacheManager.java | 316 +++++++++++++++++++ .../spring/GridSpringCacheManagerSelfTest.java | 2 +- .../GridSpringDynamicCacheManagerSelfTest.java | 218 +++++++++++++ .../GridSpringDynamicCacheTestService.java | 62 ++++ .../cache/spring/spring-dynamic-caching.xml | 43 +++ .../testsuites/bamboo/GridSpringTestSuite.java | 1 + 8 files changed, 846 insertions(+), 171 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCache.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCache.java b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCache.java new file mode 100644 index 0000000..74baf53 --- /dev/null +++ b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCache.java @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gridgain.grid.cache.spring; + +import org.apache.ignite.*; +import org.apache.ignite.lang.*; +import org.gridgain.grid.cache.*; +import org.gridgain.grid.util.typedef.*; +import org.springframework.cache.*; +import org.springframework.cache.support.*; + +import java.io.*; + +/** + * Spring cache implementation. + */ +class GridSpringCache implements Cache, Serializable { + /** */ + private String name; + + /** */ + private Ignite ignite; + + /** */ + private GridCacheProjection<Object, Object> cache; + + /** */ + private IgniteClosure<Object, Object> keyFactory; + + /** + * @param name Cache name. + * @param ignite Ignite instance. + * @param cache Cache. + * @param keyFactory Key factory. + */ + GridSpringCache(String name, Ignite ignite, GridCacheProjection<?, ?> cache, + IgniteClosure<Object, Object> keyFactory) { + assert cache != null; + + this.name = name; + this.ignite = ignite; + this.cache = (GridCacheProjection<Object, Object>)cache; + this.keyFactory = keyFactory != null ? keyFactory : F.identity(); + } + + /** {@inheritDoc} */ + @Override public String getName() { + return name; + } + + /** {@inheritDoc} */ + @Override public Object getNativeCache() { + return cache; + } + + /** {@inheritDoc} */ + @Override public ValueWrapper get(Object key) { + try { + Object val = cache.get(keyFactory.apply(key)); + + return val != null ? new SimpleValueWrapper(val) : null; + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to get value from cache [cacheName=" + cache.name() + + ", key=" + key + ']', e); + } + } + + /** {@inheritDoc} */ + @Override public <T> T get(Object key, Class<T> type) { + try { + Object val = cache.get(keyFactory.apply(key)); + + if (val != null && type != null && !type.isInstance(val)) + throw new IllegalStateException("Cached value is not of required type [cacheName=" + cache.name() + + ", key=" + key + ", val=" + val + ", requiredType=" + type + ']'); + + return (T)val; + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to get value from cache [cacheName=" + cache.name() + + ", key=" + key + ']', e); + } + } + + /** {@inheritDoc} */ + @Override public void put(Object key, Object val) { + try { + cache.putx(keyFactory.apply(key), val); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to put value to cache [cacheName=" + cache.name() + + ", key=" + key + ", val=" + val + ']', e); + } + } + + /** {@inheritDoc} */ + @Override public ValueWrapper putIfAbsent(Object key, Object val) { + try { + Object old = cache.putIfAbsent(keyFactory.apply(key), val); + + return old != null ? new SimpleValueWrapper(old) : null; + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to put value to cache [cacheName=" + cache.name() + + ", key=" + key + ", val=" + val + ']', e); + } + } + + /** {@inheritDoc} */ + @Override public void evict(Object key) { + try { + cache.removex(keyFactory.apply(key)); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to remove value from cache [cacheName=" + cache.name() + + ", key=" + key + ']', e); + } + } + + /** {@inheritDoc} */ + @Override public void clear() { + try { + ignite.compute(cache.gridProjection()).broadcast(new ClearClosure(cache)); + } + catch (IgniteCheckedException e) { + throw new IgniteException("Failed to clear cache [cacheName=" + cache.name() + ']', e); + } + } + + /** + * Closure that removes all entries from cache. + */ + private static class ClearClosure extends CAX implements Externalizable { + /** */ + private static final long serialVersionUID = 0L; + + /** Cache projection. */ + private GridCacheProjection<Object, Object> cache; + + /** + * For {@link Externalizable}. + */ + public ClearClosure() { + // No-op. + } + + /** + * @param cache Cache projection. + */ + private ClearClosure(GridCacheProjection<Object, Object> cache) { + this.cache = cache; + } + + /** {@inheritDoc} */ + @Override public void applyx() throws IgniteCheckedException { + cache.removeAll(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + out.writeObject(cache); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + cache = (GridCacheProjection<Object, Object>)in.readObject(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCacheManager.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCacheManager.java b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCacheManager.java index 45c349a..0ab73f9 100644 --- a/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCacheManager.java +++ b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringCacheManager.java @@ -20,20 +20,16 @@ package org.gridgain.grid.cache.spring; import org.apache.ignite.*; import org.apache.ignite.configuration.*; import org.apache.ignite.lang.*; -import org.apache.ignite.resources.*; import org.gridgain.grid.cache.*; import org.gridgain.grid.util.typedef.*; -import org.gridgain.grid.util.typedef.internal.*; import org.springframework.beans.factory.*; import org.springframework.cache.*; -import org.springframework.cache.support.*; -import java.io.*; import java.util.*; /** * Implementation of Spring cache abstraction based on GridGain cache. - * <h1>Overview</h1> + * <h1 class="header">Overview</h1> * Spring cache abstraction allows to enable caching for Java methods * so that the result of a method execution is stored in some storage. If * later the same method is called with the same set of parameters, @@ -65,7 +61,7 @@ import java.util.*; * xsi:schemaLocation=" * http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd * http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> - * <-- Provide configuration file path --> + * <-- Provide configuration file path. --> * <bean id="cacheManager" class="org.gridgain.grid.cache.spring.GridSpringCacheManager"> * <property name="configurationPath" value="examples/config/spring-cache.xml"/> * </bean> @@ -108,7 +104,7 @@ import java.util.*; * xsi:schemaLocation=" * http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd * http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> - * <-- Provide configuration file path --> + * <-- Provide Grid name. --> * <bean id="cacheManager" class="org.gridgain.grid.cache.spring.GridSpringCacheManager"> * <property name="gridName" value="myGrid"/> * </bean> @@ -133,18 +129,18 @@ import java.util.*; * GridGain distribution, and all these nodes will participate * in caching data. */ -public class GridSpringCacheManager implements InitializingBean, CacheManager { +public class GridSpringCacheManager implements CacheManager, InitializingBean { /** Grid configuration file path. */ private String cfgPath; - /** Grid configuration. */ + /** Ignite configuration. */ private IgniteConfiguration cfg; /** Grid name. */ private String gridName; - /** Grid instance. */ - private Ignite ignite; + /** Ignite instance. */ + protected Ignite grid; /** * Gets configuration file path. @@ -203,7 +199,7 @@ public class GridSpringCacheManager implements InitializingBean, CacheManager { /** {@inheritDoc} */ @SuppressWarnings("IfMayBeConditional") @Override public void afterPropertiesSet() throws Exception { - assert ignite == null; + assert grid == null; if (cfgPath != null && cfg != null) { throw new IllegalArgumentException("Both 'configurationPath' and 'configuration' are " + @@ -213,179 +209,33 @@ public class GridSpringCacheManager implements InitializingBean, CacheManager { } if (cfgPath != null) - ignite = Ignition.start(cfgPath); + grid = Ignition.start(cfgPath); else if (cfg != null) - ignite = Ignition.start(cfg); + grid = Ignition.start(cfg); else - ignite = Ignition.ignite(gridName); + grid = Ignition.ignite(gridName); } /** {@inheritDoc} */ @Override public Cache getCache(String name) { - assert ignite != null; + assert grid != null; - return new SpringCache(ignite.cache(name)); + try { + return new GridSpringCache(name, grid, grid.cache(name), null); + } + catch (IllegalArgumentException ignored) { + return null; + } } /** {@inheritDoc} */ @Override public Collection<String> getCacheNames() { - assert ignite != null; + assert grid != null; - return F.viewReadOnly(ignite.caches(), new IgniteClosure<GridCache<?, ?>, String>() { + return F.viewReadOnly(grid.caches(), new IgniteClosure<GridCache<?,?>, String>() { @Override public String apply(GridCache<?, ?> c) { return c.name(); } }); } - - /** - * Cache implementation. - */ - private static class SpringCache implements Cache { - /** */ - private final GridCache<Object, Object> cache; - - /** - * @param cache Cache. - */ - SpringCache(GridCache<Object, Object> cache) { - assert cache != null; - - this.cache = cache; - } - - /** {@inheritDoc} */ - @Override public String getName() { - return cache.name(); - } - - /** {@inheritDoc} */ - @Override public Object getNativeCache() { - return cache; - } - - /** {@inheritDoc} */ - @Override public ValueWrapper get(Object key) { - try { - Object val = cache.get(key); - - return val != null ? new SimpleValueWrapper(val) : null; - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to get value from cache [cacheName=" + cache.name() + - ", key=" + key + ']', e); - } - } - - /** {@inheritDoc} */ - @Override public <T> T get(Object key, Class<T> type) { - try { - Object val = cache.get(key); - - if (val != null && type != null && !type.isInstance(val)) - throw new IllegalStateException("Cached value is not of required type [cacheName=" + cache.name() + - ", key=" + key + ", val=" + val + ", requiredType=" + type + ']'); - - return (T)val; - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to get value from cache [cacheName=" + cache.name() + - ", key=" + key + ']', e); - } - } - - /** {@inheritDoc} */ - @Override public void put(Object key, Object val) { - try { - cache.putx(key, val); - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to put value to cache [cacheName=" + cache.name() + - ", key=" + key + ", val=" + val + ']', e); - } - } - - /** {@inheritDoc} */ - @Override public ValueWrapper putIfAbsent(Object key, Object val) { - try { - Object old = cache.putIfAbsent(key, val); - - return old != null ? new SimpleValueWrapper(old) : null; - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to put value to cache [cacheName=" + cache.name() + - ", key=" + key + ", val=" + val + ']', e); - } - } - - /** {@inheritDoc} */ - @Override public void evict(Object key) { - try { - cache.removex(key); - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to remove value from cache [cacheName=" + cache.name() + - ", key=" + key + ']', e); - } - } - - /** {@inheritDoc} */ - @Override public void clear() { - try { - Ignite ignite = cache.gridProjection().ignite(); - - ignite.compute(cache.gridProjection()).broadcast(new ClearClosure(cache.name())); - } - catch (IgniteCheckedException e) { - throw new IgniteException("Failed to clear cache [cacheName=" + cache.name() + ']', e); - } - } - } - - /** - * Closure that removes all entries from cache. - */ - private static class ClearClosure extends CAX implements Externalizable { - /** */ - private static final long serialVersionUID = 0L; - - /** Cache name. */ - private String cacheName; - - /** Injected grid instance. */ - @IgniteInstanceResource - private Ignite ignite; - - /** - * For {@link Externalizable}. - */ - public ClearClosure() { - // No-op. - } - - /** - * @param cacheName Cache name. - */ - private ClearClosure(String cacheName) { - this.cacheName = cacheName; - } - - /** {@inheritDoc} */ - @Override public void applyx() throws IgniteCheckedException { - GridCache<Object, Object> cache = ignite.cache(cacheName); - - if (cache != null) - cache.removeAll(); - } - - /** {@inheritDoc} */ - @Override public void writeExternal(ObjectOutput out) throws IOException { - U.writeString(out, cacheName); - } - - /** {@inheritDoc} */ - @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { - cacheName = U.readString(in); - } - } } http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManager.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManager.java b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManager.java new file mode 100644 index 0000000..1cfed51 --- /dev/null +++ b/modules/spring/src/main/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManager.java @@ -0,0 +1,316 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gridgain.grid.cache.spring; + +import org.apache.ignite.*; +import org.apache.ignite.lang.*; +import org.gridgain.grid.cache.*; +import org.gridgain.grid.kernal.*; +import org.gridgain.grid.kernal.processors.cache.*; +import org.gridgain.grid.util.tostring.*; +import org.gridgain.grid.util.typedef.*; +import org.gridgain.grid.util.typedef.internal.*; +import org.springframework.cache.*; +import org.springframework.cache.annotation.*; + +import java.io.*; +import java.util.*; + +/** + * Extension of {@link GridSpringCacheManager} that adds an option to + * emulate dynamic cache creation for you Spring-based applications. + * <p> + * All the data will be actually cached in one GridGain cache. It's + * name should be provided to this cache manager via + * {@link #setDataCacheName(String)} configuration property. + * <p> + * Under the hood, this cache manager will create a cache projection + * for each cache name provided in {@link Cacheable}, {@link CachePut}, + * etc. annotations. Note that you're still able to use caches configured in + * GridGain configuration. Cache projection will be created only + * cache with provided name doesn't exist. + * <h1 class="header">Configuration</h1> + * {@link GridSpringDynamicCacheManager} inherits all configuration + * properties from {@link GridSpringCacheManager} (see it's JavaDoc + * for more information on how to enable GridGain-based caching in + * a Spring application). + * <p> + * Additionally you will need to set a GridGain cache name where the data for + * all dynamically created caches will be stored. By default its name + * is {@code null}, which refers to default cache. Here is the example + * of how to configure a named cache: + * <pre name="code" class="xml"> + * <beans xmlns="http://www.springframework.org/schema/beans" + * xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + * xmlns:cache="http://www.springframework.org/schema/cache" + * xsi:schemaLocation=" + * http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + * http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> + * <-- Provide configuration file path --> + * <bean id="cacheManager" class="org.gridgain.grid.cache.spring.GridSpringCacheManager"> + * <property name="dataCacheName" value="myDataCache"/> + * </bean> + * + * ... + * </beans> + * </pre> + * + * @see GridSpringCacheManager + */ +public class GridSpringDynamicCacheManager extends GridSpringCacheManager { + /** Data cache name. */ + private String dataCacheName; + + /** Meta cache. */ + private GridCacheProjectionEx<MetaKey, Cache> metaCache; + + /** Data cache. */ + private GridCache<DataKey, Object> dataCache; + + /** + * Sets data cache name. + * + * @return Data cache name. + */ + public String getDataCacheName() { + return dataCacheName; + } + + /** + * Gets data cache name. + * + * @param dataCacheName Data cache name. + */ + public void setDataCacheName(String dataCacheName) { + this.dataCacheName = dataCacheName; + } + + /** {@inheritDoc} */ + @Override public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + + metaCache = ((GridEx)grid).utilityCache(MetaKey.class, Cache.class); + dataCache = grid.cache(dataCacheName); + } + + /** {@inheritDoc} */ + @Override public Cache getCache(final String name) { + Cache cache = super.getCache(name); + + if (cache != null) + return cache; + + try { + MetaKey key = new MetaKey(name); + + cache = metaCache.get(key); + + if (cache == null) { + cache = new GridSpringCache(name, grid, dataCache.projection(new ProjectionFilter(name)), + new IgniteClosure<Object, Object>() { + @Override public Object apply(Object o) { + return new DataKey(name, o); + } + }); + + Cache old = metaCache.putIfAbsent(key, cache); + + if (old != null) + cache = old; + } + + return cache; + } + catch (IgniteCheckedException e) { + throw new IgniteException(e); + } + } + + /** {@inheritDoc} */ + @Override public Collection<String> getCacheNames() { + Collection<String> names = F.view(super.getCacheNames(), new IgnitePredicate<String>() { + @Override public boolean apply(String name) { + return !F.eq(name, dataCacheName); + } + }); + + return F.concat(false, names, F.transform(metaCache.entrySetx(), + new IgniteClosure<Map.Entry<MetaKey, Cache>, String>() { + @Override public String apply(Map.Entry<MetaKey, Cache> e) { + return e.getKey().name; + } + })); + } + + /** + * Meta key. + */ + private static class MetaKey extends GridCacheUtilityKey<MetaKey> implements Externalizable { + /** Cache name. */ + private String name; + + /** + * For {@link Externalizable}. + */ + public MetaKey() { + // No-op. + } + + /** + * @param name Cache name. + */ + private MetaKey(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override protected boolean equalsx(MetaKey key) { + return name != null ? name.equals(key.name) : key.name == null; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + return name.hashCode(); + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + U.writeString(out, name); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + name = U.readString(in); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(MetaKey.class, this); + } + } + + /** + * Data key. + */ + private static class DataKey implements Externalizable { + /** Cache name. */ + private String name; + + /** Key. */ + @GridToStringInclude + private Object key; + + /** + * @param name Cache name. + * @param key Key. + */ + private DataKey(String name, Object key) { + this.name = name; + this.key = key; + } + + /** + * For {@link Externalizable}. + */ + public DataKey() { + // No-op. + } + + /** {@inheritDoc} */ + @Override public boolean equals(Object o) { + if (this == o) + return true; + + if (o == null || getClass() != o.getClass()) + return false; + + DataKey key0 = (DataKey)o; + + return name != null ? name.equals(key0.name) : key0.name == null && + key != null ? key.equals(key0.key) : key0.key == null; + } + + /** {@inheritDoc} */ + @Override public int hashCode() { + int res = name != null ? name.hashCode() : 0; + + res = 31 * res + (key != null ? key.hashCode() : 0); + + return res; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + U.writeString(out, name); + out.writeObject(key); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + name = U.readString(in); + key = in.readObject(); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(DataKey.class, this); + } + } + + /** + * Projection filter. + */ + private static class ProjectionFilter implements IgniteBiPredicate<DataKey, Object>, Externalizable { + /** Cache name. */ + private String name; + + /** + * For {@link Externalizable}. + */ + public ProjectionFilter() { + // No-op. + } + + /** + * @param name Cache name. + */ + private ProjectionFilter(String name) { + this.name = name; + } + + /** {@inheritDoc} */ + @Override public boolean apply(DataKey key, Object val) { + return name != null ? name.equals(key.name) : key.name == null; + } + + /** {@inheritDoc} */ + @Override public void writeExternal(ObjectOutput out) throws IOException { + U.writeString(out, name); + } + + /** {@inheritDoc} */ + @Override public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { + name = U.readString(in); + } + + /** {@inheritDoc} */ + @Override public String toString() { + return S.toString(ProjectionFilter.class, this); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringCacheManagerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringCacheManagerSelfTest.java b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringCacheManagerSelfTest.java index 934447d..c16658c 100644 --- a/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringCacheManagerSelfTest.java +++ b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringCacheManagerSelfTest.java @@ -18,10 +18,10 @@ package org.gridgain.grid.cache.spring; import org.apache.ignite.configuration.*; -import org.gridgain.grid.cache.*; import org.apache.ignite.spi.discovery.tcp.*; import org.apache.ignite.spi.discovery.tcp.ipfinder.*; import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*; +import org.gridgain.grid.cache.*; import org.gridgain.testframework.junits.common.*; import org.springframework.beans.factory.*; import org.springframework.context.support.*; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManagerSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManagerSelfTest.java b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManagerSelfTest.java new file mode 100644 index 0000000..29dfd45 --- /dev/null +++ b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheManagerSelfTest.java @@ -0,0 +1,218 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gridgain.grid.cache.spring; + +import org.apache.ignite.configuration.*; +import org.apache.ignite.spi.discovery.tcp.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*; +import org.gridgain.grid.cache.*; +import org.gridgain.testframework.junits.common.*; +import org.springframework.beans.factory.*; +import org.springframework.cache.*; +import org.springframework.context.support.*; + +import java.lang.reflect.*; +import java.util.*; + +/** + * Spring cache test. + */ +public class GridSpringDynamicCacheManagerSelfTest extends GridCommonAbstractTest { + /** */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** */ + private static final String DATA_CACHE_NAME = "data"; + + /** */ + private GridSpringDynamicCacheTestService svc; + + /** */ + private CacheManager mgr; + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String gridName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(gridName); + + GridCacheConfiguration cache = new GridCacheConfiguration(); + + cache.setName(DATA_CACHE_NAME); + + cfg.setCacheConfiguration(cache); + + TcpDiscoverySpi disco = new TcpDiscoverySpi(); + + disco.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(disco); + + return cfg; + } + + /** {@inheritDoc} */ + @Override public String getTestGridName() { + return "testGrid"; + } + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + startGrid(); + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + stopAllGrids(); + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + BeanFactory factory = new ClassPathXmlApplicationContext( + "org/gridgain/grid/cache/spring/spring-dynamic-caching.xml"); + + svc = (GridSpringDynamicCacheTestService)factory.getBean("testService"); + mgr = (CacheManager)factory.getBean("cacheManager"); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + grid().cache(DATA_CACHE_NAME).removeAll(); + } + + /** + * @throws Exception If failed. + */ + public void testNames() throws Exception { + assertEquals("value1", svc.cacheable(1)); + + Collection<String> names = mgr.getCacheNames(); + + assertEquals(names.toString(), 2, names.size()); + } + + /** + * @throws Exception If failed. + */ + public void testCacheAndEvict() throws Exception { + GridCache<Object, String> c = grid().cache(DATA_CACHE_NAME); + + assertEquals("value1", svc.cacheable(1)); + + assertEquals(2, c.size()); + + assertEquals("value1", c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + + svc.cacheEvict(1); + + assertEquals(1, c.size()); + + assertEquals(null, c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + } + + /** + * @throws Exception If failed. + */ + public void testPutAndEvict() throws Exception { + GridCache<Object, String> c = grid().cache(DATA_CACHE_NAME); + + assertEquals("value1", svc.cachePut(1)); + + assertEquals(2, c.size()); + + assertEquals("value1", c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + + svc.cacheEvict(1); + + assertEquals(1, c.size()); + + assertEquals(null, c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + } + + /** + * @throws Exception If failed. + */ + public void testCacheAndEvictAll() throws Exception { + GridCache<Object, String> c = grid().cache(DATA_CACHE_NAME); + + assertEquals("value1", svc.cacheable(1)); + assertEquals("value2", svc.cacheable(2)); + + assertEquals(4, c.size()); + + assertEquals("value1", c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + assertEquals("value2", c.get(key("testCache1", 2))); + assertEquals("value2", c.get(key("testCache2", 2))); + + svc.cacheEvictAll(); + + assertEquals(2, c.size()); + + assertEquals(null, c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + assertEquals(null, c.get(key("testCache1", 2))); + assertEquals("value2", c.get(key("testCache2", 2))); + } + + + /** + * @throws Exception If failed. + */ + public void testPutAndEvictAll() throws Exception { + GridCache<Object, String> c = grid().cache(DATA_CACHE_NAME); + + assertEquals("value1", svc.cachePut(1)); + assertEquals("value2", svc.cachePut(2)); + + assertEquals(4, c.size()); + + assertEquals("value1", c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + assertEquals("value2", c.get(key("testCache1", 2))); + assertEquals("value2", c.get(key("testCache2", 2))); + + svc.cacheEvictAll(); + + assertEquals(2, c.size()); + + assertEquals(null, c.get(key("testCache1", 1))); + assertEquals("value1", c.get(key("testCache2", 1))); + assertEquals(null, c.get(key("testCache1", 2))); + assertEquals("value2", c.get(key("testCache2", 2))); + } + + /** + * @param cacheName Cache name. + * @param key Key. + * @return Data key. + * @throws Exception In case of error. + */ + private Object key(String cacheName, int key) throws Exception { + Class<?> cls = Class.forName(GridSpringDynamicCacheManager.class.getName() + "$DataKey"); + + Constructor<?> cons = cls.getDeclaredConstructor(String.class, Object.class); + + cons.setAccessible(true); + + return cons.newInstance(cacheName, key); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheTestService.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheTestService.java b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheTestService.java new file mode 100644 index 0000000..9c4accd --- /dev/null +++ b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/GridSpringDynamicCacheTestService.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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.gridgain.grid.cache.spring; + +import org.springframework.cache.annotation.*; + +/** + * Test service. + */ +public class GridSpringDynamicCacheTestService { + /** + * @param key Key. + * @return Value. + */ + @Cacheable({"testCache1", "testCache2"}) + public String cacheable(Integer key) { + assert key != null; + + return "value" + key; + } + + /** + * @param key Key. + * @return Value. + */ + @CachePut({"testCache1", "testCache2"}) + public String cachePut(Integer key) { + assert key != null; + + return "value" + key; + } + + /** + * @param key Key. + */ + @CacheEvict("testCache1") + public void cacheEvict(Integer key) { + // No-op. + } + + /** + */ + @CacheEvict(value = "testCache1", allEntries = true) + public void cacheEvictAll() { + // No-op. + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/test/java/org/gridgain/grid/cache/spring/spring-dynamic-caching.xml ---------------------------------------------------------------------- diff --git a/modules/spring/src/test/java/org/gridgain/grid/cache/spring/spring-dynamic-caching.xml b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/spring-dynamic-caching.xml new file mode 100644 index 0000000..ef2f80b --- /dev/null +++ b/modules/spring/src/test/java/org/gridgain/grid/cache/spring/spring-dynamic-caching.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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. + --> + +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:cache="http://www.springframework.org/schema/cache" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd"> + <!-- + Test service with cacheable methods. + --> + <bean id="testService" class="org.gridgain.grid.cache.spring.GridSpringDynamicCacheTestService"/> + + <!-- + Cache manager. + --> + <bean id="cacheManager" class="org.gridgain.grid.cache.spring.GridSpringDynamicCacheManager"> + <property name="gridName" value="testGrid"/> + <property name="dataCacheName" value="data"/> + </bean> + + <!-- + Enable annotation-driver configuration for caching. + --> + <cache:annotation-driven/> +</beans> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/1a2d2ca1/modules/spring/src/test/java/org/gridgain/testsuites/bamboo/GridSpringTestSuite.java ---------------------------------------------------------------------- diff --git a/modules/spring/src/test/java/org/gridgain/testsuites/bamboo/GridSpringTestSuite.java b/modules/spring/src/test/java/org/gridgain/testsuites/bamboo/GridSpringTestSuite.java index 99974e3..c5850a8 100644 --- a/modules/spring/src/test/java/org/gridgain/testsuites/bamboo/GridSpringTestSuite.java +++ b/modules/spring/src/test/java/org/gridgain/testsuites/bamboo/GridSpringTestSuite.java @@ -44,6 +44,7 @@ public class GridSpringTestSuite extends TestSuite { suite.addTest(new TestSuite(GridP2PContinuousLocalDeploySelfTest.class)); suite.addTest(new TestSuite(GridSpringCacheManagerSelfTest.class)); + suite.addTest(new TestSuite(GridSpringDynamicCacheManagerSelfTest.class)); return suite; }