Commit e85cb2c4 authored by Mark Paluch's avatar Mark Paluch Committed by Stephane Nicoll

Add schemaAction property to CassandraProperties

Set schemaAction property in CassandraSessionFactoryBean. Use relaxed
property resolver for enum lookup of the configured schemaAction.

See gh-5855
parent 43867323
......@@ -4,6 +4,7 @@ jdk:
services:
- mongodb
- redis
- cassandra
sudo: false
install: true
before_script:
......
......@@ -32,6 +32,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
*
* @author Julien Dubois
* @author Phillip Webb
* @author Mark Paluch
* @since 1.3.0
*/
@ConfigurationProperties(prefix = "spring.data.cassandra")
......@@ -112,6 +113,11 @@ public class CassandraProperties {
*/
private int readTimeoutMillis = SocketOptions.DEFAULT_READ_TIMEOUT_MILLIS;
/**
* Action to take at startup.
*/
private String schemaAction = "none";
/**
* Enable SSL support.
*/
......@@ -247,4 +253,12 @@ public class CassandraProperties {
this.ssl = ssl;
}
public String getSchemaAction() {
return this.schemaAction;
}
public void setSchemaAction(String schemaAction) {
this.schemaAction = schemaAction;
}
}
......@@ -30,9 +30,12 @@ import org.springframework.boot.autoconfigure.cassandra.CassandraProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.domain.EntityScanPackages;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertyResolver;
import org.springframework.data.cassandra.config.CassandraEntityClassScanner;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
......@@ -48,6 +51,7 @@ import org.springframework.data.cassandra.mapping.CassandraMappingContext;
*
* @author Julien Dubois
* @author Eddú Meléndez
* @author Mark Paluch
* @since 1.3.0
*/
@Configuration
......@@ -62,11 +66,14 @@ public class CassandraDataAutoConfiguration {
private final Cluster cluster;
private final PropertyResolver propertyResolver;
public CassandraDataAutoConfiguration(BeanFactory beanFactory,
CassandraProperties properties, Cluster cluster) {
CassandraProperties properties, Cluster cluster, Environment environment) {
this.beanFactory = beanFactory;
this.properties = properties;
this.cluster = cluster;
this.propertyResolver = new RelaxedPropertyResolver(environment, "spring.data.cassandra.");
}
@Bean
......@@ -94,11 +101,14 @@ public class CassandraDataAutoConfiguration {
@ConditionalOnMissingBean(Session.class)
public CassandraSessionFactoryBean session(CassandraConverter converter)
throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(this.cluster);
session.setConverter(converter);
session.setKeyspaceName(this.properties.getKeyspaceName());
session.setSchemaAction(SchemaAction.NONE);
SchemaAction schemaAction = propertyResolver.getProperty("schemaAction", SchemaAction.class, SchemaAction.NONE);
session.setSchemaAction(schemaAction);
return session;
}
......
package org.springframework.boot.autoconfigure.data.cassandra;
/**
*
* @author Stephane Nicoll
*/
public class CassandraDataAutoConfigurationIntegrationTests {
}
......@@ -18,19 +18,26 @@ package org.springframework.boot.autoconfigure.data.cassandra;
import java.util.Set;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.DriverException;
import org.junit.After;
import org.junit.Test;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.test.util.EnvironmentTestUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.cassandra.config.CassandraSessionFactoryBean;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.test.util.ReflectionTestUtils;
......@@ -42,6 +49,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link CassandraDataAutoConfiguration}
*
* @author Eddú Meléndez
* @author Mark Paluch
*/
public class CassandraDataAutoConfigurationTests {
......@@ -65,6 +73,47 @@ public class CassandraDataAutoConfigurationTests {
.isEqualTo(1);
}
@Test
public void hasDefaultSchemaActionSet() {
if (isCassandraAvailable()) {
this.context = new AnnotationConfigApplicationContext();
String cityPackage = City.class.getPackage().getName();
AutoConfigurationPackages.register(this.context, cityPackage);
this.context.register(CassandraAutoConfiguration.class,
CassandraDataAutoConfiguration.class);
this.context.refresh();
CassandraSessionFactoryBean bean = this.context
.getBean(CassandraSessionFactoryBean.class);
assertThat(bean.getSchemaAction()).isEqualTo(SchemaAction.NONE);
}
}
@Test
public void hasRecreateSchemaActionSet() {
if (isCassandraAvailable()) {
createTestKeyspaceIfNotExists();
this.context = new AnnotationConfigApplicationContext();
String cityPackage = City.class.getPackage().getName();
AutoConfigurationPackages.register(this.context, cityPackage);
EnvironmentTestUtils.addEnvironment(this.context,
"spring.data.cassandra.schemaAction:RECREATE_DROP_UNUSED", "spring.data.cassandra.keyspaceName:boot_test");
this.context.register(CassandraAutoConfiguration.class,
CassandraDataAutoConfiguration.class);
this.context.refresh();
CassandraSessionFactoryBean bean = this.context
.getBean(CassandraSessionFactoryBean.class);
assertThat(bean.getSchemaAction()).isEqualTo(SchemaAction.RECREATE_DROP_UNUSED);
}
}
@Test
@SuppressWarnings("unchecked")
public void entityScanShouldSetInitialEntitySet() throws Exception {
......@@ -80,6 +129,42 @@ public class CassandraDataAutoConfigurationTests {
assertThat(initialEntitySet).containsOnly(City.class);
}
/**
* @return {@literal true} if Cassandra is available
*/
private static boolean isCassandraAvailable() {
Cluster cluster = newCluster();
try {
cluster.connect().close();
return true;
}
catch (DriverException exception) {
return false;
}
finally {
cluster.closeAsync();
}
}
private static void createTestKeyspaceIfNotExists() {
Cluster cluster = newCluster();
try {
Session session = cluster.connect();
session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test"
+ " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
session.close();
}
finally {
cluster.closeAsync();
}
}
private static Cluster newCluster() {
return Cluster.builder().addContactPoint("localhost").build();
}
@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(classes = {
Session.class }, type = FilterType.ASSIGNABLE_TYPE))
......
......@@ -16,6 +16,8 @@
package org.springframework.boot.autoconfigure.data.cassandra;
import java.util.Set;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Session;
import org.junit.After;
......@@ -34,7 +36,9 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
......@@ -43,6 +47,7 @@ import static org.mockito.Mockito.mock;
* Tests for {@link CassandraRepositoriesAutoConfiguration}.
*
* @author Eddú Meléndez
* @author Mark Paluch
*/
public class CassandraRepositoriesAutoConfigurationTests {
......@@ -63,18 +68,39 @@ public class CassandraRepositoriesAutoConfigurationTests {
addConfigurations(TestConfiguration.class);
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
assertThat(this.context.getBean(Cluster.class)).isNotNull();
BasicCassandraMappingContext mappingContext = this.context
.getBean(BasicCassandraMappingContext.class);
@SuppressWarnings("unchecked")
Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils
.getField(mappingContext, "initialEntitySet");
assertThat(entities).hasSize(1);
}
@Test
public void testNoRepositoryConfiguration() {
addConfigurations(TestExcludeConfiguration.class, EmptyConfiguration.class);
assertThat(this.context.getBean(Cluster.class)).isNotNull();
BasicCassandraMappingContext mappingContext = this.context
.getBean(BasicCassandraMappingContext.class);
@SuppressWarnings("unchecked")
Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils
.getField(mappingContext, "initialEntitySet");
assertThat(entities).hasSize(1).containsOnly(City.class);
}
@Test
public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
addConfigurations(TestExcludeConfiguration.class, CustomizedConfiguration.class);
assertThat(this.context.getBean(CityCassandraRepository.class)).isNotNull();
BasicCassandraMappingContext mappingContext = this.context
.getBean(BasicCassandraMappingContext.class);
@SuppressWarnings("unchecked")
Set<? extends Class<?>> entities = (Set<? extends Class<?>>) ReflectionTestUtils
.getField(mappingContext, "initialEntitySet");
assertThat(entities).hasSize(1).containsOnly(City.class);
}
private void addConfigurations(Class<?>... configurations) {
......
package org.springframework.boot.autoconfigure.data.cassandra;
/**
*
* @author Stephane Nicoll
*/
public class CassandraTestServer {
}
......@@ -16,6 +16,9 @@
package org.springframework.boot.autoconfigure.data.cassandra.city;
import com.datastax.driver.core.DataType.Name;
import org.springframework.data.cassandra.mapping.CassandraType;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;
......@@ -24,6 +27,7 @@ import org.springframework.data.cassandra.mapping.Table;
public class City {
@PrimaryKey
@CassandraType(type = Name.BIGINT)
private Long id;
@Column
......
......@@ -548,6 +548,7 @@ content into your application; rather pick only the properties that you need.
spring.data.cassandra.reconnection-policy= # Reconnection policy class.
spring.data.cassandra.retry-policy= # Class name of the retry policy.
spring.data.cassandra.serial-consistency-level= # Queries serial consistency level.
spring.data.cassandra.schema-action= # Action to take at starup. Default: NONE.
spring.data.cassandra.ssl=false # Enable SSL support.
spring.data.cassandra.username= # Login user of the server.
......
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