Commit fa84b179 authored by Stephane Nicoll's avatar Stephane Nicoll

Allow to customize the Couchbase environment

Closes gh-5403
parent caf11e44
...@@ -64,7 +64,7 @@ public class CouchbaseAutoConfiguration { ...@@ -64,7 +64,7 @@ public class CouchbaseAutoConfiguration {
@Bean @Bean
@Primary @Primary
public CouchbaseEnvironment couchbaseEnvironment() throws Exception { public CouchbaseEnvironment couchbaseEnvironment() throws Exception {
return DefaultCouchbaseEnvironment.create(); return createEnvironment(this.properties);
} }
@Bean @Bean
...@@ -88,6 +88,35 @@ public class CouchbaseAutoConfiguration { ...@@ -88,6 +88,35 @@ public class CouchbaseAutoConfiguration {
this.properties.getBucket().getPassword()); this.properties.getBucket().getPassword());
} }
/**
* Create a {@link CouchbaseEnvironment} based on the specified settings.
* @param properties the couchbase properties to use
* @return a {@link CouchbaseEnvironment}
*/
protected CouchbaseEnvironment createEnvironment(CouchbaseProperties properties) {
CouchbaseProperties.Endpoints endpoints = properties.getEnv().getEndpoints();
CouchbaseProperties.Timeouts timeouts = properties.getEnv().getTimeouts();
DefaultCouchbaseEnvironment.Builder builder = DefaultCouchbaseEnvironment.builder()
.connectTimeout(timeouts.getConnect())
.kvEndpoints(endpoints.getKeyValue())
.kvTimeout(timeouts.getKeyValue())
.queryEndpoints(endpoints.getQuery())
.queryTimeout(timeouts.getQuery())
.viewEndpoints(endpoints.getView())
.viewTimeout(timeouts.getView());
CouchbaseProperties.Ssl ssl = properties.getEnv().getSsl();
if (ssl.getEnabled()) {
builder.sslEnabled(true);
if (ssl.getKeyStore() != null) {
builder.sslKeystoreFile(ssl.getKeyStore());
}
if (ssl.getKeyStorePassword() != null) {
builder.sslKeystorePassword(ssl.getKeyStorePassword());
}
}
return builder.build();
}
} }
/** /**
......
...@@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.couchbase; ...@@ -19,6 +19,8 @@ package org.springframework.boot.autoconfigure.couchbase;
import java.util.List; import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.util.StringUtils;
/** /**
* Configuration properties for Couchbase. * Configuration properties for Couchbase.
...@@ -37,6 +39,8 @@ public class CouchbaseProperties { ...@@ -37,6 +39,8 @@ public class CouchbaseProperties {
private final Bucket bucket = new Bucket(); private final Bucket bucket = new Bucket();
private final Env env = new Env();
public List<String> getBootstrapHosts() { public List<String> getBootstrapHosts() {
return this.bootstrapHosts; return this.bootstrapHosts;
} }
...@@ -49,7 +53,12 @@ public class CouchbaseProperties { ...@@ -49,7 +53,12 @@ public class CouchbaseProperties {
return this.bucket; return this.bucket;
} }
static class Bucket { public Env getEnv() {
return this.env;
}
public static class Bucket {
/** /**
* Name of the bucket to connect to. * Name of the bucket to connect to.
...@@ -79,4 +88,172 @@ public class CouchbaseProperties { ...@@ -79,4 +88,172 @@ public class CouchbaseProperties {
} }
public static class Env {
@NestedConfigurationProperty
private final Endpoints endpoints = new Endpoints();
@NestedConfigurationProperty
private final Ssl ssl = new Ssl();
@NestedConfigurationProperty
private final Timeouts timeouts = new Timeouts();
public Endpoints getEndpoints() {
return this.endpoints;
}
public Ssl getSsl() {
return this.ssl;
}
public Timeouts getTimeouts() {
return this.timeouts;
}
}
public static class Endpoints {
/**
* Number of sockets per node against the Key/value service.
*/
private int keyValue = 1;
/**
* Number of sockets per node against the Query (N1QL) service.
*/
private int query = 1;
/**
* Number of sockets per node against the view service.
*/
private int view = 1;
public int getKeyValue() {
return this.keyValue;
}
public void setKeyValue(int keyValue) {
this.keyValue = keyValue;
}
public int getQuery() {
return this.query;
}
public void setQuery(int query) {
this.query = query;
}
public int getView() {
return this.view;
}
public void setView(int view) {
this.view = view;
}
}
public static class Ssl {
/**
* Enable SSL support. Enabled automatically if a "keyStore" is provided unless
* specified otherwise.
*/
private Boolean enabled;
/**
* Path to the JVM key store that holds the certificates.
*/
private String keyStore;
/**
* Password used to access the key store.
*/
private String keyStorePassword;
public Boolean getEnabled() {
return (this.enabled != null ? this.enabled : StringUtils.hasText(this.keyStore));
}
public void setEnabled(Boolean enabled) {
this.enabled = enabled;
}
public String getKeyStore() {
return this.keyStore;
}
public void setKeyStore(String keyStore) {
this.keyStore = keyStore;
}
public String getKeyStorePassword() {
return this.keyStorePassword;
}
public void setKeyStorePassword(String keyStorePassword) {
this.keyStorePassword = keyStorePassword;
}
}
public static class Timeouts {
/**
* Bucket connections timeout in milliseconds.
*/
private long connect = 5000;
/**
* Blocking operations performed on a specific key timeout in milliseconds.
*/
private long keyValue = 2500;
/**
* N1QL query operations timeout in milliseconds.
*/
private long query = 7500;
/**
* Regular and geospatial view operations timeout in milliseconds.
*/
private long view = 7500;
public long getConnect() {
return this.connect;
}
public void setConnect(long connect) {
this.connect = connect;
}
public long getKeyValue() {
return this.keyValue;
}
public void setKeyValue(long keyValue) {
this.keyValue = keyValue;
}
public long getQuery() {
return this.query;
}
public void setQuery(long query) {
this.query = query;
}
public long getView() {
return this.view;
}
public void setView(long view) {
this.view = view;
}
}
} }
...@@ -20,6 +20,7 @@ import com.couchbase.client.java.Bucket; ...@@ -20,6 +20,7 @@ import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.Cluster; import com.couchbase.client.java.Cluster;
import com.couchbase.client.java.cluster.ClusterInfo; 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.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.ExpectedException; import org.junit.rules.ExpectedException;
...@@ -58,7 +59,6 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig ...@@ -58,7 +59,6 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig
assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class)) assertThat(this.context.getBeansOfType(CouchbaseTestConfigurer.class))
.hasSize(1); .hasSize(1);
assertNoCouchbaseBeans(); assertNoCouchbaseBeans();
} }
private void assertNoCouchbaseBeans() { private void assertNoCouchbaseBeans() {
...@@ -69,4 +69,56 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig ...@@ -69,4 +69,56 @@ public class CouchbaseAutoConfigurationTests extends AbstractCouchbaseAutoConfig
assertThat(this.context.getBeansOfType(Bucket.class)).isEmpty(); assertThat(this.context.getBeansOfType(Bucket.class)).isEmpty();
} }
@Test
public void customizeEnvEndpoints() throws Exception {
DefaultCouchbaseEnvironment env = customizeEnv(
"spring.couchbase.env.endpoints.keyValue=4",
"spring.couchbase.env.endpoints.query=5",
"spring.couchbase.env.endpoints.view=6");
assertThat(env.kvEndpoints()).isEqualTo(4);
assertThat(env.queryEndpoints()).isEqualTo(5);
assertThat(env.viewEndpoints()).isEqualTo(6);
}
@Test
public void customizeEnvTimeouts() throws Exception {
DefaultCouchbaseEnvironment env = customizeEnv(
"spring.couchbase.env.timeouts.connect=100",
"spring.couchbase.env.timeouts.keyValue=200",
"spring.couchbase.env.timeouts.query=300",
"spring.couchbase.env.timeouts.view=400");
assertThat(env.connectTimeout()).isEqualTo(100);
assertThat(env.kvTimeout()).isEqualTo(200);
assertThat(env.queryTimeout()).isEqualTo(300);
assertThat(env.viewTimeout()).isEqualTo(400);
}
@Test
public void enableSslNoEnabledFlag() throws Exception {
DefaultCouchbaseEnvironment env = customizeEnv(
"spring.couchbase.env.ssl.keyStore=foo",
"spring.couchbase.env.ssl.keyStorePassword=secret");
assertThat(env.sslEnabled()).isTrue();
assertThat(env.sslKeystoreFile()).isEqualTo("foo");
assertThat(env.sslKeystorePassword()).isEqualTo("secret");
}
@Test
public void disableSslEvenWithKeyStore() throws Exception {
DefaultCouchbaseEnvironment env = customizeEnv(
"spring.couchbase.env.ssl.enabled=false",
"spring.couchbase.env.ssl.keyStore=foo",
"spring.couchbase.env.ssl.keyStorePassword=secret");
assertThat(env.sslEnabled()).isFalse();
assertThat(env.sslKeystoreFile()).isNull();
assertThat(env.sslKeystorePassword()).isNull();
}
private DefaultCouchbaseEnvironment customizeEnv(String... environment) throws Exception {
load(CouchbaseTestConfigurer.class, environment);
CouchbaseProperties properties = this.context.getBean(CouchbaseProperties.class);
return (DefaultCouchbaseEnvironment) new CouchbaseAutoConfiguration.CouchbaseConfiguration(properties)
.couchbaseEnvironment();
}
} }
...@@ -478,6 +478,16 @@ content into your application; rather pick only the properties that you need. ...@@ -478,6 +478,16 @@ content into your application; rather pick only the properties that you need.
spring.couchbase.bootstrap-hosts= # Couchbase nodes (host or IP address) to bootstrap from. spring.couchbase.bootstrap-hosts= # Couchbase nodes (host or IP address) to bootstrap from.
spring.couchbase.bucket.name=default # Name of the bucket to connect to. spring.couchbase.bucket.name=default # Name of the bucket to connect to.
spring.couchbase.bucket.password= # Password of the bucket. spring.couchbase.bucket.password= # Password of the bucket.
spring.couchbase.env.endpoints.key-value=1 # Number of sockets per node against the Key/value service.
spring.couchbase.env.endpoints.query=1 # Number of sockets per node against the Query (N1QL) service.
spring.couchbase.env.endpoints.view=1 # Number of sockets per node against the view service.
spring.couchbase.env.ssl.enabled= # Enable SSL support. Enabled automatically if a "keyStore" is provided unless specified otherwise.
spring.couchbase.env.ssl.key-store= # Path to the JVM key store that holds the certificates.
spring.couchbase.env.ssl.key-store-password= # Password used to access the key store.
spring.couchbase.env.timeouts.connect=5000 # Bucket connections timeout in milliseconds.
spring.couchbase.env.timeouts.key-value=2500 # Blocking operations performed on a specific key timeout in milliseconds.
spring.couchbase.env.timeouts.query=7500 # N1QL query operations timeout in milliseconds.
spring.couchbase.env.timeouts.view=7500 # Regular and geospatial view operations timeout in milliseconds.
# DAO ({sc-spring-boot-autoconfigure}/dao/PersistenceExceptionTranslationAutoConfiguration.{sc-ext}[PersistenceExceptionTranslationAutoConfiguration]) # DAO ({sc-spring-boot-autoconfigure}/dao/PersistenceExceptionTranslationAutoConfiguration.{sc-ext}[PersistenceExceptionTranslationAutoConfiguration])
spring.dao.exceptiontranslation.enabled=true # Enable the PersistenceExceptionTranslationPostProcessor. spring.dao.exceptiontranslation.enabled=true # Enable the PersistenceExceptionTranslationPostProcessor.
......
...@@ -3217,6 +3217,20 @@ own `org.springframework.data.couchbase.config.CouchbaseConfigurer` `@Bean` to t ...@@ -3217,6 +3217,20 @@ own `org.springframework.data.couchbase.config.CouchbaseConfigurer` `@Bean` to t
control over the whole configuration. control over the whole configuration.
==== ====
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 enable
SSL support:
[source,properties,indent=0]
----
spring.couchbase.env.timeouts.connect=3000
spring.couchbase.env.ssl.key-store=/location/of/keystore.jks
spring.couchbase.env.ssl.key-store-password=secret
----
Check the `spring.couchbase.env.*` properties for more details.
[[boot-features-spring-data-couchbase-repositories]] [[boot-features-spring-data-couchbase-repositories]]
==== Spring Data Couchbase repositories ==== Spring Data Couchbase repositories
Spring Data includes repository support for Couchbase. For complete details of Spring Spring Data includes repository support for Couchbase. For complete details of Spring
......
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