Skip to content

Commit

Permalink
Separate Couchbase setup from Spring Data
Browse files Browse the repository at this point in the history
This commit separates the basic setup of Couchbase from Spring Data so
that a `Bucket` and `Cluster` bucket beans are exposed even if Spring
Data is not available.

A basic setup happens if `spring.couchbase.bootstrap-hosts` is specified,
configuring the `default` bucket with no authentication unless specified
otherwise.

If Spring Data is available, those beans are re-used by default to
configure the `CouchbaseTemplate` and other repository-related beans.

Closes spring-projectsgh-5347
  • Loading branch information
snicoll committed Mar 14, 2016
1 parent 5fa752a commit e67f2e2
Show file tree
Hide file tree
Showing 20 changed files with 835 additions and 258 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@

package org.springframework.boot.autoconfigure.couchbase;

import java.util.List;

import javax.validation.Validator;

import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster;
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 org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
Expand All @@ -32,11 +34,8 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
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.context.annotation.Primary;
import org.springframework.data.couchbase.config.CouchbaseConfigurer;

/**
* {@link EnableAutoConfiguration Auto-Configuration} for Couchbase.
Expand All @@ -46,92 +45,68 @@
* @since 1.4.0
*/
@Configuration
@ConditionalOnClass({ CouchbaseBucket.class, AbstractCouchbaseConfiguration.class })
@ConditionalOnClass({CouchbaseBucket.class, Cluster.class})
@Conditional(CouchbaseAutoConfiguration.CouchbaseCondition.class)
@EnableConfigurationProperties(CouchbaseProperties.class)
public class CouchbaseAutoConfiguration {

@Configuration
@ConditionalOnClass(Validator.class)
public static class ValidationConfiguration {

@Bean
@ConditionalOnBean(Validator.class)
public ValidatingCouchbaseEventListener validationEventListener(
Validator validator) {
return new ValidatingCouchbaseEventListener(validator);
}

}

@Configuration
@ConditionalOnMissingBean(AbstractCouchbaseConfiguration.class)
public static class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
@ConditionalOnMissingBean(CouchbaseConfigurer.class)
public static class CouchbaseConfiguration {

private final CouchbaseProperties properties;

public CouchbaseConfiguration(CouchbaseProperties properties) {
this.properties = properties;
}

@Override
protected List<String> getBootstrapHosts() {
return this.properties.getBootstrapHosts();
}

@Override
protected String getBucketName() {
return this.properties.getBucket().getName();
}

@Override
protected String getBucketPassword() {
return this.properties.getBucket().getPassword();
@Bean
@Primary
public CouchbaseEnvironment couchbaseEnvironment() throws Exception {
return DefaultCouchbaseEnvironment.create();
}

@Override
protected Consistency getDefaultConsistency() {
return this.properties.getConsistency();
@Bean
@Primary
public Cluster couchbaseCluster() throws Exception {
return CouchbaseCluster.create(couchbaseEnvironment(),
this.properties.getBootstrapHosts());
}

@Override
@ConditionalOnMissingBean(name = "couchbaseTemplate")
@Bean(name = "couchbaseTemplate")
public CouchbaseTemplate couchbaseTemplate() throws Exception {
return super.couchbaseTemplate();
@Bean
@Primary
public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().clusterManager(this.properties.getBucket().getName(),
this.properties.getBucket().getPassword()).info();
}

@Override
@ConditionalOnMissingBean(name = "couchbaseIndexManager")
@Bean(name = "couchbaseIndexManager")
public IndexManager indexManager() {
if (this.properties.isAutoIndex()) {
return new IndexManager(true, true, true);
}
else {
return new IndexManager(false, false, false);
}
@Bean
@Primary
public Bucket couchbaseClient() throws Exception {
return couchbaseCluster().openBucket(this.properties.getBucket().getName(),
this.properties.getBucket().getPassword());
}

}

/**
* Determine if Couchbase should be configured. This happens if either the
* user-configuration defines a couchbase configuration or if at least the bucket name
* is specified.
* user-configuration defines a {@link CouchbaseConfigurer} or if at least
* the "bootstrapHosts" property is specified.
*/
static class CouchbaseCondition extends AnyNestedCondition {

CouchbaseCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}

@ConditionalOnProperty(prefix = "spring.data.couchbase.bucket", name = "name")
static class BucketNameProperty {
@ConditionalOnProperty(prefix = "spring.couchbase", name = "bootstrapHosts")
static class BootstrapHostsProperty {
}

@ConditionalOnBean(AbstractCouchbaseConfiguration.class)
static class CouchbaseConfiguration {
@ConditionalOnBean(CouchbaseConfigurer.class)
static class CouchbaseConfigurerAvailable {
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@

package org.springframework.boot.autoconfigure.couchbase;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.data.couchbase.core.query.Consistency;

/**
* Configuration properties for Couchbase.
Expand All @@ -30,36 +27,16 @@
* @author Stephane Nicoll
* @since 1.4.0
*/
@ConfigurationProperties(prefix = "spring.data.couchbase")
@ConfigurationProperties(prefix = "spring.couchbase")
public class CouchbaseProperties {

/**
* Automatically create views and indexes. Use the meta-data provided by
* "@ViewIndexed", "@N1qlPrimaryIndexed" and "@N1qlSecondaryIndexed".
*/
private boolean autoIndex;

/**
* Couchbase nodes (host or IP address) to bootstrap from.
*/
private List<String> bootstrapHosts = new ArrayList<String>(
Collections.singletonList("localhost"));
private List<String> bootstrapHosts;

private final Bucket bucket = new Bucket();

/**
* Consistency to apply by default on generated queries.
*/
private Consistency consistency = Consistency.READ_YOUR_OWN_WRITES;

public boolean isAutoIndex() {
return this.autoIndex;
}

public void setAutoIndex(boolean autoIndex) {
this.autoIndex = autoIndex;
}

public List<String> getBootstrapHosts() {
return this.bootstrapHosts;
}
Expand All @@ -72,20 +49,12 @@ public Bucket getBucket() {
return this.bucket;
}

public Consistency getConsistency() {
return this.consistency;
}

public void setConsistency(Consistency consistency) {
this.consistency = consistency;
}

static class Bucket {

/**
* Name of the bucket to connect to.
*/
private String name;
private String name = "default";

/**
* Password of the bucket.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright 2012-2016 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.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration.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
@ConditionalOnClass(CouchbaseConfigurer.class)
@ConditionalOnBean(CouchbaseConfiguration.class)
class CouchbaseConfigurerAdapterConfiguration {

private final CouchbaseConfiguration configuration;

CouchbaseConfigurerAdapterConfiguration(CouchbaseConfiguration configuration) {
this.configuration = configuration;
}

@Bean
@ConditionalOnMissingBean
public CouchbaseConfigurer springBootCouchbaseConfigurer() throws Exception {
return new SpringBootCouchbaseConfigurer(this.configuration.couchbaseEnvironment(),
this.configuration.couchbaseCluster(), this.configuration.couchbaseClusterInfo(),
this.configuration.couchbaseClient());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright 2012-2016 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 javax.validation.Validator;

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.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener;
import org.springframework.data.couchbase.repository.CouchbaseRepository;

/**
* {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Couchbase support.
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.4.0
*/
@Configuration
@ConditionalOnClass({Bucket.class, CouchbaseRepository.class})
@AutoConfigureAfter(CouchbaseAutoConfiguration.class)
@EnableConfigurationProperties(CouchbaseDataProperties.class)
@Import({ CouchbaseConfigurerAdapterConfiguration.class,
SpringBootCouchbaseDataConfiguration.class })
public class CouchbaseDataAutoConfiguration {

@Configuration
@ConditionalOnClass(Validator.class)
public static class ValidationConfiguration {

@Bean
@ConditionalOnBean(Validator.class)
public ValidatingCouchbaseEventListener validationEventListener(
Validator validator) {
return new ValidatingCouchbaseEventListener(validator);
}

}

}
Loading

0 comments on commit e67f2e2

Please sign in to comment.