From 2f6874024755542dfb3827b9e75e4819e90a427a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Basl=C3=A9?= Date: Fri, 13 Nov 2015 16:24:41 +0100 Subject: [PATCH] DATACOUCH-161 - Improve multitemplate mapping configuration The configuration step made it look like a new mapping was necessary in overrides, whereas it is actually possible and clearer to mutate the base mapping. Added a convenience method to get the MappingContext from the repository mapping. --- .../wiring/RepositoryTemplateWiringTests.java | 4 ++-- src/main/asciidoc/repository.adoc | 10 +++++----- .../config/AbstractCouchbaseConfiguration.java | 17 ++++++++++++++++- .../config/RepositoryOperationsMapping.java | 16 ++++++++++++++++ .../support/CouchbaseRepositoryFactory.java | 3 +-- .../support/CouchbaseRepositoryFactoryBean.java | 2 +- 6 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/integration/java/org/springframework/data/couchbase/repository/wiring/RepositoryTemplateWiringTests.java b/src/integration/java/org/springframework/data/couchbase/repository/wiring/RepositoryTemplateWiringTests.java index 288443bc..a7723513 100644 --- a/src/integration/java/org/springframework/data/couchbase/repository/wiring/RepositoryTemplateWiringTests.java +++ b/src/integration/java/org/springframework/data/couchbase/repository/wiring/RepositoryTemplateWiringTests.java @@ -106,8 +106,8 @@ public class RepositoryTemplateWiringTests { } @Override - public RepositoryOperationsMapping repositoryOperationsMapping() throws Exception { - return new RepositoryOperationsMapping(templateC()) + public void configureRepositoryOperationsMapping(RepositoryOperationsMapping base) { + base.setDefault(templateC()) .map(BucketBRepository.class, templateB()) .mapEntity(Item.class, templateA()); } diff --git a/src/main/asciidoc/repository.adoc b/src/main/asciidoc/repository.adoc index 2039a4b6..2938dbe6 100644 --- a/src/main/asciidoc/repository.adoc +++ b/src/main/asciidoc/repository.adoc @@ -457,12 +457,12 @@ Provide the implementation and directly use `queryView` and `queryN1QL` methods The Java Config version allows you to define multiple `Bucket` and `CouchbaseTemplate`, but in order to have different repositories use different underlying buckets/templates, you need to follow these steps: - * in your `AbstractCouchbaseConfiguration` implementation, override the `repositoryOperationsMapping` bean method. - * have it return a new `RepositoryOperationsMapping` (or reuse the `super()` one) + * in your `AbstractCouchbaseConfiguration` implementation, override the `configureRepositoryOperationsMapping` method. + * mutate the provided `RepositoryOperationsMapping` as needed (it defaults to mapping everything to the default template). * configure the mapping by chaining calls to `map`, `mapEntity` and `setDefault`. ** `map` maps a specific repository interface to the `CouchbaseOperations` it should use ** `mapEntity` maps all unmapped repositories of a domain type / entity class to a common `CouchbaseOperations` - ** finally the value passed to the constructor or `setDefault` maps all remaining unmapped repositories to a default + ** `setDefault` maps all remaining unmapped repositories to a default `CouchaseOperations` (the default, using `couchbaseTemplate` bean unless modified). The idea is that the framework will look for an entry corresponding to the repository's interface when instantiating it. @@ -500,8 +500,8 @@ public class ConcreteCouchbaseConfig extends AbstractCouchbaseConfig { //... then finally make sure all repositories of Users will use it @Override - public RepositoryOperationsMapping repositoryOperationsMapping() throws Exception { - return super.repositoryOperationsMapping() //this is already using couchbaseTemplate as default + public void configureRepositoryOperationsMapping(RepositoryOperationsMapping baseMapping) { + baseMapping //this is already using couchbaseTemplate as default .mapEntity(User.class, userTemplate()); //every repository dealing with User will be backed by userTemplate() } } 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 1c40b16f..6214e033 100644 --- a/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java +++ b/src/main/java/org/springframework/data/couchbase/config/AbstractCouchbaseConfiguration.java @@ -161,12 +161,27 @@ public abstract class AbstractCouchbaseConfiguration { /** * Creates the {@link RepositoryOperationsMapping} bean which will be used by the framework to choose which * {@link CouchbaseOperations} should back which {@link CouchbaseRepository}. + * Override {@link #configureRepositoryOperationsMapping(RepositoryOperationsMapping)} in order to customize this. * * @throws Exception */ @Bean(name = BeanNames.REPO_OPERATIONS_MAPPING) public RepositoryOperationsMapping repositoryOperationsMapping() throws Exception { - return new RepositoryOperationsMapping(couchbaseTemplate()); + //create a base mapping that associates all repositories to the default template + RepositoryOperationsMapping baseMapping = new RepositoryOperationsMapping(couchbaseTemplate()); + //let the user tune it + configureRepositoryOperationsMapping(baseMapping); + return baseMapping; + } + + /** + * In order to customize the mapping between repositories/entity types to couchbase templates, + * use the provided mapping's api (eg. in order to have different buckets backing different repositories). + * + * @param mapping the default mapping (will associate all repositories to the default template). + */ + protected void configureRepositoryOperationsMapping(RepositoryOperationsMapping mapping) { + //NO_OP } /** diff --git a/src/main/java/org/springframework/data/couchbase/repository/config/RepositoryOperationsMapping.java b/src/main/java/org/springframework/data/couchbase/repository/config/RepositoryOperationsMapping.java index 86c34daa..b762b8b3 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/config/RepositoryOperationsMapping.java +++ b/src/main/java/org/springframework/data/couchbase/repository/config/RepositoryOperationsMapping.java @@ -20,6 +20,10 @@ import java.util.HashMap; import java.util.Map; import org.springframework.data.couchbase.core.CouchbaseOperations; +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentEntity; +import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProperty; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.util.Assert; /** * A utility class for configuration allowing to tell which {@link CouchbaseOperations} should be backing @@ -33,12 +37,14 @@ public class RepositoryOperationsMapping { private Map byRepository = new HashMap(); private Map byEntity = new HashMap(); + /** * Creates a new mapping, setting the default fallback to use by otherwise non mapped repositories. * * @param defaultOperations the default fallback couchbase operations. */ public RepositoryOperationsMapping(CouchbaseOperations defaultOperations) { + Assert.notNull(defaultOperations); this.defaultOperations = defaultOperations; } @@ -49,6 +55,7 @@ public class RepositoryOperationsMapping { * @return the mapping, for chaining. */ public RepositoryOperationsMapping setDefault(CouchbaseOperations aDefault) { + Assert.notNull(aDefault); this.defaultOperations = aDefault; return this; } @@ -85,6 +92,15 @@ public class RepositoryOperationsMapping { return defaultOperations; } + /** + * Get the {@link MappingContext} to use in repositories. It is extracted from the default {@link CouchbaseOperations}. + * + * @return the mapping context. + */ + public MappingContext, CouchbasePersistentProperty> getMappingContext() { + return defaultOperations.getConverter().getMappingContext(); + } + /** * Given a repository interface and its domain type, resolves which {@link CouchbaseOperations} it should be backed with. * diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java index c2cf976c..4cdc8be1 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactory.java @@ -91,7 +91,7 @@ public class CouchbaseRepositoryFactory extends RepositoryFactorySupport { this.couchbaseOperationsMapping = couchbaseOperationsMapping; this.indexManager = indexManager; - mappingContext = this.couchbaseOperationsMapping.getDefault().getConverter().getMappingContext(); + mappingContext = this.couchbaseOperationsMapping.getMappingContext(); viewPostProcessor = ViewPostProcessor.INSTANCE; addRepositoryProxyPostProcessor(viewPostProcessor); @@ -157,7 +157,6 @@ public class CouchbaseRepositoryFactory extends RepositoryFactorySupport { //for other repos, they might also need N1QL if they don't have only @View methods if (!needsN1ql) { - for (Method method : metadata.getQueryMethods()) { boolean hasN1ql = AnnotationUtils.findAnnotation(method, Query.class) != null; diff --git a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactoryBean.java b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactoryBean.java index 43fd3155..ec79e6ad 100644 --- a/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/couchbase/repository/support/CouchbaseRepositoryFactoryBean.java @@ -54,7 +54,7 @@ public class CouchbaseRepositoryFactoryBean, S, ID e public void setCouchbaseOperationsMapping(final RepositoryOperationsMapping mapping) { this.operationsMapping = mapping; - setMappingContext(operationsMapping.getDefault().getConverter().getMappingContext()); + setMappingContext(operationsMapping.getMappingContext()); } /**