Polish contribution

Closes gh-3499
pull/5128/head
Stephane Nicoll 9 years ago
parent 76f1ca4188
commit da3b49e024

@ -93,12 +93,13 @@ import org.springframework.mail.javamail.JavaMailSenderImpl;
*/
@Configuration
@AutoConfigureBefore({ EndpointAutoConfiguration.class })
@AutoConfigureAfter({ CouchbaseAutoConfiguration.class, CassandraAutoConfiguration.class,
CassandraDataAutoConfiguration.class, DataSourceAutoConfiguration.class,
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
RedisAutoConfiguration.class, RabbitAutoConfiguration.class,
SolrAutoConfiguration.class, MailSenderAutoConfiguration.class,
JmsAutoConfiguration.class, ElasticsearchAutoConfiguration.class })
@AutoConfigureAfter({ CassandraAutoConfiguration.class,
CassandraDataAutoConfiguration.class, CouchbaseAutoConfiguration.class,
DataSourceAutoConfiguration.class, MongoAutoConfiguration.class,
MongoDataAutoConfiguration.class, RedisAutoConfiguration.class,
RabbitAutoConfiguration.class, SolrAutoConfiguration.class,
MailSenderAutoConfiguration.class, JmsAutoConfiguration.class,
ElasticsearchAutoConfiguration.class })
@EnableConfigurationProperties({ HealthIndicatorAutoConfigurationProperties.class })
public class HealthIndicatorAutoConfiguration {

@ -22,6 +22,7 @@ import com.couchbase.client.java.util.features.Version;
import org.springframework.data.couchbase.core.CouchbaseOperations;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link HealthIndicator} for Couchbase.
@ -41,7 +42,7 @@ public class CouchbaseHealthIndicator extends AbstractHealthIndicator {
@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
List<Version> versions = this.couchbaseOperations.getCouchbaseClusterInfo().getAllVersions();
builder.up().withDetail("version", versions.get(0).toString());
builder.up().withDetail("versions", StringUtils.collectionToCommaDelimitedString(versions));
}
}

@ -16,7 +16,6 @@
package org.springframework.boot.autoconfigure.couchbase;
import java.util.Arrays;
import java.util.List;
import javax.validation.Validator;
@ -24,10 +23,14 @@ import javax.validation.Validator;
import com.couchbase.client.java.CouchbaseBucket;
import org.springframework.beans.factory.annotation.Autowired;
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.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
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.config.CouchbaseBucketFactoryBean;
@ -38,10 +41,12 @@ import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbase
* Auto-Configuration} for Couchbase.
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.4.0
*/
@Configuration
@ConditionalOnClass({ CouchbaseBucket.class, CouchbaseBucketFactoryBean.class })
@ConditionalOnClass({CouchbaseBucket.class, CouchbaseBucketFactoryBean.class})
@Conditional(CouchbaseAutoConfiguration.CouchbaseCondition.class)
@EnableConfigurationProperties(CouchbaseProperties.class)
public class CouchbaseAutoConfiguration {
@ -52,24 +57,44 @@ public class CouchbaseAutoConfiguration {
}
@Configuration
static class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
@ConditionalOnMissingBean(AbstractCouchbaseConfiguration.class)
public static class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
@Autowired
private CouchbaseProperties properties;
@Override
protected List<String> getBootstrapHosts() {
return Arrays.asList(this.properties.getHosts());
return this.properties.getBootstrapHosts();
}
@Override
protected String getBucketName() {
return this.properties.getBucketName();
return this.properties.getBucket().getName();
}
@Override
protected String getBucketPassword() {
return this.properties.getBucketPassword();
return 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.
*/
static class CouchbaseCondition extends AnyNestedCondition {
CouchbaseCondition() {
super(ConfigurationPhase.REGISTER_BEAN);
}
@ConditionalOnProperty(prefix = "spring.data.couchbase.bucket", name = "name")
static class BucketNameProperty {
}
@ConditionalOnBean(AbstractCouchbaseConfiguration.class)
static class CouchbaseConfiguration {
}
}

@ -16,54 +16,68 @@
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;
/**
* Configuration properties for Couchbase.
*
* @author Eddú Meléndez
* @author Stephane Nicoll
* @since 1.4.0
*/
@ConfigurationProperties(prefix = "spring.data.couchbase")
public class CouchbaseProperties {
/**
* Couchabase server hosts.
* Couchbase nodes (host or IP address) to bootstrap from.
*/
private String[] hosts;
private List<String> bootstrapHosts = new ArrayList<String>(Collections.singletonList("localhost"));
private final Bucket bucket = new Bucket();
public List<String> getBootstrapHosts() {
return this.bootstrapHosts;
}
public void setBootstrapHosts(List<String> bootstrapHosts) {
this.bootstrapHosts = bootstrapHosts;
}
public Bucket getBucket() {
return this.bucket;
}
static class Bucket {
/**
* Couchbase bucket name.
* Name of the bucket to connect to.
*/
private String bucketName;
private String name;
/**
* Couchbase bucket password.
* Password of the bucket.
*/
private String bucketPassword;
private String password = "";
public String[] getHosts() {
return this.hosts;
public String getName() {
return this.name;
}
public void setHosts(String[] hosts) {
this.hosts = hosts;
public void setName(String name) {
this.name = name;
}
public String getBucketName() {
return this.bucketName;
public String getPassword() {
return this.password;
}
public void setBucketName(String bucketName) {
this.bucketName = bucketName;
public void setPassword(String password) {
this.password = password;
}
public String getBucketPassword() {
return this.bucketPassword;
}
public void setBucketPassword(String bucketPassword) {
this.bucketPassword = bucketPassword;
}
}

@ -16,15 +16,27 @@
package org.springframework.boot.autoconfigure.couchbase;
import javax.validation.Validator;
import com.couchbase.client.java.Bucket;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link CouchbaseAutoConfiguration}
@ -46,17 +58,55 @@ public class CouchbaseAutoConfigurationTests {
}
@Test
public void validateProperties() {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.data.couchbase.hosts=localhost",
"spring.data.couchbase.bucket-name=test",
"spring.data.couchbase.bucket-password=test");
this.context.register(PropertyPlaceholderAutoConfiguration.class,
public void bucketNameIsRequired() {
load(null);
assertThat(this.context.getBeansOfType(CouchbaseTemplate.class)).isEmpty();
assertThat(this.context.getBeansOfType(Bucket.class)).isEmpty();
assertThat(this.context.getBeansOfType(ValidatingCouchbaseEventListener.class)).isEmpty();
}
@Test
public void bucketNameIsNotRequiredIfCustomConfigurationIsSpecified() throws Exception {
load(CouchbaseTestConfiguration.class);
assertThat(this.context.getBeansOfType(AbstractCouchbaseConfiguration.class)).hasSize(1);
CouchbaseTestConfiguration configuration = this.context.getBean(CouchbaseTestConfiguration.class);
assertThat(this.context.getBean(CouchbaseTemplate.class)).isSameAs(configuration.couchbaseTemplate());
assertThat(this.context.getBean(Bucket.class)).isSameAs(configuration.couchbaseClient());
assertThat(this.context.getBeansOfType(ValidatingCouchbaseEventListener.class)).isEmpty();
}
@Test
public void validatorIsPresent() {
load(ValidatorConfiguration.class);
ValidatingCouchbaseEventListener listener = this.context
.getBean(ValidatingCouchbaseEventListener.class);
assertThat(new DirectFieldAccessor(listener).getPropertyValue("validator"))
.isEqualTo(this.context.getBean(Validator.class));
}
private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(context, environment);
if (config != null) {
context.register(config);
}
context.register(PropertyPlaceholderAutoConfiguration.class,
CouchbaseAutoConfiguration.class);
this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("Connection refused");
this.context.refresh();
context.refresh();
this.context = context;
}
@Configuration
@Import(CouchbaseTestConfiguration.class)
static class ValidatorConfiguration {
@Bean
public Validator myValidator() {
return mock(Validator.class);
}
}
}

@ -0,0 +1,72 @@
/*
* 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.couchbase;
import java.util.Collections;
import java.util.List;
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 org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import static org.mockito.Mockito.mock;
/**
* Test configuration for couchbase that mocks access.
*
* @author Stephane Nicoll
*/
@Configuration
public class CouchbaseTestConfiguration extends AbstractCouchbaseConfiguration {
@Override
protected List<String> getBootstrapHosts() {
return Collections.singletonList("localhost");
}
@Override
protected String getBucketName() {
return "my-bucket";
}
@Override
protected String getBucketPassword() {
return "my-password";
}
@Override
public Cluster couchbaseCluster() throws Exception {
return mock(CouchbaseCluster.class);
}
@Bean
public ClusterInfo couchbaseClusterInfo() {
return mock(ClusterInfo.class);
}
@Override
public Bucket couchbaseClient() throws Exception {
return mock(CouchbaseBucket.class);
}
}

@ -16,35 +16,21 @@
package org.springframework.boot.autoconfigure.data.couchbase;
import java.util.Collections;
import java.util.List;
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 org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseTestConfiguration;
import org.springframework.boot.autoconfigure.data.couchbase.city.City;
import org.springframework.boot.autoconfigure.data.couchbase.city.CityRepository;
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.data.couchbase.core.WriteResultChecking;
import org.springframework.data.couchbase.core.query.Consistency;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* @author Eddú Meléndez
@ -61,7 +47,6 @@ public class CouchbaseRepositoriesAutoConfigurationTests {
@Test
public void testDefaultRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext();
addCouchbaseProperties(this.context);
this.context.register(TestConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
@ -72,79 +57,16 @@ public class CouchbaseRepositoriesAutoConfigurationTests {
@Test
public void testNoRepositoryConfiguration() throws Exception {
this.context = new AnnotationConfigApplicationContext();
addCouchbaseProperties(this.context);
this.context.register(EmptyConfiguration.class, TestConfiguration.class,
PropertyPlaceholderAutoConfiguration.class);
this.context.refresh();
assertThat(this.context.getBean(Bucket.class)).isNotNull();
}
@Test
public void templateExists() {
this.context = new AnnotationConfigApplicationContext();
EnvironmentTestUtils.addEnvironment(this.context,
"spring.data.couchbase.hosts=localhost",
"spring.data.couchbase.bucket-name=test",
"spring.data.couchbase.bucket-password=test");
this.context.register(PropertyPlaceholderAutoConfiguration.class,
TestConfiguration.class);
this.context.refresh();
assertThat(this.context.getBeanNamesForType(CouchbaseTemplate.class).length).isEqualTo(1);
}
private void addCouchbaseProperties(AnnotationConfigApplicationContext context) {
EnvironmentTestUtils.addEnvironment(context,
"spring.data.couchbase.hosts=localhost",
"spring.data.couchbase.bucket-name=test",
"spring.data.couchbase.bucket-password=test");
}
@Configuration
@TestAutoConfigurationPackage(City.class)
@Import(CouchbaseRepositoriesRegistrar.class)
static class TestConfiguration extends AbstractCouchbaseConfiguration {
@Override
protected List<String> getBootstrapHosts() {
return Collections.singletonList("192.1.2.3");
}
@Override
protected String getBucketName() {
return "someBucket";
}
@Override
protected String getBucketPassword() {
return "someBucketPassword";
}
@Override
public Cluster couchbaseCluster() throws Exception {
return mock(CouchbaseCluster.class);
}
@Bean
public ClusterInfo couchbaseClusterInfo() {
return mock(ClusterInfo.class);
}
@Override
public Bucket couchbaseClient() throws Exception {
return mock(CouchbaseBucket.class);
}
@Override
public CouchbaseTemplate couchbaseTemplate() throws Exception {
CouchbaseTemplate template = super.couchbaseTemplate();
template.setWriteResultChecking(WriteResultChecking.LOG);
return template;
}
@Override
protected Consistency getDefaultConsistency() {
return Consistency.READ_YOUR_OWN_WRITES;
}
@Import({ CouchbaseRepositoriesRegistrar.class, CouchbaseTestConfiguration.class })
static class TestConfiguration {
}

@ -1795,23 +1795,12 @@
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-couchbase</artifactId>
<version>${spring-data-couchbase.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-releasetrain</artifactId>
<version>${spring-data-releasetrain.version}</version>
<scope>import</scope>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-couchbase</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.hateoas</groupId>

@ -489,9 +489,9 @@ content into your application; rather pick only the properties that you need.
spring.data.cassandra.username= # Login user of the server.
# COUCHBASE ({sc-spring-boot-autoconfigure}/couchbase/CouchbaseProperties.{sc-ext}[CouchbaseProperties])
spring.data.couchbase.hosts= # the db host
spring.data.couchbase.bucket-name= # the bucket name
spring.data.couchbase.bucket-password= # the bucket password
spring.data.couchbase.bootstrap-hosts=localhost # Couchbase nodes (host or IP address) to bootstrap from.
spring.data.couchbase.bucket.name= # Name of the bucket to connect to.
spring.data.couchbase.bucket.password= # Password of the bucket.
# ELASTICSEARCH ({sc-spring-boot-autoconfigure}/elasticsearch/ElasticsearchProperties.{sc-ext}[ElasticsearchProperties])
spring.data.elasticsearch.cluster-name=elasticsearch # Elasticsearch cluster name.

@ -3122,6 +3122,66 @@ TIP: For complete details of Spring Data Cassandra, refer to their
http://docs.spring.io/spring-data/cassandra/docs/[reference documentation].
[[boot-features-couchbase]]
=== Couchbase
http://www.couchbase.com/[Couchbase] is an open-source, distributed multi-model NoSQL
document-oriented database that is optimized for interactive applications. Spring Boot
offers auto-configuration for Couchbase and abstractions on top of it provided by
https://github.com/spring-projects/spring-data-couchbase[Spring Data Couchbase].
There is a `spring-boot-starter-data-couchbase` '`Starter POM`' for collecting the
dependencies in a convenient way.
[[boot-features-connecting-to-couchbase]]
==== Connecting to Couchbase
You can inject an auto-configured `CouchbaseTemplate` instance as you would with any
other Spring Bean. The `spring.data.couchbase.*` properties can be used to customize the
connection. Generally you will provide the bootstrap hosts, bucket name and password:
[source,properties,indent=0]
----
spring.data.couchbase.bootstrap-hosts=my-host-1,192.168.1.123
spring.data.couchbase.bucket.name=my-bucket
spring.data.couchbase.bucket.password=secret
----
[TIP]
====
You need to provide _at least_ the bucket name, in which case the bootstrap host is
localhost and the password is an empty String. Alternatively, you can define your
own `org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration` `@Bean`
configuration to take control over the whole configuration.
====
[source,java,indent=0]
----
@Component
public class MyBean {
private final CouchbaseTemplate template;
@Autowired
public MyBean(CouchbaseTemplate template) {
this.template = template;
}
// ...
}
----
If you add a `@Bean` of your own of type `CassandraTemplate` it will replace the
default.
[[boot-features-spring-data-couchbase-repositories]]
==== Spring Data Couchbase repositories
Spring Data includes repository support for Couchbase. For complete details of Spring
Data Couchbase, refer to their
http://docs.spring.io/spring-data/couchbase/docs/current/reference/html/[reference documentation].
[[boot-features-caching]]
== Caching

@ -0,0 +1,22 @@
= Spring Boot Couchbase Sample
This sample demonstrates how you can store a simple document using Spring Data Couchbase.
The sample expects couchbase to run on your machine with a bucket named `mybucket` and
`couchbase` for the password. You can customize these settings in `application.properties`.
Before you use the sample, you need _at least_ to create an `all` view for the `User`: go
to the Couchbase servers admin console and visit the Views screen, then click `Create
Development View` and name it `all` with `user` as document name. On that view, you need
to change the code to:
```java
function (doc, meta) {
if (doc._class == "sample.data.couchbase.User") {
emit(meta.id, null);
}
}
```
and the _reduce_ function to `_count`. After you've saved your changes go back to `Views`
and click on `Publish` so that the `all` view move to the `Production Views` tab.

@ -16,6 +16,8 @@
package sample.data.couchbase;
import java.util.UUID;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
@ -40,8 +42,9 @@ public class SampleCouchbaseApplication implements CommandLineRunner {
private void saveUsers() {
User user = new User();
user.setFirstname("Alice");
user.setLastname("Smith");
user.setId(UUID.randomUUID().toString());
user.setFirstName("Alice");
user.setLastName("Smith");
this.userRepository.save(user);
}

@ -28,10 +28,10 @@ public class User {
private String id;
@Field
private String firstname;
private String firstName;
@Field
private String lastname;
private String lastName;
public String getId() {
return this.id;
@ -41,28 +41,28 @@ public class User {
this.id = id;
}
public String getFirstname() {
return this.firstname;
public String getFirstName() {
return this.firstName;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastname() {
return this.lastname;
public String getLastName() {
return this.lastName;
}
public void setLastname(String lastname) {
this.lastname = lastname;
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "User{" +
"id='" + this.id + '\'' +
", firstname='" + this.firstname + '\'' +
", lastname='" + this.lastname + '\'' +
", firstName='" + this.firstName + '\'' +
", lastName='" + this.lastName + '\'' +
'}';
}
}

@ -28,7 +28,7 @@ public class SampleCouchbaseApplicationTests {
}
}
String output = this.outputCapture.toString();
assertThat(output).contains("firstname='Alice', lastname='Smith'");
assertThat(output).contains("firstName='Alice', lastName='Smith'");
}
private boolean serverNotRunning(RuntimeException ex) {

@ -1,3 +1,2 @@
spring.data.couchbase.bucket-name=mybucket
spring.data.couchbase.bucket-password=couchbase
spring.data.couchbase.hosts[0]=127.0.0.1
spring.data.couchbase.bucket.name=mybucket
spring.data.couchbase.bucket.password=couchbase
Loading…
Cancel
Save