Commit e3899df2 authored by Stephane Nicoll's avatar Stephane Nicoll

Configure Spring Data Couchbase explicitly

This commit configures Spring Data Couchbase explicitly rather than
relying on the abstract configuration class. This has the advantage of
simplifying the auto-configuration and let it us proxy-free
configuration classes.

Spring Boot no longer uses or interacts with CouchbaseConfigurer. Users
relying on that to teach Spring Boot which components to use should
rely on `@Primary` flag instead in case of multiple beans of the same
type.

`CouchbaseConfiguration` is no longer public as extending from it is
no longer necessary. If the `CouchbaseEnvironment` has to be
customized, a `CouchbaseEnvironmentBuilderCustomizer` bean can be
registered to tune the auto-configured environment.

Closes gh-20533
parent 4544785a
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -16,18 +16,28 @@ ...@@ -16,18 +16,28 @@
package org.springframework.boot.autoconfigure.couchbase; package org.springframework.boot.autoconfigure.couchbase;
import com.couchbase.client.core.env.KeyValueServiceConfig;
import com.couchbase.client.core.env.QueryServiceConfig;
import com.couchbase.client.core.env.ViewServiceConfig;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseBucket; import com.couchbase.client.java.CouchbaseBucket;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment.Builder;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
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.couchbase.CouchbaseProperties.Endpoints;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.DependsOn;
/** /**
* {@link EnableAutoConfiguration Auto-configuration} for Couchbase. * {@link EnableAutoConfiguration Auto-configuration} for Couchbase.
...@@ -39,42 +49,105 @@ import org.springframework.context.annotation.Import; ...@@ -39,42 +49,105 @@ import org.springframework.context.annotation.Import;
*/ */
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ CouchbaseBucket.class, Cluster.class }) @ConditionalOnClass({ CouchbaseBucket.class, Cluster.class })
@Conditional(CouchbaseAutoConfiguration.CouchbaseCondition.class) @Conditional(OnBootstrapHostsCondition.class)
@EnableConfigurationProperties(CouchbaseProperties.class) @EnableConfigurationProperties(CouchbaseProperties.class)
public class CouchbaseAutoConfiguration { public class CouchbaseAutoConfiguration {
@Configuration(proxyBeanMethods = false) @Bean
@ConditionalOnMissingBean(value = CouchbaseConfiguration.class, @ConditionalOnMissingBean(CouchbaseEnvironment.class)
type = "org.springframework.data.couchbase.config.CouchbaseConfigurer") public DefaultCouchbaseEnvironment couchbaseEnvironment(CouchbaseProperties properties,
@Import(CouchbaseConfiguration.class) ObjectProvider<CouchbaseEnvironmentBuilderCustomizer> customizers) {
static class DefaultCouchbaseConfiguration { Builder builder = initializeEnvironmentBuilder(properties);
customizers.orderedStream().forEach((customizer) -> customizer.customize(builder));
return builder.build();
} }
/** @Bean
* Determine if Couchbase should be configured. This happens if either the @ConditionalOnMissingBean(Cluster.class)
* user-configuration defines a {@code CouchbaseConfigurer} or if at least the public CouchbaseCluster couchbaseCluster(CouchbaseProperties properties,
* "bootstrapHosts" property is specified. CouchbaseEnvironment couchbaseEnvironment) {
* <p> CouchbaseCluster couchbaseCluster = CouchbaseCluster.create(couchbaseEnvironment,
* The reason why we check for the presence of {@code CouchbaseConfigurer} is that it properties.getBootstrapHosts());
* might use {@link CouchbaseProperties} for its internal customization. if (isRoleBasedAccessControlEnabled(properties)) {
*/ return couchbaseCluster.authenticate(properties.getUsername(), properties.getPassword());
static class CouchbaseCondition extends AnyNestedCondition {
CouchbaseCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
} }
return couchbaseCluster;
}
@Conditional(OnBootstrapHostsCondition.class) @Bean
static class BootstrapHostsProperty { @ConditionalOnMissingBean
@DependsOn("couchbaseClient")
public ClusterInfo couchbaseClusterInfo(CouchbaseProperties properties, Cluster couchbaseCluster) {
if (isRoleBasedAccessControlEnabled(properties)) {
return couchbaseCluster.clusterManager().info();
}
return couchbaseCluster.clusterManager(properties.getBucket().getName(), properties.getBucket().getPassword())
.info();
}
@Bean
@ConditionalOnMissingBean
public Bucket couchbaseClient(CouchbaseProperties properties, Cluster couchbaseCluster) {
if (isRoleBasedAccessControlEnabled(properties)) {
return couchbaseCluster.openBucket(properties.getBucket().getName());
} }
return couchbaseCluster.openBucket(properties.getBucket().getName(), properties.getBucket().getPassword());
}
@ConditionalOnBean(type = "org.springframework.data.couchbase.config.CouchbaseConfigurer") private boolean isRoleBasedAccessControlEnabled(CouchbaseProperties properties) {
static class CouchbaseConfigurerAvailable { return properties.getUsername() != null && properties.getPassword() != null;
}
private DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
CouchbaseProperties.Bootstrap bootstrap = properties.getEnv().getBootstrap();
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder();
if (bootstrap.getHttpDirectPort() != null) {
builder.bootstrapHttpDirectPort(bootstrap.getHttpDirectPort());
}
if (bootstrap.getHttpSslPort() != null) {
builder.bootstrapHttpSslPort(bootstrap.getHttpSslPort());
}
if (timeouts.getConnect() != null) {
builder = builder.connectTimeout(timeouts.getConnect().toMillis());
} }
builder = builder.keyValueServiceConfig(KeyValueServiceConfig.create(endpoints.getKeyValue()));
if (timeouts.getKeyValue() != null) {
builder = builder.kvTimeout(timeouts.getKeyValue().toMillis());
}
if (timeouts.getQuery() != null) {
builder = builder.queryTimeout(timeouts.getQuery().toMillis());
builder = builder.queryServiceConfig(getQueryServiceConfig(endpoints));
builder = builder.viewServiceConfig(getViewServiceConfig(endpoints));
}
if (timeouts.getSocketConnect() != null) {
builder = builder.socketConnectTimeout((int) timeouts.getSocketConnect().toMillis());
}
if (timeouts.getView() != null) {
builder = builder.viewTimeout(timeouts.getView().toMillis());
}
CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl();
if (ssl.getEnabled()) {
builder = builder.sslEnabled(true);
if (ssl.getKeyStore() != null) {
builder = builder.sslKeystoreFile(ssl.getKeyStore());
}
if (ssl.getKeyStorePassword() != null) {
builder = builder.sslKeystorePassword(ssl.getKeyStorePassword());
}
}
return builder;
}
private QueryServiceConfig getQueryServiceConfig(Endpoints endpoints) {
return QueryServiceConfig.create(endpoints.getQueryservice().getMinEndpoints(),
endpoints.getQueryservice().getMaxEndpoints());
}
private ViewServiceConfig getViewServiceConfig(Endpoints endpoints) {
return ViewServiceConfig.create(endpoints.getViewservice().getMinEndpoints(),
endpoints.getViewservice().getMaxEndpoints());
} }
} }
/*
* Copyright 2012-2020 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
*
* https://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.couchbase;
import java.util.List;
import com.couchbase.client.core.env.KeyValueServiceConfig;
import com.couchbase.client.core.env.QueryServiceConfig;
import com.couchbase.client.core.env.ViewServiceConfig;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseCluster;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties.Endpoints;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
/**
* Support class to configure Couchbase based on {@link CouchbaseProperties}.
*
* @author Stephane Nicoll
* @author Brian Clozel
* @since 2.1.0
*/
@Configuration
public class CouchbaseConfiguration {
private final CouchbaseProperties properties;
public CouchbaseConfiguration(CouchbaseProperties properties) {
this.properties = properties;
}
@Bean
@Primary
public DefaultCouchbaseEnvironment couchbaseEnvironment() {
return initializeEnvironmentBuilder(this.properties).build();
}
@Bean
@Primary
public Cluster couchbaseCluster() {
CouchbaseCluster couchbaseCluster = CouchbaseCluster.create(couchbaseEnvironment(), determineBootstrapHosts());
if (isRoleBasedAccessControlEnabled()) {
return couchbaseCluster.authenticate(this.properties.getUsername(), this.properties.getPassword());
}
return couchbaseCluster;
}
/**
* Determine the Couchbase nodes to bootstrap from.
* @return the Couchbase nodes to bootstrap from
*/
protected List<String> determineBootstrapHosts() {
return this.properties.getBootstrapHosts();
}
@Bean
@Primary
@DependsOn("couchbaseClient")
public ClusterInfo couchbaseClusterInfo() {
if (isRoleBasedAccessControlEnabled()) {
return couchbaseCluster().clusterManager().info();
}
return couchbaseCluster()
.clusterManager(this.properties.getBucket().getName(), this.properties.getBucket().getPassword())
.info();
}
@Bean
@Primary
public Bucket couchbaseClient() {
if (isRoleBasedAccessControlEnabled()) {
return couchbaseCluster().openBucket(this.properties.getBucket().getName());
}
return couchbaseCluster().openBucket(this.properties.getBucket().getName(),
this.properties.getBucket().getPassword());
}
private boolean isRoleBasedAccessControlEnabled() {
return this.properties.getUsername() != null && this.properties.getPassword() != null;
}
/**
* Initialize an environment builder based on the specified settings.
* @param properties the couchbase properties to use
* @return the {@link DefaultCouchbaseEnvironment} builder.
*/
protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
CouchbaseProperties.Bootstrap bootstrap = properties.getEnv().getBootstrap();
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder();
if (bootstrap.getHttpDirectPort() != null) {
builder.bootstrapHttpDirectPort(bootstrap.getHttpDirectPort());
}
if (bootstrap.getHttpSslPort() != null) {
builder.bootstrapHttpSslPort(bootstrap.getHttpSslPort());
}
if (timeouts.getConnect() != null) {
builder = builder.connectTimeout(timeouts.getConnect().toMillis());
}
builder = builder.keyValueServiceConfig(KeyValueServiceConfig.create(endpoints.getKeyValue()));
if (timeouts.getKeyValue() != null) {
builder = builder.kvTimeout(timeouts.getKeyValue().toMillis());
}
if (timeouts.getQuery() != null) {
builder = builder.queryTimeout(timeouts.getQuery().toMillis());
builder = builder.queryServiceConfig(getQueryServiceConfig(endpoints));
builder = builder.viewServiceConfig(getViewServiceConfig(endpoints));
}
if (timeouts.getSocketConnect() != null) {
builder = builder.socketConnectTimeout((int) timeouts.getSocketConnect().toMillis());
}
if (timeouts.getView() != null) {
builder = builder.viewTimeout(timeouts.getView().toMillis());
}
CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl();
if (ssl.getEnabled()) {
builder = builder.sslEnabled(true);
if (ssl.getKeyStore() != null) {
builder = builder.sslKeystoreFile(ssl.getKeyStore());
}
if (ssl.getKeyStorePassword() != null) {
builder = builder.sslKeystorePassword(ssl.getKeyStorePassword());
}
}
return builder;
}
private QueryServiceConfig getQueryServiceConfig(Endpoints endpoints) {
return QueryServiceConfig.create(endpoints.getQueryservice().getMinEndpoints(),
endpoints.getQueryservice().getMaxEndpoints());
}
private ViewServiceConfig getViewServiceConfig(Endpoints endpoints) {
return ViewServiceConfig.create(endpoints.getViewservice().getMinEndpoints(),
endpoints.getViewservice().getMaxEndpoints());
}
}
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -14,57 +14,26 @@ ...@@ -14,57 +14,26 @@
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.boot.autoconfigure.data.couchbase; package org.springframework.boot.autoconfigure.couchbase;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.CouchbaseEnvironment; import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
/** /**
* A simple {@link CouchbaseConfigurer} implementation. * Callback interface that can be implemented by beans wishing to customize the
* {@link CouchbaseEnvironment} via a {@link DefaultCouchbaseEnvironment.Builder} whilst
* retaining default auto-configuration.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 1.4.0 * @since 2.3.0
*/ */
public class SpringBootCouchbaseConfigurer implements CouchbaseConfigurer { @FunctionalInterface
public interface CouchbaseEnvironmentBuilderCustomizer {
private final CouchbaseEnvironment env;
/**
private final Cluster cluster; * Customize the {@link DefaultCouchbaseEnvironment.Builder}.
* @param builder the builder to customize
private final ClusterInfo clusterInfo; */
void customize(DefaultCouchbaseEnvironment.Builder builder);
private final Bucket bucket;
public SpringBootCouchbaseConfigurer(CouchbaseEnvironment env, Cluster cluster, ClusterInfo clusterInfo,
Bucket bucket) {
this.env = env;
this.cluster = cluster;
this.clusterInfo = clusterInfo;
this.bucket = bucket;
}
@Override
public CouchbaseEnvironment couchbaseEnvironment() throws Exception {
return this.env;
}
@Override
public Cluster couchbaseCluster() throws Exception {
return this.cluster;
}
@Override
public ClusterInfo couchbaseClusterInfo() throws Exception {
return this.clusterInfo;
}
@Override
public Bucket couchbaseClient() throws Exception {
return this.bucket;
}
} }
/*
* Copyright 2012-2019 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
*
* https://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.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
/**
* Adapt the core Couchbase configuration to an expected {@link CouchbaseConfigurer} if
* necessary.
*
* @author Stephane Nicoll
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(CouchbaseConfigurer.class)
@ConditionalOnBean(CouchbaseConfiguration.class)
class CouchbaseConfigurerAdapterConfiguration {
private final CouchbaseConfiguration configuration;
CouchbaseConfigurerAdapterConfiguration(CouchbaseConfiguration configuration) {
this.configuration = configuration;
}
@Bean
@ConditionalOnMissingBean
CouchbaseConfigurer springBootCouchbaseConfigurer() throws Exception {
return new SpringBootCouchbaseConfigurer(this.configuration.couchbaseEnvironment(),
this.configuration.couchbaseCluster(), this.configuration.couchbaseClusterInfo(),
this.configuration.couchbaseClient());
}
}
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -44,7 +44,7 @@ import org.springframework.data.couchbase.repository.CouchbaseRepository; ...@@ -44,7 +44,7 @@ import org.springframework.data.couchbase.repository.CouchbaseRepository;
@ConditionalOnClass({ Bucket.class, CouchbaseRepository.class }) @ConditionalOnClass({ Bucket.class, CouchbaseRepository.class })
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, ValidationAutoConfiguration.class }) @AutoConfigureAfter({ CouchbaseAutoConfiguration.class, ValidationAutoConfiguration.class })
@EnableConfigurationProperties(CouchbaseDataProperties.class) @EnableConfigurationProperties(CouchbaseDataProperties.class)
@Import({ CouchbaseConfigurerAdapterConfiguration.class, SpringBootCouchbaseDataConfiguration.class }) @Import(CouchbaseDataConfiguration.class)
public class CouchbaseDataAutoConfiguration { public class CouchbaseDataAutoConfiguration {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
......
...@@ -16,90 +16,104 @@ ...@@ -16,90 +16,104 @@
package org.springframework.boot.autoconfigure.data.couchbase; package org.springframework.boot.autoconfigure.data.couchbase;
import java.util.Set; import java.util.Collections;
import org.springframework.beans.factory.ObjectProvider; import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.cluster.ClusterInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.boot.autoconfigure.domain.EntityScanner; import org.springframework.boot.autoconfigure.domain.EntityScanner;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.annotation.Persistent; import org.springframework.data.annotation.Persistent;
import org.springframework.data.convert.CustomConversions;
import org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration;
import org.springframework.data.couchbase.config.BeanNames; import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService;
import org.springframework.data.couchbase.core.convert.translation.TranslationService;
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
import org.springframework.data.couchbase.core.mapping.Document; import org.springframework.data.couchbase.core.mapping.Document;
import org.springframework.data.couchbase.core.query.Consistency; import org.springframework.data.couchbase.repository.config.RepositoryOperationsMapping;
import org.springframework.data.couchbase.repository.support.IndexManager; import org.springframework.data.couchbase.repository.support.IndexManager;
import org.springframework.data.mapping.model.FieldNamingStrategy;
/** /**
* Configure Spring Data's couchbase support. * Configuration for Spring Data's couchbase support.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Configuration @Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(AbstractCouchbaseDataConfiguration.class) class CouchbaseDataConfiguration {
@ConditionalOnBean(CouchbaseConfigurer.class)
class SpringBootCouchbaseDataConfiguration extends AbstractCouchbaseDataConfiguration { @Bean(name = BeanNames.COUCHBASE_MAPPING_CONVERTER)
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_MAPPING_CONVERTER)
private final ApplicationContext applicationContext; MappingCouchbaseConverter couchbaseMappingConverter(CouchbaseDataProperties properties,
CouchbaseMappingContext couchbaseMappingContext, CouchbaseCustomConversions couchbaseCustomConversions) {
private final CouchbaseDataProperties properties; MappingCouchbaseConverter converter = new MappingCouchbaseConverter(couchbaseMappingContext,
properties.getTypeKey());
private final CouchbaseConfigurer couchbaseConfigurer; converter.setCustomConversions(couchbaseCustomConversions);
return converter;
SpringBootCouchbaseDataConfiguration(ApplicationContext applicationContext, CouchbaseDataProperties properties,
ObjectProvider<CouchbaseConfigurer> couchbaseConfigurer) {
this.applicationContext = applicationContext;
this.properties = properties;
this.couchbaseConfigurer = couchbaseConfigurer.getIfAvailable();
}
@Override
protected CouchbaseConfigurer couchbaseConfigurer() {
return this.couchbaseConfigurer;
}
@Override
protected Consistency getDefaultConsistency() {
return this.properties.getConsistency();
} }
@Override @Bean(name = BeanNames.COUCHBASE_TRANSLATION_SERVICE)
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException { @ConditionalOnMissingBean(name = BeanNames.COUCHBASE_TRANSLATION_SERVICE)
return new EntityScanner(this.applicationContext).scan(Document.class, Persistent.class); TranslationService couchbaseTranslationService() {
return new JacksonTranslationService();
} }
@Override @Bean(name = BeanNames.COUCHBASE_MAPPING_CONTEXT)
public String typeKey() { @ConditionalOnMissingBean(name = BeanNames.COUCHBASE_MAPPING_CONTEXT)
return this.properties.getTypeKey(); CouchbaseMappingContext couchbaseMappingContext(CouchbaseDataProperties properties,
} ApplicationContext applicationContext, CouchbaseCustomConversions couchbaseCustomConversions)
throws Exception {
@Override CouchbaseMappingContext mappingContext = new CouchbaseMappingContext();
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_TEMPLATE) mappingContext
@Bean(name = BeanNames.COUCHBASE_TEMPLATE) .setInitialEntitySet(new EntityScanner(applicationContext).scan(Document.class, Persistent.class));
public CouchbaseTemplate couchbaseTemplate() throws Exception { mappingContext.setSimpleTypeHolder(couchbaseCustomConversions.getSimpleTypeHolder());
return super.couchbaseTemplate(); Class<?> fieldNamingStrategy = properties.getFieldNamingStrategy();
if (fieldNamingStrategy != null) {
mappingContext
.setFieldNamingStrategy((FieldNamingStrategy) BeanUtils.instantiateClass(fieldNamingStrategy));
}
return mappingContext;
} }
@Override
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
@Bean(name = BeanNames.COUCHBASE_CUSTOM_CONVERSIONS) @Bean(name = BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
public CustomConversions customConversions() { @ConditionalOnMissingBean(name = BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
return super.customConversions(); CouchbaseCustomConversions couchbaseCustomConversions() {
return new CouchbaseCustomConversions(Collections.emptyList());
} }
@Override
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_INDEX_MANAGER)
@Bean(name = BeanNames.COUCHBASE_INDEX_MANAGER) @Bean(name = BeanNames.COUCHBASE_INDEX_MANAGER)
public IndexManager indexManager() { @ConditionalOnMissingBean(name = BeanNames.COUCHBASE_INDEX_MANAGER)
if (this.properties.isAutoIndex()) { IndexManager indexManager(CouchbaseDataProperties properties) {
if (properties.isAutoIndex()) {
return new IndexManager(true, true, true); return new IndexManager(true, true, true);
} }
return new IndexManager(false, false, false); return new IndexManager(false, false, false);
} }
@Bean(name = BeanNames.COUCHBASE_TEMPLATE)
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_TEMPLATE)
@ConditionalOnBean({ ClusterInfo.class, Bucket.class })
CouchbaseTemplate couchbaseTemplate(CouchbaseDataProperties properties, ClusterInfo clusterInfo, Bucket bucket,
MappingCouchbaseConverter mappingCouchbaseConverter, TranslationService translationService) {
CouchbaseTemplate template = new CouchbaseTemplate(clusterInfo, bucket, mappingCouchbaseConverter,
translationService);
template.setDefaultConsistency(properties.getConsistency());
return template;
}
@Bean(name = BeanNames.COUCHBASE_OPERATIONS_MAPPING)
@ConditionalOnMissingBean(name = BeanNames.COUCHBASE_OPERATIONS_MAPPING)
@ConditionalOnSingleCandidate(CouchbaseTemplate.class)
RepositoryOperationsMapping repositoryOperationsMapping(CouchbaseTemplate couchbaseTemplate) {
return new RepositoryOperationsMapping(couchbaseTemplate);
}
} }
...@@ -39,6 +39,11 @@ public class CouchbaseDataProperties { ...@@ -39,6 +39,11 @@ public class CouchbaseDataProperties {
*/ */
private Consistency consistency = Consistency.READ_YOUR_OWN_WRITES; private Consistency consistency = Consistency.READ_YOUR_OWN_WRITES;
/**
* Fully qualified name of the FieldNamingStrategy to use.
*/
private Class<?> fieldNamingStrategy;
/** /**
* Name of the field that stores the type information for complex types when using * Name of the field that stores the type information for complex types when using
* "MappingCouchbaseConverter". * "MappingCouchbaseConverter".
...@@ -61,6 +66,14 @@ public class CouchbaseDataProperties { ...@@ -61,6 +66,14 @@ public class CouchbaseDataProperties {
this.consistency = consistency; this.consistency = consistency;
} }
public Class<?> getFieldNamingStrategy() {
return this.fieldNamingStrategy;
}
public void setFieldNamingStrategy(Class<?> fieldNamingStrategy) {
this.fieldNamingStrategy = fieldNamingStrategy;
}
public String getTypeKey() { public String getTypeKey() {
return this.typeKey; return this.typeKey;
} }
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -36,7 +36,7 @@ import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository ...@@ -36,7 +36,7 @@ import org.springframework.data.couchbase.repository.ReactiveCouchbaseRepository
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Bucket.class, ReactiveCouchbaseRepository.class, Flux.class }) @ConditionalOnClass({ Bucket.class, ReactiveCouchbaseRepository.class, Flux.class })
@AutoConfigureAfter(CouchbaseDataAutoConfiguration.class) @AutoConfigureAfter(CouchbaseDataAutoConfiguration.class)
@Import(SpringBootCouchbaseReactiveDataConfiguration.class) @Import(CouchbaseReactiveDataConfiguration.class)
public class CouchbaseReactiveDataAutoConfiguration { public class CouchbaseReactiveDataAutoConfiguration {
} }
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -16,60 +16,45 @@ ...@@ -16,60 +16,45 @@
package org.springframework.boot.autoconfigure.data.couchbase; package org.springframework.boot.autoconfigure.data.couchbase;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.cluster.ClusterInfo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnSingleCandidate;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.BeanNames;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate; import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate;
import org.springframework.data.couchbase.core.query.Consistency; import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.convert.translation.TranslationService;
import org.springframework.data.couchbase.repository.config.ReactiveRepositoryOperationsMapping; import org.springframework.data.couchbase.repository.config.ReactiveRepositoryOperationsMapping;
/** /**
* Configure Spring Data's reactive couchbase support. * Configuration for Spring Data's couchbase reactive support.
* *
* @author Alex Derkach * @author Stephane Nicoll
*/ */
@Configuration @Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(AbstractReactiveCouchbaseDataConfiguration.class) class CouchbaseReactiveDataConfiguration {
@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) @Bean(name = BeanNames.RXJAVA1_COUCHBASE_TEMPLATE)
public RxJavaCouchbaseTemplate reactiveCouchbaseTemplate() throws Exception { @ConditionalOnMissingBean(name = BeanNames.RXJAVA1_COUCHBASE_TEMPLATE)
return super.reactiveCouchbaseTemplate(); @ConditionalOnBean({ ClusterInfo.class, Bucket.class })
RxJavaCouchbaseTemplate reactiveCouchbaseTemplate(CouchbaseDataProperties properties, ClusterInfo clusterInfo,
Bucket bucket, MappingCouchbaseConverter mappingCouchbaseConverter, TranslationService translationService) {
RxJavaCouchbaseTemplate template = new RxJavaCouchbaseTemplate(clusterInfo, bucket, mappingCouchbaseConverter,
translationService);
template.setDefaultConsistency(properties.getConsistency());
return template;
} }
@Override
@ConditionalOnMissingBean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING)
@Bean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING) @Bean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING)
public ReactiveRepositoryOperationsMapping reactiveRepositoryOperationsMapping( @ConditionalOnMissingBean(name = BeanNames.REACTIVE_COUCHBASE_OPERATIONS_MAPPING)
RxJavaCouchbaseTemplate reactiveCouchbaseTemplate) throws Exception { @ConditionalOnSingleCandidate(RxJavaCouchbaseTemplate.class)
return super.reactiveRepositoryOperationsMapping(reactiveCouchbaseTemplate); ReactiveRepositoryOperationsMapping reactiveRepositoryOperationsMapping(
RxJavaCouchbaseTemplate reactiveCouchbaseTemplate) {
return new ReactiveRepositoryOperationsMapping(reactiveCouchbaseTemplate);
} }
} }
...@@ -22,7 +22,6 @@ import java.util.List; ...@@ -22,7 +22,6 @@ import java.util.List;
import com.couchbase.client.java.Bucket; import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseBucket;
import com.couchbase.client.java.bucket.BucketType; import com.couchbase.client.java.bucket.BucketType;
import com.couchbase.client.java.cluster.BucketSettings; import com.couchbase.client.java.cluster.BucketSettings;
import com.couchbase.client.java.cluster.ClusterInfo; import com.couchbase.client.java.cluster.ClusterInfo;
...@@ -30,16 +29,14 @@ import com.couchbase.client.java.cluster.DefaultBucketSettings; ...@@ -30,16 +29,14 @@ import com.couchbase.client.java.cluster.DefaultBucketSettings;
import com.couchbase.client.java.cluster.UserRole; import com.couchbase.client.java.cluster.UserRole;
import com.couchbase.client.java.cluster.UserSettings; import com.couchbase.client.java.cluster.UserSettings;
import com.couchbase.client.java.env.CouchbaseEnvironment; import com.couchbase.client.java.env.CouchbaseEnvironment;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.CouchbaseContainer; import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; 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.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -59,7 +56,12 @@ class CouchbaseAutoConfigurationIntegrationTests { ...@@ -59,7 +56,12 @@ class CouchbaseAutoConfigurationIntegrationTests {
static final CouchbaseContainer couchbase = new CouchbaseContainer().withClusterAdmin("spring", "password") static final CouchbaseContainer couchbase = new CouchbaseContainer().withClusterAdmin("spring", "password")
.withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10)); .withStartupAttempts(5).withStartupTimeout(Duration.ofMinutes(10));
private AnnotationConfigApplicationContext context; private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(CouchbaseAutoConfiguration.class))
.withPropertyValues("spring.couchbase.bootstrap-hosts=localhost",
"spring.couchbase.env.bootstrap.http-direct-port:" + couchbase.getMappedPort(8091),
"spring.couchbase.username:spring", "spring.couchbase.password:password",
"spring.couchbase.bucket.name:default");
@BeforeAll @BeforeAll
static void createBucket() { static void createBucket() {
...@@ -70,40 +72,10 @@ class CouchbaseAutoConfigurationIntegrationTests { ...@@ -70,40 +72,10 @@ class CouchbaseAutoConfigurationIntegrationTests {
UserSettings.build().password(bucketSettings.password()).roles(userSettings), true); UserSettings.build().password(bucketSettings.password()).roles(userSettings), true);
} }
@BeforeEach
void setUp() {
this.context = new AnnotationConfigApplicationContext();
this.context.register(CouchbaseAutoConfiguration.class);
TestPropertyValues.of("spring.couchbase.bootstrap-hosts=localhost",
"spring.couchbase.env.bootstrap.http-direct-port:" + couchbase.getMappedPort(8091),
"spring.couchbase.username:spring", "spring.couchbase.password:password",
"spring.couchbase.bucket.name:default").applyTo(this.context.getEnvironment());
}
@AfterEach
void close() {
if (this.context != null) {
this.context.close();
}
}
@Test @Test
void defaultConfiguration() { void defaultConfiguration() {
this.context.refresh(); this.contextRunner.run((context) -> assertThat(context).hasSingleBean(CouchbaseEnvironment.class)
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(1); .hasSingleBean(Cluster.class).hasSingleBean(ClusterInfo.class).hasSingleBean(Bucket.class));
assertThat(this.context.getBeansOfType(ClusterInfo.class)).hasSize(1);
assertThat(this.context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(1);
}
@Test
void customConfiguration() {
this.context.register(CustomConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeansOfType(Cluster.class)).hasSize(2);
assertThat(this.context.getBeansOfType(ClusterInfo.class)).hasSize(1);
assertThat(this.context.getBeansOfType(CouchbaseEnvironment.class)).hasSize(1);
assertThat(this.context.getBeansOfType(Bucket.class)).hasSize(2);
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
...@@ -116,7 +88,7 @@ class CouchbaseAutoConfigurationIntegrationTests { ...@@ -116,7 +88,7 @@ class CouchbaseAutoConfigurationIntegrationTests {
@Bean @Bean
Bucket myCustomCouchbaseClient() { Bucket myCustomCouchbaseClient() {
return mock(CouchbaseBucket.class); return mock(Bucket.class);
} }
} }
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -18,22 +18,17 @@ package org.springframework.boot.autoconfigure.couchbase; ...@@ -18,22 +18,17 @@ package org.springframework.boot.autoconfigure.couchbase;
import java.util.function.Consumer; import java.util.function.Consumer;
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseBucket;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.CouchbaseEnvironment; import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/** /**
* Tests for {@link CouchbaseAutoConfiguration}. * Tests for {@link CouchbaseAutoConfiguration}.
...@@ -43,38 +38,25 @@ import static org.mockito.Mockito.mock; ...@@ -43,38 +38,25 @@ import static org.mockito.Mockito.mock;
*/ */
class CouchbaseAutoConfigurationTests { class CouchbaseAutoConfigurationTests {
private ApplicationContextRunner contextRunner = new ApplicationContextRunner().withConfiguration( private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
AutoConfigurations.of(PropertyPlaceholderAutoConfiguration.class, CouchbaseAutoConfiguration.class)); .withConfiguration(AutoConfigurations.of(CouchbaseAutoConfiguration.class));
@Test @Test
void bootstrapHostsIsRequired() { void bootstrapHostsIsRequired() {
this.contextRunner.run(this::assertNoCouchbaseBeans); this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseEnvironment.class)
.doesNotHaveBean(Cluster.class));
} }
@Test @Test
void bootstrapHostsNotRequiredIfCouchbaseConfigurerIsSet() { void bootstrapHostsCreateEnvironmentAndCluster() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class).run((context) -> { this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
assertThat(context).hasSingleBean(CouchbaseTestConfigurer.class); .withPropertyValues("spring.couchbase.bootstrap-hosts=localhost").run((context) -> {
// No beans are going to be created assertThat(context).hasSingleBean(CouchbaseEnvironment.class).hasSingleBean(Cluster.class);
assertNoCouchbaseBeans(context); assertThat(context.getBean(Cluster.class))
}); .isSameAs(context.getBean(CouchbaseTestConfiguration.class).couchbaseCluster());
}
@Test
void bootstrapHostsIgnoredIfCouchbaseConfigurerIsSet() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class)
.withPropertyValues("spring.couchbase.bootstrapHosts=localhost").run((context) -> {
assertThat(context).hasSingleBean(CouchbaseTestConfigurer.class);
assertNoCouchbaseBeans(context);
}); });
} }
private void assertNoCouchbaseBeans(AssertableApplicationContext context) {
// No beans are going to be created
assertThat(context).doesNotHaveBean(CouchbaseEnvironment.class).doesNotHaveBean(ClusterInfo.class)
.doesNotHaveBean(Cluster.class).doesNotHaveBean(Bucket.class);
}
@Test @Test
void customizeEnvEndpoints() { void customizeEnvEndpoints() {
testCouchbaseEnv((env) -> { testCouchbaseEnv((env) -> {
...@@ -147,53 +129,32 @@ class CouchbaseAutoConfigurationTests { ...@@ -147,53 +129,32 @@ class CouchbaseAutoConfigurationTests {
} }
private void testCouchbaseEnv(Consumer<DefaultCouchbaseEnvironment> environmentConsumer, String... environment) { private void testCouchbaseEnv(Consumer<DefaultCouchbaseEnvironment> environmentConsumer, String... environment) {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class).withPropertyValues(environment) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.run((context) -> { .withPropertyValues("spring.couchbase.bootstrap-hosts=localhost").withPropertyValues(environment)
CouchbaseProperties properties = context.getBean(CouchbaseProperties.class); .run((context) -> environmentConsumer.accept(context.getBean(DefaultCouchbaseEnvironment.class)));
DefaultCouchbaseEnvironment env = new CouchbaseConfiguration(properties)
.initializeEnvironmentBuilder(properties).build();
environmentConsumer.accept(env);
});
} }
@Test @Test
void customizeEnvWithCustomCouchbaseConfiguration() { void customizeEnvWithCustomCouchbaseConfiguration() {
this.contextRunner.withUserConfiguration(CustomCouchbaseConfiguration.class) this.contextRunner
.withUserConfiguration(CouchbaseTestConfiguration.class,
CouchbaseEnvironmentCustomizerConfiguration.class)
.withPropertyValues("spring.couchbase.bootstrap-hosts=localhost", .withPropertyValues("spring.couchbase.bootstrap-hosts=localhost",
"spring.couchbase.env.timeouts.connect=100") "spring.couchbase.env.timeouts.connect=100")
.run((context) -> { .run((context) -> {
assertThat(context).hasSingleBean(CouchbaseConfiguration.class); assertThat(context).hasSingleBean(DefaultCouchbaseEnvironment.class);
DefaultCouchbaseEnvironment env = context.getBean(DefaultCouchbaseEnvironment.class); DefaultCouchbaseEnvironment env = context.getBean(DefaultCouchbaseEnvironment.class);
assertThat(env.socketConnectTimeout()).isEqualTo(5000); assertThat(env.socketConnectTimeout()).isEqualTo(5000);
assertThat(env.connectTimeout()).isEqualTo(2000); assertThat(env.connectTimeout()).isEqualTo(2000);
}); });
} }
@Configuration @Configuration(proxyBeanMethods = false)
static class CustomCouchbaseConfiguration extends CouchbaseConfiguration { static class CouchbaseEnvironmentCustomizerConfiguration {
CustomCouchbaseConfiguration(CouchbaseProperties properties) {
super(properties);
}
@Override
protected DefaultCouchbaseEnvironment.Builder initializeEnvironmentBuilder(CouchbaseProperties properties) {
return super.initializeEnvironmentBuilder(properties).socketConnectTimeout(5000).connectTimeout(2000);
}
@Override
public Cluster couchbaseCluster() {
return mock(Cluster.class);
}
@Override
public ClusterInfo couchbaseClusterInfo() {
return mock(ClusterInfo.class);
}
@Override @Bean
public Bucket couchbaseClient() { CouchbaseEnvironmentBuilderCustomizer couchbaseEnvironmentBuilderCustomizer() {
return mock(CouchbaseBucket.class); return (builder) -> builder.socketConnectTimeout(5000).connectTimeout(2000);
} }
} }
......
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2020 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
...@@ -20,37 +20,33 @@ import com.couchbase.client.java.Bucket; ...@@ -20,37 +20,33 @@ import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.CouchbaseBucket; import com.couchbase.client.java.CouchbaseBucket;
import com.couchbase.client.java.cluster.ClusterInfo; import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import org.springframework.data.couchbase.config.CouchbaseConfigurer; import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component; import org.springframework.context.annotation.Configuration;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
/** /**
* Test configurer for couchbase that mocks access. * Test configuration for couchbase that mocks access.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
*/ */
@Component @Configuration(proxyBeanMethods = false)
public class CouchbaseTestConfigurer implements CouchbaseConfigurer { public class CouchbaseTestConfiguration {
@Override private final Cluster cluster = mock(Cluster.class);
public CouchbaseEnvironment couchbaseEnvironment() throws Exception {
return mock(CouchbaseEnvironment.class);
}
@Override @Bean
public Cluster couchbaseCluster() throws Exception { public Cluster couchbaseCluster() {
return mock(Cluster.class); return this.cluster;
} }
@Override @Bean
public ClusterInfo couchbaseClusterInfo() { public ClusterInfo couchbaseClusterInfo() {
return mock(ClusterInfo.class); return mock(ClusterInfo.class);
} }
@Override @Bean
public Bucket couchbaseClient() { public Bucket couchbaseClient() {
return mock(CouchbaseBucket.class); return mock(CouchbaseBucket.class);
} }
......
...@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test; ...@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties; import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.couchbase.city.City; import org.springframework.boot.autoconfigure.data.couchbase.city.City;
import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
...@@ -33,12 +33,11 @@ import org.springframework.context.annotation.Bean; ...@@ -33,12 +33,11 @@ import org.springframework.context.annotation.Bean;
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.core.convert.converter.Converter; import org.springframework.core.convert.converter.Converter;
import org.springframework.data.couchbase.config.AbstractCouchbaseDataConfiguration;
import org.springframework.data.couchbase.config.BeanNames; import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
import org.springframework.data.couchbase.core.CouchbaseTemplate; import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions; import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.convert.DefaultCouchbaseTypeMapper; import org.springframework.data.couchbase.core.convert.DefaultCouchbaseTypeMapper;
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener;
import org.springframework.data.couchbase.core.query.Consistency; import org.springframework.data.couchbase.core.query.Consistency;
...@@ -60,26 +59,17 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -60,26 +59,17 @@ class CouchbaseDataAutoConfigurationTests {
@Test @Test
void disabledIfCouchbaseIsNotConfigured() { void disabledIfCouchbaseIsNotConfigured() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(IndexManager.class)); this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(CouchbaseTemplate.class));
}
@Test
void customConfiguration() {
this.contextRunner.withUserConfiguration(CustomCouchbaseConfiguration.class).run((context) -> {
CouchbaseTemplate couchbaseTemplate = context.getBean(CouchbaseTemplate.class);
assertThat(couchbaseTemplate.getDefaultConsistency()).isEqualTo(Consistency.STRONGLY_CONSISTENT);
});
} }
@Test @Test
void validatorIsPresent() { void validatorIsPresent() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.run((context) -> assertThat(context).hasSingleBean(ValidatingCouchbaseEventListener.class));
.run((context) -> assertThat(context).hasSingleBean(ValidatingCouchbaseEventListener.class));
} }
@Test @Test
void autoIndexIsDisabledByDefault() { void autoIndexIsDisabledByDefault() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class).run((context) -> { this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class).run((context) -> {
IndexManager indexManager = context.getBean(IndexManager.class); IndexManager indexManager = context.getBean(IndexManager.class);
assertThat(indexManager.isIgnoreViews()).isTrue(); assertThat(indexManager.isIgnoreViews()).isTrue();
assertThat(indexManager.isIgnoreN1qlPrimary()).isTrue(); assertThat(indexManager.isIgnoreN1qlPrimary()).isTrue();
...@@ -89,7 +79,7 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -89,7 +79,7 @@ class CouchbaseDataAutoConfigurationTests {
@Test @Test
void enableAutoIndex() { void enableAutoIndex() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.withPropertyValues("spring.data.couchbase.auto-index=true").run((context) -> { .withPropertyValues("spring.data.couchbase.auto-index=true").run((context) -> {
IndexManager indexManager = context.getBean(IndexManager.class); IndexManager indexManager = context.getBean(IndexManager.class);
assertThat(indexManager.isIgnoreViews()).isFalse(); assertThat(indexManager.isIgnoreViews()).isFalse();
...@@ -100,11 +90,10 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -100,11 +90,10 @@ class CouchbaseDataAutoConfigurationTests {
@Test @Test
void changeConsistency() { void changeConsistency() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.withPropertyValues("spring.data.couchbase.consistency=eventually-consistent").run((context) -> { .withPropertyValues("spring.data.couchbase.consistency=eventually-consistent").run((context) -> {
SpringBootCouchbaseDataConfiguration configuration = context CouchbaseTemplate couchbaseTemplate = context.getBean(CouchbaseTemplate.class);
.getBean(SpringBootCouchbaseDataConfiguration.class); assertThat(couchbaseTemplate.getDefaultConsistency()).isEqualTo(Consistency.EVENTUALLY_CONSISTENT);
assertThat(configuration.getDefaultConsistency()).isEqualTo(Consistency.EVENTUALLY_CONSISTENT);
}); });
} }
...@@ -121,16 +110,16 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -121,16 +110,16 @@ class CouchbaseDataAutoConfigurationTests {
@Test @Test
void typeKeyDefault() { void typeKeyDefault() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.run((context) -> assertThat(context.getBean(AbstractCouchbaseDataConfiguration.class).typeKey()) .run((context) -> assertThat(context.getBean(MappingCouchbaseConverter.class).getTypeKey())
.isEqualTo(DefaultCouchbaseTypeMapper.DEFAULT_TYPE_KEY)); .isEqualTo(DefaultCouchbaseTypeMapper.DEFAULT_TYPE_KEY));
} }
@Test @Test
void typeKeyCanBeCustomized() { void typeKeyCanBeCustomized() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.withPropertyValues("spring.data.couchbase.type-key=_custom") .withPropertyValues("spring.data.couchbase.type-key=_custom")
.run((context) -> assertThat(context.getBean(AbstractCouchbaseDataConfiguration.class).typeKey()) .run((context) -> assertThat(context.getBean(MappingCouchbaseConverter.class).getTypeKey())
.isEqualTo("_custom")); .isEqualTo("_custom"));
} }
...@@ -144,23 +133,8 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -144,23 +133,8 @@ class CouchbaseDataAutoConfigurationTests {
}); });
} }
@Configuration
static class CustomCouchbaseConfiguration extends AbstractCouchbaseDataConfiguration {
@Override
protected CouchbaseConfigurer couchbaseConfigurer() {
return new CouchbaseTestConfigurer();
}
@Override
protected Consistency getDefaultConsistency() {
return Consistency.STRONGLY_CONSISTENT;
}
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class CustomConversionsConfig { static class CustomConversionsConfig {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS) @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
...@@ -172,7 +146,7 @@ class CouchbaseDataAutoConfigurationTests { ...@@ -172,7 +146,7 @@ class CouchbaseDataAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EntityScan("org.springframework.boot.autoconfigure.data.couchbase.city") @EntityScan("org.springframework.boot.autoconfigure.data.couchbase.city")
@Import(CustomCouchbaseConfiguration.class) @Import(CouchbaseTestConfiguration.class)
static class EntityScanConfig { static class EntityScanConfig {
} }
......
...@@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test; ...@@ -23,7 +23,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.couchbase.city.CityRepository; import org.springframework.boot.autoconfigure.data.couchbase.city.CityRepository;
import org.springframework.boot.autoconfigure.data.couchbase.city.ReactiveCityRepository; import org.springframework.boot.autoconfigure.data.couchbase.city.ReactiveCityRepository;
import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.boot.test.context.runner.ApplicationContextRunner;
...@@ -62,7 +62,7 @@ class CouchbaseReactiveAndImperativeRepositoriesAutoConfigurationTests { ...@@ -62,7 +62,7 @@ class CouchbaseReactiveAndImperativeRepositoriesAutoConfigurationTests {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Import({ CouchbaseTestConfigurer.class, Registrar.class }) @Import({ CouchbaseTestConfiguration.class, Registrar.class })
static class BaseConfiguration { static class BaseConfiguration {
} }
......
...@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test; ...@@ -24,7 +24,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties; import org.springframework.boot.autoconfigure.couchbase.CouchbaseProperties;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.couchbase.city.City; import org.springframework.boot.autoconfigure.data.couchbase.city.City;
import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration; import org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration;
...@@ -33,15 +33,11 @@ import org.springframework.context.annotation.Bean; ...@@ -33,15 +33,11 @@ import org.springframework.context.annotation.Bean;
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.core.convert.converter.Converter; 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.BeanNames;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;
import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate; import org.springframework.data.couchbase.core.RxJavaCouchbaseTemplate;
import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions; import org.springframework.data.couchbase.core.convert.CouchbaseCustomConversions;
import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext; import org.springframework.data.couchbase.core.mapping.CouchbaseMappingContext;
import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener; 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 org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
...@@ -60,20 +56,12 @@ class CouchbaseReactiveDataAutoConfigurationTests { ...@@ -60,20 +56,12 @@ class CouchbaseReactiveDataAutoConfigurationTests {
@Test @Test
void disabledIfCouchbaseIsNotConfigured() { void disabledIfCouchbaseIsNotConfigured() {
this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(IndexManager.class)); this.contextRunner.run((context) -> assertThat(context).doesNotHaveBean(RxJavaCouchbaseTemplate.class));
}
@Test
void customConfiguration() {
this.contextRunner.withUserConfiguration(CustomCouchbaseConfiguration.class).run((context) -> {
RxJavaCouchbaseTemplate rxJavaCouchbaseTemplate = context.getBean(RxJavaCouchbaseTemplate.class);
assertThat(rxJavaCouchbaseTemplate.getDefaultConsistency()).isEqualTo(Consistency.STRONGLY_CONSISTENT);
});
} }
@Test @Test
void validatorIsPresent() { void validatorIsPresent() {
this.contextRunner.withUserConfiguration(CouchbaseTestConfigurer.class) this.contextRunner.withUserConfiguration(CouchbaseTestConfiguration.class)
.run((context) -> assertThat(context).hasSingleBean(ValidatingCouchbaseEventListener.class)); .run((context) -> assertThat(context).hasSingleBean(ValidatingCouchbaseEventListener.class));
} }
...@@ -98,23 +86,8 @@ class CouchbaseReactiveDataAutoConfigurationTests { ...@@ -98,23 +86,8 @@ class CouchbaseReactiveDataAutoConfigurationTests {
}); });
} }
@Configuration
static class CustomCouchbaseConfiguration extends AbstractReactiveCouchbaseDataConfiguration {
@Override
protected CouchbaseConfigurer couchbaseConfigurer() {
return new CouchbaseTestConfigurer();
}
@Override
protected Consistency getDefaultConsistency() {
return Consistency.STRONGLY_CONSISTENT;
}
}
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class CustomConversionsConfig { static class CustomConversionsConfig {
@Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS) @Bean(BeanNames.COUCHBASE_CUSTOM_CONVERSIONS)
...@@ -126,7 +99,7 @@ class CouchbaseReactiveDataAutoConfigurationTests { ...@@ -126,7 +99,7 @@ class CouchbaseReactiveDataAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@EntityScan("org.springframework.boot.autoconfigure.data.couchbase.city") @EntityScan("org.springframework.boot.autoconfigure.data.couchbase.city")
@Import(CustomCouchbaseConfiguration.class) @Import(CouchbaseTestConfiguration.class)
static class EntityScanConfig { static class EntityScanConfig {
} }
......
...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test; ...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.alt.couchbase.CityCouchbaseRepository; import org.springframework.boot.autoconfigure.data.alt.couchbase.CityCouchbaseRepository;
import org.springframework.boot.autoconfigure.data.alt.couchbase.ReactiveCityCouchbaseRepository; 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.City;
...@@ -86,14 +86,14 @@ class CouchbaseReactiveRepositoriesAutoConfigurationTests { ...@@ -86,14 +86,14 @@ class CouchbaseReactiveRepositoriesAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class DefaultConfiguration { static class DefaultConfiguration {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class) @TestAutoConfigurationPackage(EmptyDataPackage.class)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class NoRepositoryConfiguration { static class NoRepositoryConfiguration {
} }
...@@ -101,7 +101,7 @@ class CouchbaseReactiveRepositoriesAutoConfigurationTests { ...@@ -101,7 +101,7 @@ class CouchbaseReactiveRepositoriesAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(CouchbaseReactiveRepositoriesAutoConfigurationTests.class) @TestAutoConfigurationPackage(CouchbaseReactiveRepositoriesAutoConfigurationTests.class)
@EnableCouchbaseRepositories(basePackageClasses = CityCouchbaseRepository.class) @EnableCouchbaseRepositories(basePackageClasses = CityCouchbaseRepository.class)
@Import(CouchbaseDataAutoConfigurationTests.CustomCouchbaseConfiguration.class) @Import(CouchbaseTestConfiguration.class)
static class CustomizedConfiguration { static class CustomizedConfiguration {
} }
......
...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test; ...@@ -21,7 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration; import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfigurer; import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.couchbase.city.City; import org.springframework.boot.autoconfigure.data.couchbase.city.City;
import org.springframework.boot.autoconfigure.data.couchbase.city.CityRepository; import org.springframework.boot.autoconfigure.data.couchbase.city.CityRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
...@@ -82,14 +82,14 @@ class CouchbaseRepositoriesAutoConfigurationTests { ...@@ -82,14 +82,14 @@ class CouchbaseRepositoriesAutoConfigurationTests {
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(City.class) @TestAutoConfigurationPackage(City.class)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class DefaultConfiguration { static class DefaultConfiguration {
} }
@Configuration(proxyBeanMethods = false) @Configuration(proxyBeanMethods = false)
@TestAutoConfigurationPackage(EmptyDataPackage.class) @TestAutoConfigurationPackage(EmptyDataPackage.class)
@Import(CouchbaseTestConfigurer.class) @Import(CouchbaseTestConfiguration.class)
static class NoRepositoryConfiguration { static class NoRepositoryConfiguration {
} }
......
...@@ -4485,7 +4485,6 @@ Generally, you provide the bootstrap hosts, bucket name, and password, as shown ...@@ -4485,7 +4485,6 @@ Generally, you provide the bootstrap hosts, bucket name, and password, as shown
---- ----
TIP: You need to provide _at least_ the bootstrap host(s), in which case the bucket name is `default` and the password is an empty String. TIP: You need to provide _at least_ the bootstrap host(s), in which case the bucket name is `default` and the password is an empty String.
Alternatively, you can define your own `org.springframework.data.couchbase.config.CouchbaseConfigurer` `@Bean` to take control over the whole configuration.
It is also possible to customize some of the `CouchbaseEnvironment` settings. It is also possible to customize some of the `CouchbaseEnvironment` settings.
For instance, the following configuration changes the timeout to use to open a new `Bucket` and enables SSL support: For instance, the following configuration changes the timeout to use to open a new `Bucket` and enables SSL support:
...@@ -4497,7 +4496,8 @@ For instance, the following configuration changes the timeout to use to open a n ...@@ -4497,7 +4496,8 @@ For instance, the following configuration changes the timeout to use to open a n
spring.couchbase.env.ssl.key-store-password=secret spring.couchbase.env.ssl.key-store-password=secret
---- ----
Check the `spring.couchbase.env.*` properties for more details. TIP: Check the `spring.couchbase.env.*` properties for more details.
To take more control, one or more `CouchbaseEnvironmentBuilderCustomizer` beans can be used.
......
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