diff --git a/pom.xml b/pom.xml
index f6bd8cd2..6f5735ff 100644
--- a/pom.xml
+++ b/pom.xml
@@ -18,8 +18,8 @@
- 3.0.1
- 3.0.1
+ 3.0.2
+ 3.0.2
2.3.0.BUILD-SNAPSHOT
spring.data.couchbase
@@ -39,7 +39,7 @@
org.springframework
- spring-context
+ spring-context-support
org.springframework
diff --git a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java
index c501ca05..b33d90ea 100644
--- a/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java
+++ b/src/main/java/org/springframework/data/couchbase/cache/CouchbaseCacheManager.java
@@ -17,18 +17,21 @@
package org.springframework.data.couchbase.cache;
import java.util.Collection;
+import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
import org.springframework.cache.Cache;
-import org.springframework.cache.support.AbstractCacheManager;
+import org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager;
import org.springframework.data.couchbase.CouchbaseClientFactory;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
-public class CouchbaseCacheManager extends AbstractCacheManager {
+public class CouchbaseCacheManager extends AbstractTransactionSupportingCacheManager {
private final CouchbaseCacheWriter cacheWriter;
private final CouchbaseCacheConfiguration defaultCacheConfig;
@@ -45,20 +48,51 @@ public class CouchbaseCacheManager extends AbstractCacheManager {
* @param allowInFlightCacheCreation allow create unconfigured caches.
*/
private CouchbaseCacheManager(final CouchbaseCacheWriter cacheWriter,
- final CouchbaseCacheConfiguration defaultCacheConfiguration, final boolean allowInFlightCacheCreation) {
+ final CouchbaseCacheConfiguration defaultCacheConfiguration,
+ final Map initialCacheConfiguration,
+ final boolean allowInFlightCacheCreation) {
Assert.notNull(cacheWriter, "CacheWriter must not be null!");
Assert.notNull(defaultCacheConfiguration, "DefaultCacheConfiguration must not be null!");
this.cacheWriter = cacheWriter;
this.defaultCacheConfig = defaultCacheConfiguration;
- this.initialCacheConfiguration = new LinkedHashMap<>();
+ this.initialCacheConfiguration = initialCacheConfiguration;
this.allowInFlightCacheCreation = allowInFlightCacheCreation;
}
- public static CouchbaseCacheManager create(final CouchbaseClientFactory connectionFactory) {
- return new CouchbaseCacheManager(new DefaultCouchbaseCacheWriter(connectionFactory),
- CouchbaseCacheConfiguration.defaultCacheConfig(), true);
+ /**
+ * Create a new {@link CouchbaseCacheManager} with defaults applied.
+ *
+ * @param clientFactory must not be {@literal null}.
+ * @return new instance of {@link CouchbaseCacheManager}.
+ */
+ public static CouchbaseCacheManager create(CouchbaseClientFactory clientFactory) {
+ Assert.notNull(clientFactory, "ConnectionFactory must not be null!");
+ return new CouchbaseCacheManager(new DefaultCouchbaseCacheWriter(clientFactory),
+ CouchbaseCacheConfiguration.defaultCacheConfig(), new LinkedHashMap<>(), true);
+ }
+
+ /**
+ * Entry point for builder style {@link CouchbaseCacheManager} configuration.
+ *
+ * @param clientFactory must not be {@literal null}.
+ * @return new {@link CouchbaseCacheManagerBuilder}.
+ */
+ public static CouchbaseCacheManagerBuilder builder(CouchbaseClientFactory clientFactory) {
+ Assert.notNull(clientFactory, "ConnectionFactory must not be null!");
+ return CouchbaseCacheManagerBuilder.fromConnectionFactory(clientFactory);
+ }
+
+ /**
+ * Entry point for builder style {@link CouchbaseCacheManager} configuration.
+ *
+ * @param cacheWriter must not be {@literal null}.
+ * @return new {@link CouchbaseCacheManagerBuilder}.
+ */
+ public static CouchbaseCacheManagerBuilder builder(CouchbaseCacheWriter cacheWriter) {
+ Assert.notNull(cacheWriter, "CacheWriter must not be null!");
+ return CouchbaseCacheManagerBuilder.fromCacheWriter(cacheWriter);
}
@Override
@@ -89,4 +123,155 @@ public class CouchbaseCacheManager extends AbstractCacheManager {
return new CouchbaseCache(name, cacheWriter, cacheConfig != null ? cacheConfig : defaultCacheConfig);
}
+ public static class CouchbaseCacheManagerBuilder {
+
+ private final CouchbaseCacheWriter cacheWriter;
+ private CouchbaseCacheConfiguration defaultCacheConfiguration = CouchbaseCacheConfiguration.defaultCacheConfig();
+ private final Map initialCaches = new LinkedHashMap<>();
+ private boolean enableTransactions;
+ boolean allowInFlightCacheCreation = true;
+
+ private CouchbaseCacheManagerBuilder(CouchbaseCacheWriter cacheWriter) {
+ this.cacheWriter = cacheWriter;
+ }
+
+ /**
+ * Entry point for builder style {@link CouchbaseCacheManager} configuration.
+ *
+ * @param clientFactory must not be {@literal null}.
+ * @return new {@link CouchbaseCacheManagerBuilder}.
+ */
+ public static CouchbaseCacheManagerBuilder fromConnectionFactory(CouchbaseClientFactory clientFactory) {
+ Assert.notNull(clientFactory, "ConnectionFactory must not be null!");
+ return builder(new DefaultCouchbaseCacheWriter(clientFactory));
+ }
+
+ /**
+ * Entry point for builder style {@link CouchbaseCacheManager} configuration.
+ *
+ * @param cacheWriter must not be {@literal null}.
+ * @return new {@link CouchbaseCacheManagerBuilder}.
+ */
+ public static CouchbaseCacheManagerBuilder fromCacheWriter(CouchbaseCacheWriter cacheWriter) {
+ Assert.notNull(cacheWriter, "CacheWriter must not be null!");
+ return new CouchbaseCacheManagerBuilder(cacheWriter);
+ }
+
+ /**
+ * Define a default {@link CouchbaseCacheConfiguration} applied to dynamically created {@link CouchbaseCache}s.
+ *
+ * @param defaultCacheConfiguration must not be {@literal null}.
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder cacheDefaults(CouchbaseCacheConfiguration defaultCacheConfiguration) {
+ Assert.notNull(defaultCacheConfiguration, "DefaultCacheConfiguration must not be null!");
+ this.defaultCacheConfiguration = defaultCacheConfiguration;
+ return this;
+ }
+
+ /**
+ * Enable {@link CouchbaseCache}s to synchronize cache put/evict operations with ongoing Spring-managed transactions.
+ *
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder transactionAware() {
+ this.enableTransactions = true;
+ return this;
+ }
+
+ /**
+ * Append a {@link Set} of cache names to be pre initialized with current {@link CouchbaseCacheConfiguration}.
+ * NOTE: This calls depends on {@link #cacheDefaults(CouchbaseCacheConfiguration)} using whatever
+ * default {@link CouchbaseCacheConfiguration} is present at the time of invoking this method.
+ *
+ * @param cacheNames must not be {@literal null}.
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder initialCacheNames(Set cacheNames) {
+ Assert.notNull(cacheNames, "CacheNames must not be null!");
+ cacheNames.forEach(it -> withCacheConfiguration(it, defaultCacheConfiguration));
+ return this;
+ }
+
+ /**
+ * Append a {@link Map} of cache name/{@link CouchbaseCacheConfiguration} pairs to be pre initialized.
+ *
+ * @param cacheConfigurations must not be {@literal null}.
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder withInitialCacheConfigurations(
+ Map cacheConfigurations) {
+
+ Assert.notNull(cacheConfigurations, "CacheConfigurations must not be null!");
+ cacheConfigurations.forEach((cacheName, configuration) -> Assert.notNull(configuration,
+ String.format("CouchbaseCacheConfiguration for cache %s must not be null!", cacheName)));
+
+ this.initialCaches.putAll(cacheConfigurations);
+ return this;
+ }
+
+ /**
+ * @param cacheName
+ * @param cacheConfiguration
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder withCacheConfiguration(String cacheName,
+ CouchbaseCacheConfiguration cacheConfiguration) {
+
+ Assert.notNull(cacheName, "CacheName must not be null!");
+ Assert.notNull(cacheConfiguration, "CacheConfiguration must not be null!");
+
+ this.initialCaches.put(cacheName, cacheConfiguration);
+ return this;
+ }
+
+ /**
+ * Disable in-flight {@link org.springframework.cache.Cache} creation for unconfigured caches.
+ *
+ * {@link CouchbaseCacheManager#getMissingCache(String)} returns {@literal null} for any unconfigured
+ * {@link org.springframework.cache.Cache} instead of a new {@link CouchbaseCache} instance. This allows eg.
+ * {@link org.springframework.cache.support.CompositeCacheManager} to chime in.
+ *
+ * @return this {@link CouchbaseCacheManagerBuilder}.
+ */
+ public CouchbaseCacheManagerBuilder disableCreateOnMissingCache() {
+
+ this.allowInFlightCacheCreation = false;
+ return this;
+ }
+
+ /**
+ * Get the {@link Set} of cache names for which the builder holds {@link CouchbaseCacheConfiguration configuration}.
+ *
+ * @return an unmodifiable {@link Set} holding the name of caches for which a {@link CouchbaseCacheConfiguration
+ * configuration} has been set.
+ */
+ public Set getConfiguredCaches() {
+ return Collections.unmodifiableSet(this.initialCaches.keySet());
+ }
+
+ /**
+ * Get the {@link CouchbaseCacheConfiguration} for a given cache by its name.
+ *
+ * @param cacheName must not be {@literal null}.
+ * @return {@link Optional#empty()} if no {@link CouchbaseCacheConfiguration} set for the given cache name.
+ */
+ public Optional getCacheConfigurationFor(String cacheName) {
+ return Optional.ofNullable(this.initialCaches.get(cacheName));
+ }
+
+ /**
+ * Create new instance of {@link CouchbaseCacheManager} with configuration options applied.
+ *
+ * @return new instance of {@link CouchbaseCacheManager}.
+ */
+ public CouchbaseCacheManager build() {
+ CouchbaseCacheManager cm = new CouchbaseCacheManager(cacheWriter, defaultCacheConfiguration, initialCaches,
+ allowInFlightCacheCreation);
+ cm.setTransactionAware(enableTransactions);
+ return cm;
+ }
+
+ }
+
}
diff --git a/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java b/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java
index 8f4404e1..52d7346e 100644
--- a/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java
+++ b/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java
@@ -94,13 +94,13 @@ public abstract class AbstractCouchbaseConfiguration {
}
- @Bean
+ @Bean(name = BeanNames.COUCHBASE_TEMPLATE)
public CouchbaseTemplate couchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory,
MappingCouchbaseConverter mappingCouchbaseConverter) {
return new CouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter);
}
- @Bean
+ @Bean(name = BeanNames.REACTIVE_COUCHBASE_TEMPLATE)
public ReactiveCouchbaseTemplate reactiveCouchbaseTemplate(CouchbaseClientFactory couchbaseClientFactory,
MappingCouchbaseConverter mappingCouchbaseConverter) {
return new ReactiveCouchbaseTemplate(couchbaseClientFactory, mappingCouchbaseConverter);
@@ -195,7 +195,7 @@ public abstract class AbstractCouchbaseConfiguration {
public CouchbaseMappingContext couchbaseMappingContext() throws Exception {
CouchbaseMappingContext mappingContext = new CouchbaseMappingContext();
mappingContext.setInitialEntitySet(getInitialEntitySet());
- mappingContext.setSimpleTypeHolder(couchbaseCustomConversions().getSimpleTypeHolder());
+ mappingContext.setSimpleTypeHolder(customConversions().getSimpleTypeHolder());
mappingContext.setFieldNamingStrategy(fieldNamingStrategy());
return mappingContext;
}
@@ -207,8 +207,8 @@ public abstract class AbstractCouchbaseConfiguration {
*
* @return must not be {@literal null}.
*/
- @Bean
- public CustomConversions couchbaseCustomConversions() {
+ @Bean(name = BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
+ public CustomConversions customConversions() {
return new CouchbaseCustomConversions(Collections.emptyList());
}
diff --git a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java
index 71997f7e..d2ee2c0b 100644
--- a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java
+++ b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java
@@ -32,14 +32,12 @@ import org.springframework.data.couchbase.core.convert.translation.TranslationSe
*/
public class BeanNames {
- /**
- * The name for the default {@link CouchbaseOperations} bean. See
- * {@link AbstractCouchbaseConfiguration#couchbaseTemplate(CouchbaseClientFactory, MappingCouchbaseConverter)} )}
- * for java config, and the "<couchbase:template />"
- * element for xml config.
- */
public static final String COUCHBASE_TEMPLATE = "couchbaseTemplate";
+ public static final String REACTIVE_COUCHBASE_TEMPLATE = "reactiveCouchbaseTemplate";
+
+ public static final String COUCHBASE_CUSTOM_CONVERSIONS = "couchbaseCustomConversions";
+
/**
* The name for the bean that stores custom mapping between repositories and their backing couchbaseOperations.
*/