Commit 80543250 authored by Andy Wilkinson's avatar Andy Wilkinson

Rework properties for enabling Spring Data repositories

Rather than using two properties to enable or disable reactive and
imperative repositories for a particular store, this commit introduces
a new repository type condition that's backed by a single
spring.data.<store>.repositories.type property. The type can be
auto (automatically enables whatever's available), imperative (enables
imperative repositories), none (enables nothing), or reactive (enables
reactive repositories). The default is auto.

Repositories do not have a reactive option (such as JPA) continue to
have a spring.data.<store>.repositories.enabled property that takes a
boolean value.

Closes gh-11134
parent 8b98db40
/*
* Copyright 2012-2017 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.boot.autoconfigure.data;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Conditional;
/**
* {@link Conditional} that only matches when a particular type of Spring Data repository
* has been enabled.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnRepositoryTypeCondition.class)
public @interface ConditionalOnRepositoryType {
/**
* The name of the store that backs the repositories.
* @return the store
*/
String store();
/**
* The required repository type.
* @return the required repository type
*/
RepositoryType type();
}
/*
* Copyright 2012-2017 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.boot.autoconfigure.data;
import java.util.Locale;
import java.util.Map;
import org.springframework.boot.autoconfigure.condition.ConditionMessage;
import org.springframework.boot.autoconfigure.condition.ConditionOutcome;
import org.springframework.boot.autoconfigure.condition.SpringBootCondition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
/**
* {@link SpringBootCondition} for controlling what type of Spring Data repositories are
* auto-configured.
*
* @author Andy Wilkinson
*/
class OnRepositoryTypeCondition extends SpringBootCondition {
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
Map<String, Object> attributes = metadata.getAnnotationAttributes(
ConditionalOnRepositoryType.class.getName(), true);
RepositoryType configuredType = getTypeProperty(context.getEnvironment(),
(String) attributes.get("store"));
RepositoryType requiredType = (RepositoryType) attributes.get("type");
ConditionMessage.Builder message = ConditionMessage
.forCondition(ConditionalOnRepositoryType.class);
if (configuredType == requiredType || configuredType == RepositoryType.AUTO) {
return ConditionOutcome.match(message.because("configured type of '"
+ configuredType.name() + "' matched required type"));
}
return ConditionOutcome
.noMatch(message.because("configured type (" + configuredType.name()
+ ") did not match required type (" + requiredType.name() + ")"));
}
private RepositoryType getTypeProperty(Environment environment, String store) {
return RepositoryType.valueOf(environment
.getProperty(String.format("spring.data.%s.repositories.type", store),
"auto")
.toUpperCase(Locale.ENGLISH));
}
}
/*
* Copyright 2012-2017 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.boot.autoconfigure.data;
/**
* Type of Spring Data repositories to enable.
*
* @author Andy Wilkinson
* @since 2.0.0
*/
public enum RepositoryType {
/**
* Enables all repository types automatically based on their availability.
*/
AUTO,
/**
* Enables imperative repositories.
*/
IMPERATIVE,
/**
* Enables no repositories.
*/
NONE,
/**
* Enables reactive repositories.
*/
REACTIVE;
}
...@@ -20,7 +20,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; ...@@ -20,7 +20,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.cassandra.ReactiveSession; import org.springframework.data.cassandra.ReactiveSession;
...@@ -39,7 +40,7 @@ import org.springframework.data.cassandra.repository.support.ReactiveCassandraRe ...@@ -39,7 +40,7 @@ import org.springframework.data.cassandra.repository.support.ReactiveCassandraRe
*/ */
@Configuration @Configuration
@ConditionalOnClass({ ReactiveSession.class, ReactiveCassandraRepository.class }) @ConditionalOnClass({ ReactiveSession.class, ReactiveCassandraRepository.class })
@ConditionalOnProperty(prefix = "spring.data.cassandra.reactiverepositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "cassandra", type = RepositoryType.REACTIVE)
@ConditionalOnMissingBean(ReactiveCassandraRepositoryFactoryBean.class) @ConditionalOnMissingBean(ReactiveCassandraRepositoryFactoryBean.class)
@Import(CassandraReactiveRepositoriesAutoConfigureRegistrar.class) @Import(CassandraReactiveRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(CassandraReactiveDataAutoConfiguration.class) @AutoConfigureAfter(CassandraReactiveDataAutoConfiguration.class)
......
...@@ -21,7 +21,8 @@ import com.datastax.driver.core.Session; ...@@ -21,7 +21,8 @@ import com.datastax.driver.core.Session;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.cassandra.repository.CassandraRepository; import org.springframework.data.cassandra.repository.CassandraRepository;
...@@ -38,7 +39,7 @@ import org.springframework.data.cassandra.repository.support.CassandraRepository ...@@ -38,7 +39,7 @@ import org.springframework.data.cassandra.repository.support.CassandraRepository
*/ */
@Configuration @Configuration
@ConditionalOnClass({ Session.class, CassandraRepository.class }) @ConditionalOnClass({ Session.class, CassandraRepository.class })
@ConditionalOnProperty(prefix = "spring.data.cassandra.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "cassandra", type = RepositoryType.IMPERATIVE)
@ConditionalOnMissingBean(CassandraRepositoryFactoryBean.class) @ConditionalOnMissingBean(CassandraRepositoryFactoryBean.class)
@Import(CassandraRepositoriesAutoConfigureRegistrar.class) @Import(CassandraRepositoriesAutoConfigureRegistrar.class)
public class CassandraRepositoriesAutoConfiguration { public class CassandraRepositoriesAutoConfiguration {
......
...@@ -24,7 +24,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; ...@@ -24,7 +24,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository; import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository;
...@@ -40,7 +41,7 @@ import org.springframework.data.couchbase.repository.support.ReactiveCouchbaseRe ...@@ -40,7 +41,7 @@ import org.springframework.data.couchbase.repository.support.ReactiveCouchbaseRe
*/ */
@Configuration @Configuration
@ConditionalOnClass({ Bucket.class, ReactiveCouchbaseRepository.class, Flux.class }) @ConditionalOnClass({ Bucket.class, ReactiveCouchbaseRepository.class, Flux.class })
@ConditionalOnProperty(prefix = "spring.data.couchbase.reactiverepositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "couchbase", type = RepositoryType.REACTIVE)
@ConditionalOnBean(ReactiveRepositoryOperationsMapping.class) @ConditionalOnBean(ReactiveRepositoryOperationsMapping.class)
@ConditionalOnMissingBean(ReactiveCouchbaseRepositoryFactoryBean.class) @ConditionalOnMissingBean(ReactiveCouchbaseRepositoryFactoryBean.class)
@Import(CouchbaseReactiveRepositoriesRegistrar.class) @Import(CouchbaseReactiveRepositoriesRegistrar.class)
......
...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; ...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.couchbase.repository.CouchbaseRepository; import org.springframework.data.couchbase.repository.CouchbaseRepository;
...@@ -40,7 +41,7 @@ import org.springframework.data.couchbase.repository.support.CouchbaseRepository ...@@ -40,7 +41,7 @@ import org.springframework.data.couchbase.repository.support.CouchbaseRepository
@Configuration @Configuration
@ConditionalOnClass({ Bucket.class, CouchbaseRepository.class }) @ConditionalOnClass({ Bucket.class, CouchbaseRepository.class })
@ConditionalOnBean(RepositoryOperationsMapping.class) @ConditionalOnBean(RepositoryOperationsMapping.class)
@ConditionalOnProperty(prefix = "spring.data.couchbase.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "couchbase", type = RepositoryType.IMPERATIVE)
@ConditionalOnMissingBean(CouchbaseRepositoryFactoryBean.class) @ConditionalOnMissingBean(CouchbaseRepositoryFactoryBean.class)
@Import(CouchbaseRepositoriesRegistrar.class) @Import(CouchbaseRepositoriesRegistrar.class)
public class CouchbaseRepositoriesAutoConfiguration { public class CouchbaseRepositoriesAutoConfiguration {
......
...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; ...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
...@@ -51,7 +52,7 @@ import org.springframework.data.mongodb.repository.support.ReactiveMongoReposito ...@@ -51,7 +52,7 @@ import org.springframework.data.mongodb.repository.support.ReactiveMongoReposito
@ConditionalOnClass({ MongoClient.class, ReactiveMongoRepository.class }) @ConditionalOnClass({ MongoClient.class, ReactiveMongoRepository.class })
@ConditionalOnMissingBean({ ReactiveMongoRepositoryFactoryBean.class, @ConditionalOnMissingBean({ ReactiveMongoRepositoryFactoryBean.class,
ReactiveMongoRepositoryConfigurationExtension.class }) ReactiveMongoRepositoryConfigurationExtension.class })
@ConditionalOnProperty(prefix = "spring.data.mongodb.reactiverepositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "mongodb", type = RepositoryType.REACTIVE)
@Import(MongoReactiveRepositoriesAutoConfigureRegistrar.class) @Import(MongoReactiveRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(MongoReactiveDataAutoConfiguration.class) @AutoConfigureAfter(MongoReactiveDataAutoConfiguration.class)
public class MongoReactiveRepositoriesAutoConfiguration { public class MongoReactiveRepositoriesAutoConfiguration {
......
...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter; ...@@ -22,7 +22,8 @@ import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.data.ConditionalOnRepositoryType;
import org.springframework.boot.autoconfigure.data.RepositoryType;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.MongoRepository;
...@@ -55,7 +56,7 @@ import org.springframework.data.mongodb.repository.support.MongoRepositoryFactor ...@@ -55,7 +56,7 @@ import org.springframework.data.mongodb.repository.support.MongoRepositoryFactor
@ConditionalOnClass({ Mongo.class, MongoRepository.class }) @ConditionalOnClass({ Mongo.class, MongoRepository.class })
@ConditionalOnMissingBean({ MongoRepositoryFactoryBean.class, @ConditionalOnMissingBean({ MongoRepositoryFactoryBean.class,
MongoRepositoryConfigurationExtension.class }) MongoRepositoryConfigurationExtension.class })
@ConditionalOnProperty(prefix = "spring.data.mongodb.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) @ConditionalOnRepositoryType(store = "mongodb", type = RepositoryType.IMPERATIVE)
@Import(MongoRepositoriesAutoConfigureRegistrar.class) @Import(MongoRepositoriesAutoConfigureRegistrar.class)
@AutoConfigureAfter(MongoDataAutoConfiguration.class) @AutoConfigureAfter(MongoDataAutoConfiguration.class)
public class MongoRepositoriesAutoConfiguration { public class MongoRepositoriesAutoConfiguration {
......
...@@ -95,32 +95,40 @@ ...@@ -95,32 +95,40 @@
"defaultValue": "none" "defaultValue": "none"
}, },
{ {
"name": "spring.data.cassandra.reactiverepositories.enabled", "name": "spring.data.cassandra.repositories.type",
"type": "java.lang.Boolean", "type": "org.springframework.boot.autoconfigure.data.RepositoryType",
"description": "Whether to enable Cassandra reactive repositories.", "description": "Type of Cassandra repositories to enable.",
"defaultValue": true "defaultValue": "auto"
}, },
{ {
"name": "spring.data.cassandra.repositories.enabled", "name": "spring.data.cassandra.repositories.enabled",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",
"description": "Whether to enable Cassandra repositories.", "description": "Whether to enable Cassandra repositories.",
"defaultValue": true "defaultValue": true,
"deprecation": {
"replacement": "spring.data.cassandra.repositories.type",
"level": "error"
}
}, },
{ {
"name": "spring.data.couchbase.consistency", "name": "spring.data.couchbase.consistency",
"defaultValue": "read-your-own-writes" "defaultValue": "read-your-own-writes"
}, },
{ {
"name": "spring.data.couchbase.reactiverepositories.enabled", "name": "spring.data.couchbase.repositories.type",
"type": "java.lang.Boolean", "type": "org.springframework.boot.autoconfigure.data.RepositoryType",
"description": "Whether to enable Couchbase reactive repositories.", "description": "Type of Couchbase repositories to enable.",
"defaultValue": true "defaultValue": "auto"
}, },
{ {
"name": "spring.data.couchbase.repositories.enabled", "name": "spring.data.couchbase.repositories.enabled",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",
"description": "Whether to enable Couchbase repositories.", "description": "Whether to enable Couchbase repositories.",
"defaultValue": true "defaultValue": true,
"deprecation": {
"replacement": "spring.data.couchbase.repositories.type",
"level": "error"
}
}, },
{ {
"name": "spring.data.elasticsearch.repositories.enabled", "name": "spring.data.elasticsearch.repositories.enabled",
...@@ -141,16 +149,20 @@ ...@@ -141,16 +149,20 @@
"defaultValue": true "defaultValue": true
}, },
{ {
"name": "spring.data.mongodb.reactiverepositories.enabled", "name": "spring.data.mongodb.repositories.type",
"type": "java.lang.Boolean", "type": "org.springframework.boot.autoconfigure.data.RepositoryType",
"description": "Whether to enable Mongo reactive repositories.", "description": "Type of Mongo repositories to enable.",
"defaultValue": true "defaultValue": "auto"
}, },
{ {
"name": "spring.data.mongodb.repositories.enabled", "name": "spring.data.mongodb.repositories.enabled",
"type": "java.lang.Boolean", "type": "java.lang.Boolean",
"description": "Whether to enable Mongo repositories.", "description": "Whether to enable Mongo repositories.",
"defaultValue": true "defaultValue": true,
"deprecation": {
"replacement": "spring.data.mongodb.repositories.type",
"level": "error"
}
}, },
{ {
"name": "spring.data.neo4j.open-in-view", "name": "spring.data.neo4j.open-in-view",
......
/*
* Copyright 2012-2017 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.boot.autoconfigure.data;
import org.junit.Test;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ConditionalOnRepositoryType}.
*
* @author Andy Wilkinson
*/
public class ConditionalOnRepositoryTypeTests {
private final ApplicationContextRunner runner = new ApplicationContextRunner();
@Test
public void imperativeRepositoryMatchesWithNoConfiguredType() {
this.runner.withUserConfiguration(ImperativeRepository.class)
.run((context) -> assertThat(context)
.hasSingleBean(ImperativeRepository.class));
}
@Test
public void reactiveRepositoryMatchesWithNoConfiguredType() {
this.runner.withUserConfiguration(ReactiveRepository.class).run(
(context) -> assertThat(context).hasSingleBean(ReactiveRepository.class));
}
@Test
public void imperativeRepositoryMatchesWithAutoConfiguredType() {
this.runner.withUserConfiguration(ImperativeRepository.class)
.withPropertyValues("spring.data.test.repositories.type:auto")
.run((context) -> assertThat(context)
.hasSingleBean(ImperativeRepository.class));
}
@Test
public void reactiveRepositoryMatchesWithAutoConfiguredType() {
this.runner.withUserConfiguration(ReactiveRepository.class)
.withPropertyValues("spring.data.test.repositories.type:auto")
.run((context) -> assertThat(context)
.hasSingleBean(ReactiveRepository.class));
}
@Test
public void imperativeRepositoryMatchesWithImperativeConfiguredType() {
this.runner.withUserConfiguration(ImperativeRepository.class)
.withPropertyValues("spring.data.test.repositories.type:imperative")
.run((context) -> assertThat(context)
.hasSingleBean(ImperativeRepository.class));
}
@Test
public void reactiveRepositoryMatchesWithReactiveConfiguredType() {
this.runner.withUserConfiguration(ReactiveRepository.class)
.withPropertyValues("spring.data.test.repositories.type:reactive")
.run((context) -> assertThat(context)
.hasSingleBean(ReactiveRepository.class));
}
@Test
public void imperativeRepositoryDoesNotMatchWithReactiveConfiguredType() {
this.runner.withUserConfiguration(ImperativeRepository.class)
.withPropertyValues("spring.data.test.repositories.type:reactive")
.run((context) -> assertThat(context)
.doesNotHaveBean(ImperativeRepository.class));
}
@Test
public void reactiveRepositoryDoesNotMatchWithImperativeConfiguredType() {
this.runner.withUserConfiguration(ReactiveRepository.class)
.withPropertyValues("spring.data.test.repositories.type:imperative")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveRepository.class));
}
@Test
public void imperativeRepositoryDoesNotMatchWithNoneConfiguredType() {
this.runner.withUserConfiguration(ImperativeRepository.class)
.withPropertyValues("spring.data.test.repositories.type:none")
.run((context) -> assertThat(context)
.doesNotHaveBean(ImperativeRepository.class));
}
@Test
public void reactiveRepositoryDoesNotMatchWithNoneConfiguredType() {
this.runner.withUserConfiguration(ReactiveRepository.class)
.withPropertyValues("spring.data.test.repositories.type:none")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveRepository.class));
}
@Test
public void failsFastWhenConfiguredTypeIsUnknown() {
this.runner.withUserConfiguration(ReactiveRepository.class)
.withPropertyValues("spring.data.test.repositories.type:abcde")
.run((context) -> assertThat(context).hasFailed());
}
@Configuration
@ConditionalOnRepositoryType(store = "test", type = RepositoryType.IMPERATIVE)
protected static class ImperativeRepository {
}
@Configuration
@ConditionalOnRepositoryType(store = "test", type = RepositoryType.REACTIVE)
protected static class ReactiveRepository {
}
}
...@@ -20,9 +20,9 @@ import java.util.Set; ...@@ -20,9 +20,9 @@ import java.util.Set;
import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session; import com.datastax.driver.core.Session;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
...@@ -30,7 +30,8 @@ import org.springframework.boot.autoconfigure.data.alt.cassandra.ReactiveCityCas ...@@ -30,7 +30,8 @@ import org.springframework.boot.autoconfigure.data.alt.cassandra.ReactiveCityCas
import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.autoconfigure.data.cassandra.city.City;
import org.springframework.boot.autoconfigure.data.cassandra.city.ReactiveCityRepository; import org.springframework.boot.autoconfigure.data.cassandra.city.ReactiveCityRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.ComponentScan.Filter;
...@@ -50,62 +51,72 @@ import static org.mockito.Mockito.mock; ...@@ -50,62 +51,72 @@ import static org.mockito.Mockito.mock;
* @author Eddú Meléndez * @author Eddú Meléndez
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Mark Paluch * @author Mark Paluch
* @author Andy Wilkinson
*/ */
public class CassandraReactiveRepositoriesAutoConfigurationTests { public class CassandraReactiveRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private final ApplicationContextRunner runner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class,
@After CassandraRepositoriesAutoConfiguration.class,
public void close() { CassandraDataAutoConfiguration.class,
if (this.context != null) { CassandraReactiveDataAutoConfiguration.class,
this.context.close(); CassandraReactiveRepositoriesAutoConfiguration.class,
} PropertyPlaceholderAutoConfiguration.class));
}
@Test @Test
public void testDefaultRepositoryConfiguration() { public void testDefaultRepositoryConfiguration() {
load(TestConfiguration.class); this.runner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(this.context.getBean(ReactiveCityRepository.class)).isNotNull(); assertThat(context).hasSingleBean(ReactiveCityRepository.class);
assertThat(this.context.getBean(Cluster.class)).isNotNull(); assertThat(context).hasSingleBean(Cluster.class);
assertThat(getInitialEntitySet()).hasSize(1); assertThat(getInitialEntitySet(context)).hasSize(1);
});
} }
@Test @Test
public void testNoRepositoryConfiguration() { public void testNoRepositoryConfiguration() {
load(TestExcludeConfiguration.class, EmptyConfiguration.class); this.runner.withUserConfiguration(TestExcludeConfiguration.class,
assertThat(this.context.getBean(Cluster.class)).isNotNull(); EmptyConfiguration.class).run((context) -> {
assertThat(getInitialEntitySet()).hasSize(1).containsOnly(City.class); assertThat(context).hasSingleBean(Cluster.class);
assertThat(getInitialEntitySet(context)).hasSize(1)
.containsOnly(City.class);
});
} }
@Test @Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
load(TestExcludeConfiguration.class, CustomizedConfiguration.class); this.runner.withUserConfiguration(TestExcludeConfiguration.class,
assertThat(this.context.getBean(ReactiveCityCassandraRepository.class)) CustomizedConfiguration.class).run((context) -> {
.isNotNull(); assertThat(context)
assertThat(getInitialEntitySet()).hasSize(1).containsOnly(City.class); .hasSingleBean(ReactiveCityCassandraRepository.class);
assertThat(getInitialEntitySet(context)).hasSize(1)
.containsOnly(City.class);
});
}
@Test
public void enablingImperativeRepositoriesDisablesReactiveRepositories() {
this.runner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.cassandra.repositories.type=imperative")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveCityRepository.class));
}
@Test
public void enablingNoRepositoriesDisablesReactiveRepositories() {
this.runner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.cassandra.repositories.type=none")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveCityRepository.class));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Set<Class<?>> getInitialEntitySet() { private Set<Class<?>> getInitialEntitySet(ApplicationContext context) {
CassandraMappingContext mappingContext = this.context CassandraMappingContext mappingContext = context
.getBean(CassandraMappingContext.class); .getBean(CassandraMappingContext.class);
return (Set<Class<?>>) ReflectionTestUtils.getField(mappingContext, return (Set<Class<?>>) ReflectionTestUtils.getField(mappingContext,
"initialEntitySet"); "initialEntitySet");
} }
private void load(Class<?>... configurations) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(configurations);
ctx.register(CassandraAutoConfiguration.class,
CassandraRepositoriesAutoConfiguration.class,
CassandraDataAutoConfiguration.class,
CassandraReactiveDataAutoConfiguration.class,
CassandraReactiveRepositoriesAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
ctx.refresh();
this.context = ctx;
}
@Configuration @Configuration
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
static class TestConfiguration { static class TestConfiguration {
......
...@@ -20,10 +20,9 @@ import java.util.Set; ...@@ -20,10 +20,9 @@ import java.util.Set;
import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session; import com.datastax.driver.core.Session;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
...@@ -31,7 +30,8 @@ import org.springframework.boot.autoconfigure.data.alt.cassandra.CityCassandraRe ...@@ -31,7 +30,8 @@ import org.springframework.boot.autoconfigure.data.alt.cassandra.CityCassandraRe
import org.springframework.boot.autoconfigure.data.cassandra.city.City; import org.springframework.boot.autoconfigure.data.cassandra.city.City;
import org.springframework.boot.autoconfigure.data.cassandra.city.CityRepository; import org.springframework.boot.autoconfigure.data.cassandra.city.CityRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -52,57 +52,65 @@ import static org.mockito.Mockito.mock; ...@@ -52,57 +52,65 @@ import static org.mockito.Mockito.mock;
*/ */
public class CassandraRepositoriesAutoConfigurationTests { public class CassandraRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private final ApplicationContextRunner runner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class,
CassandraRepositoriesAutoConfiguration.class,
CassandraDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class));
@Before @Test
public void setUp() { public void testDefaultRepositoryConfiguration() {
this.context = new AnnotationConfigApplicationContext(); this.runner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(CityRepository.class);
assertThat(context).hasSingleBean(Cluster.class);
assertThat(getInitialEntitySet(context)).hasSize(1);
});
} }
@After @Test
public void close() { public void testNoRepositoryConfiguration() {
this.context.close(); this.runner.withUserConfiguration(TestExcludeConfiguration.class,
EmptyConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Cluster.class);
assertThat(getInitialEntitySet(context)).hasSize(1)
.containsOnly(City.class);
});
} }
@Test @Test
public void testDefaultRepositoryConfiguration() { public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
addConfigurations(TestConfiguration.class); this.runner.withUserConfiguration(TestExcludeConfiguration.class,
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); CustomizedConfiguration.class).run((context) -> {
assertThat(this.context.getBean(Cluster.class)).isNotNull(); assertThat(context).hasSingleBean(CityCassandraRepository.class);
assertThat(getInitialEntitySet()).hasSize(1); assertThat(getInitialEntitySet(context)).hasSize(1)
.containsOnly(City.class);
});
} }
@Test @Test
public void testNoRepositoryConfiguration() { public void enablingReactiveRepositoriesDisablesImperativeRepositories() {
addConfigurations(TestExcludeConfiguration.class, EmptyConfiguration.class); this.runner.withUserConfiguration(TestConfiguration.class)
assertThat(this.context.getBean(Cluster.class)).isNotNull(); .withPropertyValues("spring.data.cassandra.repositories.type=reactive")
assertThat(getInitialEntitySet()).hasSize(1).containsOnly(City.class); .run((context) -> assertThat(context)
.doesNotHaveBean(CityCassandraRepository.class));
} }
@Test @Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { public void enablingNoRepositoriesDisablesReactiveRepositories() {
addConfigurations(TestExcludeConfiguration.class, CustomizedConfiguration.class); this.runner.withUserConfiguration(TestConfiguration.class)
assertThat(this.context.getBean(CityCassandraRepository.class)).isNotNull(); .withPropertyValues("spring.data.cassandra.repositories.type=none")
assertThat(getInitialEntitySet()).hasSize(1).containsOnly(City.class); .run((context) -> assertThat(context)
.doesNotHaveBean(CityCassandraRepository.class));
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Set<Class<?>> getInitialEntitySet() { private Set<Class<?>> getInitialEntitySet(AssertableApplicationContext context) {
CassandraMappingContext mappingContext = this.context CassandraMappingContext mappingContext = context
.getBean(CassandraMappingContext.class); .getBean(CassandraMappingContext.class);
return (Set<Class<?>>) ReflectionTestUtils.getField(mappingContext, return (Set<Class<?>>) ReflectionTestUtils.getField(mappingContext,
"initialEntitySet"); "initialEntitySet");
} }
private void addConfigurations(Class<?>... configurations) {
this.context.register(configurations);
this.context.register(CassandraAutoConfiguration.class,
CassandraRepositoriesAutoConfiguration.class,
CassandraDataAutoConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
}
@Configuration @Configuration
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
static class TestConfiguration { static class TestConfiguration {
......
...@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
public class CouchbaseReactiveAndBlockingRepositoriesAutoConfigurationTests { public class CouchbaseReactiveAndImperativeRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private AnnotationConfigApplicationContext context;
...@@ -55,12 +55,12 @@ public class CouchbaseReactiveAndBlockingRepositoriesAutoConfigurationTests { ...@@ -55,12 +55,12 @@ public class CouchbaseReactiveAndBlockingRepositoriesAutoConfigurationTests {
} }
@Test @Test
public void shouldCreateInstancesForReactiveAndBlockingRepositories() public void shouldCreateInstancesForReactiveAndImperativeRepositories()
throws Exception { throws Exception {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues.of("spring.datasource.initialization-mode:never") TestPropertyValues.of("spring.datasource.initialization-mode:never")
.applyTo(this.context); .applyTo(this.context);
this.context.register(BlockingAndReactiveConfiguration.class, this.context.register(ImperativeAndReactiveConfiguration.class,
BaseConfiguration.class); BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); assertThat(this.context.getBean(CityRepository.class)).isNotNull();
...@@ -71,7 +71,7 @@ public class CouchbaseReactiveAndBlockingRepositoriesAutoConfigurationTests { ...@@ -71,7 +71,7 @@ public class CouchbaseReactiveAndBlockingRepositoriesAutoConfigurationTests {
@TestAutoConfigurationPackage(CouchbaseAutoConfigurationTests.class) @TestAutoConfigurationPackage(CouchbaseAutoConfigurationTests.class)
@EnableCouchbaseRepositories(basePackageClasses = CityRepository.class) @EnableCouchbaseRepositories(basePackageClasses = CityRepository.class)
@EnableReactiveCouchbaseRepositories(basePackageClasses = ReactiveCityRepository.class) @EnableReactiveCouchbaseRepositories(basePackageClasses = ReactiveCityRepository.class)
protected static class BlockingAndReactiveConfiguration { protected static class ImperativeAndReactiveConfiguration {
} }
......
...@@ -65,10 +65,15 @@ public class CouchbaseReactiveRepositoriesAutoConfigurationTests { ...@@ -65,10 +65,15 @@ public class CouchbaseReactiveRepositoriesAutoConfigurationTests {
} }
@Test @Test
public void disableReactiveRepository() { public void imperativeRepositories() {
load(DefaultConfiguration.class, load(DefaultConfiguration.class,
"spring.data.couchbase.reactiverepositories.enabled=false", "spring.data.couchbase.repositories.type=imperative");
"spring.data.couchbase.repositories.enabled=false"); assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0);
}
@Test
public void disabledRepositories() {
load(DefaultConfiguration.class, "spring.data.couchbase.repositories.type=none");
assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0); assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0);
} }
......
...@@ -63,9 +63,15 @@ public class CouchbaseRepositoriesAutoConfigurationTests { ...@@ -63,9 +63,15 @@ public class CouchbaseRepositoriesAutoConfigurationTests {
} }
@Test @Test
public void disableRepository() { public void reactiveRepositories() {
load(DefaultConfiguration.class, load(DefaultConfiguration.class,
"spring.data.couchbase.repositories.enabled=false"); "spring.data.couchbase.repositories.type=reactive");
assertThat(this.context.getBeansOfType(CityRepository.class)).hasSize(0);
}
@Test
public void disabledRepositories() {
load(DefaultConfiguration.class, "spring.data.couchbase.repositories.type=none");
assertThat(this.context.getBeansOfType(CityRepository.class)).hasSize(0); assertThat(this.context.getBeansOfType(CityRepository.class)).hasSize(0);
} }
......
...@@ -106,7 +106,7 @@ public class MixedMongoRepositoriesAutoConfigurationTests { ...@@ -106,7 +106,7 @@ public class MixedMongoRepositoriesAutoConfigurationTests {
this.context = new AnnotationConfigApplicationContext(); this.context = new AnnotationConfigApplicationContext();
TestPropertyValues TestPropertyValues
.of("spring.datasource.initialization-mode:never", .of("spring.datasource.initialization-mode:never",
"spring.data.mongodb.repositories.enabled:false") "spring.data.mongodb.repositories.type:none")
.applyTo(this.context); .applyTo(this.context);
this.context.register(OverlapConfiguration.class, BaseConfiguration.class); this.context.register(OverlapConfiguration.class, BaseConfiguration.class);
this.context.refresh(); this.context.refresh();
......
...@@ -19,10 +19,9 @@ package org.springframework.boot.autoconfigure.data.mongo; ...@@ -19,10 +19,9 @@ package org.springframework.boot.autoconfigure.data.mongo;
import java.util.Set; import java.util.Set;
import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClient;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.alt.mongo.CityMongoDbRepository; import org.springframework.boot.autoconfigure.data.alt.mongo.CityMongoDbRepository;
...@@ -32,7 +31,7 @@ import org.springframework.boot.autoconfigure.data.mongo.city.City; ...@@ -32,7 +31,7 @@ import org.springframework.boot.autoconfigure.data.mongo.city.City;
import org.springframework.boot.autoconfigure.data.mongo.city.ReactiveCityRepository; import org.springframework.boot.autoconfigure.data.mongo.city.ReactiveCityRepository;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
...@@ -45,61 +44,67 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -45,61 +44,67 @@ import static org.assertj.core.api.Assertions.assertThat;
* Tests for {@link MongoReactiveRepositoriesAutoConfiguration}. * Tests for {@link MongoReactiveRepositoriesAutoConfiguration}.
* *
* @author Mark Paluch * @author Mark Paluch
* @author Andy Wilkinson
*/ */
public class MongoReactiveRepositoriesAutoConfigurationTests { public class MongoReactiveRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private final ApplicationContextRunner runner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class,
@After MongoDataAutoConfiguration.class,
public void close() { MongoReactiveAutoConfiguration.class,
if (this.context != null) { MongoReactiveDataAutoConfiguration.class,
this.context.close(); MongoReactiveRepositoriesAutoConfiguration.class,
} PropertyPlaceholderAutoConfiguration.class));
}
@Test @Test
public void testDefaultRepositoryConfiguration() throws Exception { public void testDefaultRepositoryConfiguration() throws Exception {
prepareApplicationContext(TestConfiguration.class); this.runner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(this.context.getBean(ReactiveCityRepository.class)).isNotNull(); assertThat(context).hasSingleBean(ReactiveCityRepository.class);
MongoClient client = this.context.getBean(MongoClient.class); MongoClient client = context.getBean(MongoClient.class);
assertThat(client).isInstanceOf(MongoClient.class); assertThat(client).isInstanceOf(MongoClient.class);
MongoMappingContext mappingContext = this.context MongoMappingContext mappingContext = context
.getBean(MongoMappingContext.class); .getBean(MongoMappingContext.class);
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils
.getField(mappingContext, "initialEntitySet"); .getField(mappingContext, "initialEntitySet");
assertThat(entities).hasSize(1); assertThat(entities).hasSize(1);
});
} }
@Test @Test
public void testNoRepositoryConfiguration() throws Exception { public void testNoRepositoryConfiguration() throws Exception {
prepareApplicationContext(EmptyConfiguration.class); this.runner.withUserConfiguration(EmptyConfiguration.class)
MongoClient client = this.context.getBean(MongoClient.class); .run((context) -> assertThat(context).hasSingleBean(MongoClient.class));
assertThat(client).isInstanceOf(MongoClient.class);
} }
@Test @Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
prepareApplicationContext(CustomizedConfiguration.class); this.runner.withUserConfiguration(CustomizedConfiguration.class)
assertThat(this.context.getBeansOfType(ReactiveCityMongoDbRepository.class)) .run((context) -> assertThat(context)
.isEmpty(); .doesNotHaveBean(ReactiveCityMongoDbRepository.class));
} }
@Test(expected = NoSuchBeanDefinitionException.class) @Test
public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() { public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
prepareApplicationContext(SortOfInvalidCustomConfiguration.class); this.runner.withUserConfiguration(SortOfInvalidCustomConfiguration.class)
this.context.getBean(ReactiveCityRepository.class); .run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveCityRepository.class));
} }
private void prepareApplicationContext(Class<?>... configurationClasses) { @Test
this.context = new AnnotationConfigApplicationContext(); public void enablingImperativeRepositoriesDisablesReactiveRepositories() {
this.context.register(configurationClasses); this.runner.withUserConfiguration(TestConfiguration.class)
this.context.register(MongoAutoConfiguration.class, .withPropertyValues("spring.data.mongodb.repositories.type=imperative")
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class, .run((context) -> assertThat(context)
MongoReactiveDataAutoConfiguration.class, .doesNotHaveBean(ReactiveCityRepository.class));
MongoReactiveRepositoriesAutoConfiguration.class, }
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh(); @Test
public void enablingNoRepositoriesDisablesReactiveRepositories() {
this.runner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=none")
.run((context) -> assertThat(context)
.doesNotHaveBean(ReactiveCityRepository.class));
} }
@Configuration @Configuration
......
...@@ -20,10 +20,9 @@ import java.util.Set; ...@@ -20,10 +20,9 @@ import java.util.Set;
import com.mongodb.Mongo; import com.mongodb.Mongo;
import com.mongodb.MongoClient; import com.mongodb.MongoClient;
import org.junit.After;
import org.junit.Test; import org.junit.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.data.alt.mongo.CityMongoDbRepository; import org.springframework.boot.autoconfigure.data.alt.mongo.CityMongoDbRepository;
...@@ -31,7 +30,7 @@ import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; ...@@ -31,7 +30,7 @@ import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.autoconfigure.data.mongo.city.City; import org.springframework.boot.autoconfigure.data.mongo.city.City;
import org.springframework.boot.autoconfigure.data.mongo.city.CityRepository; import org.springframework.boot.autoconfigure.data.mongo.city.CityRepository;
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration; import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.MongoMappingContext;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
...@@ -47,58 +46,62 @@ import static org.assertj.core.api.Assertions.assertThat; ...@@ -47,58 +46,62 @@ import static org.assertj.core.api.Assertions.assertThat;
*/ */
public class MongoRepositoriesAutoConfigurationTests { public class MongoRepositoriesAutoConfigurationTests {
private AnnotationConfigApplicationContext context; private final ApplicationContextRunner runner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class,
@After MongoDataAutoConfiguration.class,
public void close() { MongoRepositoriesAutoConfiguration.class,
this.context.close(); PropertyPlaceholderAutoConfiguration.class));
}
@Test @Test
public void testDefaultRepositoryConfiguration() throws Exception { public void testDefaultRepositoryConfiguration() throws Exception {
prepareApplicationContext(TestConfiguration.class); this.runner.withUserConfiguration(TestConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(CityRepository.class);
assertThat(this.context.getBean(CityRepository.class)).isNotNull(); Mongo mongo = context.getBean(Mongo.class);
Mongo mongo = this.context.getBean(Mongo.class); assertThat(mongo).isInstanceOf(MongoClient.class);
assertThat(mongo).isInstanceOf(MongoClient.class); MongoMappingContext mappingContext = context
MongoMappingContext mappingContext = this.context .getBean(MongoMappingContext.class);
.getBean(MongoMappingContext.class); @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils
Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils .getField(mappingContext, "initialEntitySet");
.getField(mappingContext, "initialEntitySet"); assertThat(entities).hasSize(1);
assertThat(entities).hasSize(1); });
} }
@Test @Test
public void testNoRepositoryConfiguration() throws Exception { public void testNoRepositoryConfiguration() throws Exception {
prepareApplicationContext(EmptyConfiguration.class); this.runner.withUserConfiguration(EmptyConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(Mongo.class);
Mongo mongo = this.context.getBean(Mongo.class); assertThat(context.getBean(Mongo.class)).isInstanceOf(MongoClient.class);
assertThat(mongo).isInstanceOf(MongoClient.class); });
} }
@Test @Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
prepareApplicationContext(CustomizedConfiguration.class); this.runner.withUserConfiguration(CustomizedConfiguration.class)
.run((context) -> assertThat(context)
assertThat(this.context.getBean(CityMongoDbRepository.class)).isNotNull(); .hasSingleBean(CityMongoDbRepository.class));
} }
@Test(expected = NoSuchBeanDefinitionException.class) @Test
public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() { public void autoConfigurationShouldNotKickInEvenIfManualConfigDidNotCreateAnyRepositories() {
prepareApplicationContext(SortOfInvalidCustomConfiguration.class); this.runner.withUserConfiguration(SortOfInvalidCustomConfiguration.class).run(
(context) -> assertThat(context).doesNotHaveBean(CityRepository.class));
}
this.context.getBean(CityRepository.class); @Test
public void enablingReactiveRepositoriesDisablesImperativeRepositories() {
this.runner.withUserConfiguration(TestConfiguration.class)
.withPropertyValues("spring.data.mongodb.repositories.type=reactive")
.run((context) -> assertThat(context)
.doesNotHaveBean(CityRepository.class));
} }
private void prepareApplicationContext(Class<?>... configurationClasses) { @Test
this.context = new AnnotationConfigApplicationContext(); public void enablingNoRepositoriesDisablesReactiveRepositories() {
this.context.register(configurationClasses); this.runner.withUserConfiguration(TestConfiguration.class)
this.context.register(MongoAutoConfiguration.class, .withPropertyValues("spring.data.mongodb.repositories.type=none")
MongoDataAutoConfiguration.class, .run((context) -> assertThat(context)
MongoRepositoriesAutoConfiguration.class, .doesNotHaveBean(CityRepository.class));
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
} }
@Configuration @Configuration
......
...@@ -576,10 +576,9 @@ content into your application. Rather, pick only the properties that you need. ...@@ -576,10 +576,9 @@ content into your application. Rather, pick only the properties that you need.
spring.data.cassandra.pool.idle-timeout=120 # Idle timeout before an idle connection is removed. If a duration suffix is not specified, seconds will be used. spring.data.cassandra.pool.idle-timeout=120 # Idle timeout before an idle connection is removed. If a duration suffix is not specified, seconds will be used.
spring.data.cassandra.pool.max-queue-size=256 # Maximum number of requests that get queued if no connection is available. spring.data.cassandra.pool.max-queue-size=256 # Maximum number of requests that get queued if no connection is available.
spring.data.cassandra.pool.pool-timeout=5000ms # Pool timeout when trying to acquire a connection from a host's pool. spring.data.cassandra.pool.pool-timeout=5000ms # Pool timeout when trying to acquire a connection from a host's pool.
spring.data.cassandra.reactiverepositories.enabled=true # Whether to enable Cassandra reactive repositories.
spring.data.cassandra.read-timeout= # Socket option: read time out. spring.data.cassandra.read-timeout= # Socket option: read time out.
spring.data.cassandra.reconnection-policy= # Reconnection policy class. spring.data.cassandra.reconnection-policy= # Reconnection policy class.
spring.data.cassandra.repositories.enabled= # Enable Cassandra repositories. spring.data.cassandra.repositories.type=auto # Type of Cassandra repositories to enable.
spring.data.cassandra.retry-policy= # Class name of the retry policy. spring.data.cassandra.retry-policy= # Class name of the retry policy.
spring.data.cassandra.serial-consistency-level= # Queries serial consistency level. spring.data.cassandra.serial-consistency-level= # Queries serial consistency level.
spring.data.cassandra.schema-action=none # Schema action to take at startup. spring.data.cassandra.schema-action=none # Schema action to take at startup.
...@@ -589,8 +588,7 @@ content into your application. Rather, pick only the properties that you need. ...@@ -589,8 +588,7 @@ content into your application. Rather, pick only the properties that you need.
# DATA COUCHBASE ({sc-spring-boot-autoconfigure}/data/couchbase/CouchbaseDataProperties.{sc-ext}[CouchbaseDataProperties]) # DATA COUCHBASE ({sc-spring-boot-autoconfigure}/data/couchbase/CouchbaseDataProperties.{sc-ext}[CouchbaseDataProperties])
spring.data.couchbase.auto-index=false # Automatically create views and indexes. spring.data.couchbase.auto-index=false # Automatically create views and indexes.
spring.data.couchbase.consistency=read-your-own-writes # Consistency to apply by default on generated queries. spring.data.couchbase.consistency=read-your-own-writes # Consistency to apply by default on generated queries.
spring.data.couchbase.reactiverepositories.enabled=true # Enable Couchbase reactive repositories. spring.data.couchbase.repositories.type=auto # Type of Couchbase repositories to enable.
spring.data.couchbase.repositories.enabled=true # Enable Couchbase repositories.
# ELASTICSEARCH ({sc-spring-boot-autoconfigure}/data/elasticsearch/ElasticsearchProperties.{sc-ext}[ElasticsearchProperties]) # ELASTICSEARCH ({sc-spring-boot-autoconfigure}/data/elasticsearch/ElasticsearchProperties.{sc-ext}[ElasticsearchProperties])
spring.data.elasticsearch.cluster-name=elasticsearch # Elasticsearch cluster name. spring.data.elasticsearch.cluster-name=elasticsearch # Elasticsearch cluster name.
...@@ -609,8 +607,7 @@ content into your application. Rather, pick only the properties that you need. ...@@ -609,8 +607,7 @@ content into your application. Rather, pick only the properties that you need.
spring.data.mongodb.host=localhost # Mongo server host. Cannot be set with URI. spring.data.mongodb.host=localhost # Mongo server host. Cannot be set with URI.
spring.data.mongodb.password= # Login password of the mongo server. Cannot be set with URI. spring.data.mongodb.password= # Login password of the mongo server. Cannot be set with URI.
spring.data.mongodb.port=27017 # Mongo server port. Cannot be set with URI. spring.data.mongodb.port=27017 # Mongo server port. Cannot be set with URI.
spring.data.mongodb.reactiverepositories.enabled=true # Whether to enable Mongo reactive repositories. spring.data.mongodb.repositories.type=true # Type of Mongo repositories to enable.
spring.data.mongodb.repositories.enabled=true # Whether to enable Mongo repositories.
spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. Cannot be set with host, port and credentials. spring.data.mongodb.uri=mongodb://localhost/test # Mongo database URI. Cannot be set with host, port and credentials.
spring.data.mongodb.username= # Login user of the mongo server. Cannot be set with URI. spring.data.mongodb.username= # Login user of the mongo server. Cannot be set with URI.
......
...@@ -1902,10 +1902,11 @@ repositories for you. The most explicit way to do that is to use the standard Sp ...@@ -1902,10 +1902,11 @@ repositories for you. The most explicit way to do that is to use the standard Sp
`+@EnableJpaRepositories+` and `+@EnableMongoRepositories+` annotations and provide the `+@EnableJpaRepositories+` and `+@EnableMongoRepositories+` annotations and provide the
location of your `Repository` interfaces. location of your `Repository` interfaces.
There are also flags (`+spring.data.*.repositories.enabled+`) that you can use to switch the There are also flags (`+spring.data.*.repositories.enabled+` and
auto-configured repositories on and off in external configuration. Doing so is useful, for `+spring.data.*.repositories.type+`) that you can use to switch the auto-configured
instance, in case you want to switch off the Mongo repositories and still use the repositories on and off in external configuration. Doing so is useful, for instance, in
auto-configured `MongoTemplate`. case you want to switch off the Mongo repositories and still use the auto-configured
`MongoTemplate`.
The same obstacle and the same features exist for other auto-configured Spring Data The same obstacle and the same features exist for other auto-configured Spring Data
repository types (Elasticsearch, Solr, and others). To work with them, change the names of the annotations and flags repository types (Elasticsearch, Solr, and others). To work with them, change the names of the annotations and flags
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment