From 568cd6472b7b6c639f189c2864c13c3be2f61a13 Mon Sep 17 00:00:00 2001 From: Alex Derkach Date: Sun, 29 Oct 2017 16:47:06 +0200 Subject: [PATCH] Add support for reactive Spring Data Couchbase See gh-10812 --- ...ouchbaseReactiveDataAutoConfiguration.java | 41 +++++ ...ReactiveRepositoriesAutoConfiguration.java | 48 ++++++ ...iveRepositoriesAutoConfigureRegistrar.java | 57 +++++++ ...ootCouchbaseReactiveDataConfiguration.java | 74 ++++++++ ...itional-spring-configuration-metadata.json | 10 +- .../main/resources/META-INF/spring.factories | 2 + .../ReactiveCityCouchbaseRepository.java | 28 +++ ...aseReactiveDataAutoConfigurationTests.java | 160 ++++++++++++++++++ ...iveRepositoriesAutoConfigurationTests.java | 125 ++++++++++++++ .../city/ReactiveCityRepository.java | 26 +++ .../spring-boot-dependencies/pom.xml | 5 + .../appendix-application-properties.adoc | 1 + .../spring-boot-starters/pom.xml | 1 + .../pom.xml | 41 +++++ .../main/resources/META-INF/spring.provides | 1 + 15 files changed, 618 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfiguration.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigureRegistrar.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/SpringBootCouchbaseReactiveDataConfiguration.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/couchbase/ReactiveCityCouchbaseRepository.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfigurationTests.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigurationTests.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/city/ReactiveCityRepository.java create mode 100644 spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/pom.xml create mode 100644 spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/src/main/resources/META-INF/spring.provides diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfiguration.java new file mode 100644 index 0000000000..16a38b7f42 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfiguration.java @@ -0,0 +1,41 @@ +/* + * 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.couchbase; + +import com.couchbase.client.java.Bucket; +import reactor.core.publisher.Flux; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Reactive Couchbase + * support. + * + * @author Alex Derkach + * @since 2.0.0 + */ +@Configuration +@ConditionalOnClass({Bucket.class, ReactiveCouchbaseRepository.class, Flux.class}) +@AutoConfigureAfter(CouchbaseDataAutoConfiguration.class) +@Import(SpringBootCouchbaseReactiveDataConfiguration.class) +public class CouchbaseReactiveDataAutoConfiguration { +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfiguration.java new file mode 100644 index 0000000000..9de42979ad --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfiguration.java @@ -0,0 +1,48 @@ +/* + * 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.couchbase; + +import com.couchbase.client.java.Bucket; + +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository; +import org.springframework.data.couchbase.repository.config.ReactiveRepositoryOperationsMapping; +import org.springframework.data.couchbase.repository.support.ReactiveCouchbaseRepositoryFactoryBean; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Couchbase + * Reactive Repositories. + * + * @author Alex Derkach + * @since 2.0.0 + */ +@Configuration +@ConditionalOnClass({Bucket.class, ReactiveCouchbaseRepository.class}) +@ConditionalOnProperty(prefix = "spring.data.couchbase.reactive-repositories", name = "enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnBean(ReactiveRepositoryOperationsMapping.class) +@ConditionalOnMissingBean(ReactiveCouchbaseRepositoryFactoryBean.class) +@Import(CouchbaseReactiveRepositoriesAutoConfigureRegistrar.class) +@AutoConfigureAfter(CouchbaseReactiveDataAutoConfiguration.class) +public class CouchbaseReactiveRepositoriesAutoConfiguration { +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigureRegistrar.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigureRegistrar.java new file mode 100644 index 0000000000..5678e99f87 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigureRegistrar.java @@ -0,0 +1,57 @@ +/* + * 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.couchbase; + +import java.lang.annotation.Annotation; + +import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.data.couchbase.repository.config.EnableReactiveCouchbaseRepositories; +import org.springframework.data.couchbase.repository.config.ReactiveCouchbaseRepositoryConfigurationExtension; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +/** + * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Couchbase + * Reactive Repositories. + * + * @author Alex Derkach + * @since 2.0.0 + */ +public class CouchbaseReactiveRepositoriesAutoConfigureRegistrar + extends AbstractRepositoryConfigurationSourceSupport { + + @Override + protected Class getAnnotation() { + return EnableReactiveCouchbaseRepositories.class; + } + + @Override + protected Class getConfiguration() { + return EnableReactiveCouchbaseRepositoriesConfiguration.class; + } + + @Override + protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() { + return new ReactiveCouchbaseRepositoryConfigurationExtension(); + } + + @EnableReactiveCouchbaseRepositories + private static class EnableReactiveCouchbaseRepositoriesConfiguration { + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/SpringBootCouchbaseReactiveDataConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/SpringBootCouchbaseReactiveDataConfiguration.java new file mode 100644 index 0000000000..e00db28c48 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/couchbase/SpringBootCouchbaseReactiveDataConfiguration.java @@ -0,0 +1,74 @@ +/* + * 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.couchbase; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.couchbase.config.AbstractReactiveCouchbaseDataConfiguration; +import org.springframework.data.couchbase.config.BeanNames; +import org.springframework.data.couchbase.config.CouchbaseConfigurer; +import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate; +import org.springframework.data.couchbase.core.query.Consistency; +import org.springframework.data.couchbase.repository.config.ReactiveRepositoryOperationsMapping; + +/** + * Configure Spring Data's reactive couchbase support. + * + * @author Alex Derkach + * @since 2.0.0 + */ +@Configuration +@ConditionalOnMissingBean(AbstractReactiveCouchbaseDataConfiguration.class) +@ConditionalOnBean(CouchbaseConfigurer.class) +class SpringBootCouchbaseReactiveDataConfiguration extends AbstractReactiveCouchbaseDataConfiguration { + + private final CouchbaseDataProperties properties; + + private final CouchbaseConfigurer couchbaseConfigurer; + + SpringBootCouchbaseReactiveDataConfiguration(CouchbaseDataProperties properties, + CouchbaseConfigurer couchbaseConfigurer) { + this.properties = properties; + this.couchbaseConfigurer = couchbaseConfigurer; + } + + @Override + protected CouchbaseConfigurer couchbaseConfigurer() { + return this.couchbaseConfigurer; + } + + @Override + protected Consistency getDefaultConsistency() { + return this.properties.getConsistency(); + } + + @Override + @ConditionalOnMissingBean(name = BeanNames.RXJAVA1_COUCHBASE_TEMPLATE) + @Bean(name = BeanNames.RXJAVA1_COUCHBASE_TEMPLATE) + public RxJavaCouchbaseTemplate reactiveCouchbaseTemplate() throws Exception { + return super.reactiveCouchbaseTemplate(); + } + + @Override + @ConditionalOnMissingBean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING) + @Bean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING) + public ReactiveRepositoryOperationsMapping reactiveRepositoryOperationsMapping(RxJavaCouchbaseTemplate reactiveCouchbaseTemplate) throws Exception { + return super.reactiveRepositoryOperationsMapping(reactiveCouchbaseTemplate); + } +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json index a8d05d7f98..ef10ef518b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json @@ -99,14 +99,20 @@ "description": "Enable Cassandra reactive repositories.", "defaultValue": true }, + { + "name": "spring.data.cassandra.repositories.enabled", + "type": "java.lang.Boolean", + "description": "Enable Cassandra repositories.", + "defaultValue": true + }, { "name": "spring.data.couchbase.consistency", "defaultValue": "read-your-own-writes" }, { - "name": "spring.data.cassandra.repositories.enabled", + "name": "spring.data.couchbase.reactive-repositories.enabled", "type": "java.lang.Boolean", - "description": "Enable Cassandra repositories.", + "description": "Enable Couchbase reactive repositories.", "defaultValue": true }, { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 0afb614c7b..2e140d4d0c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -34,6 +34,8 @@ org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoC org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.couchbase.CouchbaseRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/couchbase/ReactiveCityCouchbaseRepository.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/couchbase/ReactiveCityCouchbaseRepository.java new file mode 100644 index 0000000000..4fd710643e --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/couchbase/ReactiveCityCouchbaseRepository.java @@ -0,0 +1,28 @@ +/* + * 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.alt.couchbase; + +import reactor.core.publisher.Mono; + +import org.springframework.boot.autoconfigure.data.couchbase.city.City; +import org.springframework.data.repository.Repository; + +public interface ReactiveCityCouchbaseRepository extends Repository { + Mono save(City city); + + Mono findById(Long id); +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfigurationTests.java new file mode 100644 index 0000000000..c8ca7a7eda --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveDataAutoConfigurationTests.java @@ -0,0 +1,160 @@ +/* + * 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.couchbase; + +import java.util.Collections; +import java.util.Set; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; +import org.springframework.boot.autoconfigure.data.couchbase.city.City; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.couchbase.config.AbstractReactiveCouchbaseDataConfiguration; +import org.springframework.data.couchbase.config.BeanNames; +import org.springframework.data.couchbase.config.CouchbaseConfigurer; +import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate; +import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions; +import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; +import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; +import org.springframework.data.couchbase.core.query.Consistency; +import org.springframework.data.couchbase.repository.support.IndexManager; +import org.springframework.test.util.ReflectionTestUtils; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CouchbaseReactiveDataAutoConfiguration}. + * + * @author Alex Derkach + */ +public class CouchbaseReactiveDataAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void disabledIfCouchbaseIsNotConfigured() { + load(null); + assertThat(this.context.getBeansOfType(IndexManager.class)).isEmpty(); + } + + @Test + public void customConfiguration() { + load(CustomCouchbaseConfiguration.class); + RxJavaCouchbaseTemplate rxJavaCouchbaseTemplate = this.context.getBean(RxJavaCouchbaseTemplate.class); + assertThat(rxJavaCouchbaseTemplate.getDefaultConsistency()).isEqualTo(Consistency.STRONGLY_CONSISTENT); + } + + @Test + public void validatorIsPresent() { + load(CouchbaseTestConfigurer.class); + assertThat(this.context.getBeansOfType(ValidatingCouchbaseEventListener.class)).hasSize(1); + } + + @Test + @SuppressWarnings("unchecked") + public void entityScanShouldSetInitialEntitySet() throws Exception { + load(EntityScanConfig.class); + CouchbaseMappingContext mappingContext = this.context + .getBean(CouchbaseMappingContext.class); + Set> initialEntitySet = (Set>) ReflectionTestUtils + .getField(mappingContext, "initialEntitySet"); + assertThat(initialEntitySet).containsOnly(City.class); + } + + @Test + public void customConversions() { + load(CustomConversionsConfig.class); + RxJavaCouchbaseTemplate template = this.context.getBean(RxJavaCouchbaseTemplate.class); + assertThat(template.getConverter().getConversionService() + .canConvert(CouchbaseProperties.class, Boolean.class)).isTrue(); + } + + private void load(Class config, String... environment) { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of(environment).applyTo(context); + if (config != null) { + context.register(config); + } + context.register(PropertyPlaceholderAutoConfiguration.class, + ValidationAutoConfiguration.class, CouchbaseAutoConfiguration.class, + CouchbaseDataAutoConfiguration.class, CouchbaseReactiveDataAutoConfiguration.class); + context.refresh(); + this.context = context; + } + + @Configuration + static class CustomCouchbaseConfiguration extends AbstractReactiveCouchbaseDataConfiguration { + + @Override + protected CouchbaseConfigurer couchbaseConfigurer() { + return new CouchbaseTestConfigurer(); + } + + @Override + protected Consistency getDefaultConsistency() { + return Consistency.STRONGLY_CONSISTENT; + } + + } + + @Configuration + @Import(CouchbaseTestConfigurer.class) + static class CustomConversionsConfig { + + @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS) + public CouchbaseCustomConversions myCustomConversions() { + return new CouchbaseCustomConversions( + Collections.singletonList(new MyConverter())); + } + + } + + @Configuration + @EntityScan("org.springframework.boot.autoconfigure.data.couchbase.city") + @Import(CustomCouchbaseConfiguration.class) + static class EntityScanConfig { + + } + + static class MyConverter implements Converter { + + @Override + public Boolean convert(CouchbaseProperties value) { + return true; + } + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigurationTests.java new file mode 100644 index 0000000000..4f75978961 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/CouchbaseReactiveRepositoriesAutoConfigurationTests.java @@ -0,0 +1,125 @@ +/* + * 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.couchbase; + +import org.junit.After; +import org.junit.Test; + +import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; +import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; +import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; +import org.springframework.boot.autoconfigure.data.alt.couchbase.CityCouchbaseRepository; +import org.springframework.boot.autoconfigure.data.alt.couchbase.ReactiveCityCouchbaseRepository; +import org.springframework.boot.autoconfigure.data.couchbase.city.City; +import org.springframework.boot.autoconfigure.data.couchbase.city.ReactiveCityRepository; +import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link CouchbaseReactiveRepositoriesAutoConfiguration}. + * + * @author Alex Derkach + */ +public class CouchbaseReactiveRepositoriesAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void couchbaseNotAvailable() throws Exception { + load(null); + assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0); + } + + @Test + public void defaultRepository() throws Exception { + load(DefaultConfiguration.class); + assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(1); + } + + @Test + public void disableReactiveRepository() { + load(DefaultConfiguration.class, + "spring.data.couchbase.reactive-repositories.enabled=false", + "spring.data.couchbase.repositories.enabled=false"); + assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0); + } + + @Test + public void noRepositoryAvailable() throws Exception { + load(NoRepositoryConfiguration.class); + assertThat(this.context.getBeansOfType(ReactiveCityRepository.class)).hasSize(0); + } + + @Test + public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { + load(CouchbaseReactiveRepositoriesAutoConfigurationTests.CustomizedConfiguration.class); + assertThat(this.context.getBeansOfType(ReactiveCityCouchbaseRepository.class)) + .isEmpty(); + } + + private void load(Class config, String... environment) { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of(environment).applyTo(context); + if (config != null) { + context.register(config); + } + context.register(PropertyPlaceholderAutoConfiguration.class, + CouchbaseAutoConfiguration.class, + CouchbaseDataAutoConfiguration.class, + CouchbaseRepositoriesAutoConfiguration.class, + CouchbaseReactiveDataAutoConfiguration.class, + CouchbaseReactiveRepositoriesAutoConfiguration.class + ); + context.refresh(); + this.context = context; + } + + @Configuration + @TestAutoConfigurationPackage(City.class) + @Import(CouchbaseTestConfigurer.class) + static class DefaultConfiguration { + + } + + @Configuration + @TestAutoConfigurationPackage(EmptyDataPackage.class) + @Import(CouchbaseTestConfigurer.class) + protected static class NoRepositoryConfiguration { + + } + + @Configuration + @TestAutoConfigurationPackage(CouchbaseReactiveRepositoriesAutoConfigurationTests.class) + @EnableMongoRepositories(basePackageClasses = CityCouchbaseRepository.class) + protected static class CustomizedConfiguration { + + } +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/city/ReactiveCityRepository.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/city/ReactiveCityRepository.java new file mode 100644 index 0000000000..4163264874 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/couchbase/city/ReactiveCityRepository.java @@ -0,0 +1,26 @@ +/* + * 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.couchbase.city; + +import reactor.core.publisher.Mono; + +import org.springframework.data.repository.Repository; + +public interface ReactiveCityRepository extends Repository { + Mono save(City city); + Mono findById(Long id); +} diff --git a/spring-boot-project/spring-boot-dependencies/pom.xml b/spring-boot-project/spring-boot-dependencies/pom.xml index 1a9474d6e3..e5234780ae 100644 --- a/spring-boot-project/spring-boot-dependencies/pom.xml +++ b/spring-boot-project/spring-boot-dependencies/pom.xml @@ -334,6 +334,11 @@ spring-boot-starter-data-couchbase ${revision} + + org.springframework.boot + spring-boot-starter-data-couchbase-reactive + ${revision} + org.springframework.boot spring-boot-starter-data-elasticsearch diff --git a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 0cc22e2637..f3076e8aeb 100644 --- a/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-project/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -588,6 +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]) 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.reactive-repositories.enabled=true # Enable Couchbase reactive repositories. spring.data.couchbase.repositories.enabled=true # Enable Couchbase repositories. # ELASTICSEARCH ({sc-spring-boot-autoconfigure}/data/elasticsearch/ElasticsearchProperties.{sc-ext}[ElasticsearchProperties]) diff --git a/spring-boot-project/spring-boot-starters/pom.xml b/spring-boot-project/spring-boot-starters/pom.xml index 60d1360616..6f9a4da9a5 100644 --- a/spring-boot-project/spring-boot-starters/pom.xml +++ b/spring-boot-project/spring-boot-starters/pom.xml @@ -27,6 +27,7 @@ spring-boot-starter-data-cassandra spring-boot-starter-data-cassandra-reactive spring-boot-starter-data-couchbase + spring-boot-starter-data-couchbase-reactive spring-boot-starter-data-elasticsearch spring-boot-starter-data-jpa spring-boot-starter-data-ldap diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/pom.xml b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/pom.xml new file mode 100644 index 0000000000..34c28d7ae4 --- /dev/null +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + spring-boot-starters + org.springframework.boot + ${revision} + + spring-boot-starter-data-couchbase-reactive + Spring Boot Data Couchbase Reactive Starter + Starter for using Couchbase document-oriented database and Spring Data + Couchbase Reactive + + ${basedir}/../../.. + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.data + spring-data-couchbase + + + org.slf4j + jcl-over-slf4j + + + com.couchbase.mock + CouchbaseMock + + + + + io.projectreactor + reactor-core + + + diff --git a/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/src/main/resources/META-INF/spring.provides b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/src/main/resources/META-INF/spring.provides new file mode 100644 index 0000000000..7eb2d6ff97 --- /dev/null +++ b/spring-boot-project/spring-boot-starters/spring-boot-starter-data-couchbase-reactive/src/main/resources/META-INF/spring.provides @@ -0,0 +1 @@ +provides: spring-data-couchbase