diff --git a/spring-boot-actuator/pom.xml b/spring-boot-actuator/pom.xml index fd786e55f78..3b4e501c2e1 100644 --- a/spring-boot-actuator/pom.xml +++ b/spring-boot-actuator/pom.xml @@ -147,6 +147,11 @@ spring-webmvc true + + org.springframework.data + spring-data-cassandra + true + org.springframework.data spring-data-mongodb diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CassandraHealthIndicator.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CassandraHealthIndicator.java new file mode 100644 index 00000000000..e2359c24bc0 --- /dev/null +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/health/CassandraHealthIndicator.java @@ -0,0 +1,65 @@ +/* + * Copyright 2012-2015 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.actuate.health; + +import org.springframework.data.cassandra.core.CassandraAdminOperations; +import org.springframework.util.Assert; + +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.querybuilder.QueryBuilder; +import com.datastax.driver.core.querybuilder.Select; + +/** + * Simple implementation of a {@link HealthIndicator} returning status information for + * Cassandra data stores. + * + * @author Julien Dubois + * @since 1.3.0 + */ +public class CassandraHealthIndicator extends AbstractHealthIndicator { + + private CassandraAdminOperations cassandraAdminOperations; + + /** + * Create a new {@link CassandraHealthIndicator} instance. + * @param cassandraAdminOperations the Cassandra admin operations + */ + public CassandraHealthIndicator(CassandraAdminOperations cassandraAdminOperations) { + Assert.notNull(cassandraAdminOperations, + "CassandraAdminOperations must not be null"); + this.cassandraAdminOperations = cassandraAdminOperations; + } + + @Override + protected void doHealthCheck(Health.Builder builder) throws Exception { + try { + Select select = QueryBuilder.select("release_version") + .from("system", "local"); + ResultSet results = this.cassandraAdminOperations.query(select); + if (results.isExhausted()) { + builder.up(); + return; + } + String version = results.one().getString(0); + builder.up().withDetail("version", version); + } + catch (Exception ex) { + builder.down(ex); + } + } + +} diff --git a/spring-boot-autoconfigure/pom.xml b/spring-boot-autoconfigure/pom.xml index 3b17f5c02a9..3100f1560c2 100644 --- a/spring-boot-autoconfigure/pom.xml +++ b/spring-boot-autoconfigure/pom.xml @@ -342,6 +342,11 @@ + + org.springframework.data + spring-data-cassandra + true + org.springframework.data spring-data-mongodb diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java new file mode 100644 index 00000000000..ce2c889077b --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java @@ -0,0 +1,107 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.ReconnectionPolicy; +import com.datastax.driver.core.policies.RetryPolicy; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Cassandra. + * + * @author Julien Dubois + * @author Phillip Webb + * @since 1.3.0 + */ +@Configuration +@ConditionalOnClass({ Cluster.class }) +@EnableConfigurationProperties(CassandraProperties.class) +public class CassandraAutoConfiguration { + + @Autowired + private CassandraProperties properties; + + @Bean + @ConditionalOnMissingBean + public Cluster cluster() { + CassandraProperties properties = this.properties; + Cluster.Builder builder = Cluster.builder() + .withClusterName(properties.getClusterName()) + .withPort(properties.getPort()); + if (properties.getCompression() != null) { + builder.withCompression(properties.getCompression()); + } + if (properties.getLoadBalancingPolicy() != null) { + LoadBalancingPolicy policy = instantiate(properties.getLoadBalancingPolicy()); + builder.withLoadBalancingPolicy(policy); + } + builder.withQueryOptions(getQueryOptions()); + if (properties.getReconnectionPolicy() != null) { + ReconnectionPolicy policy = instantiate(properties.getReconnectionPolicy()); + builder.withReconnectionPolicy(policy); + } + if (properties.getRetryPolicy() != null) { + RetryPolicy policy = instantiate(properties.getRetryPolicy()); + builder.withRetryPolicy(policy); + } + builder.withSocketOptions(getSocketOptions()); + if (properties.isSsl()) { + builder.withSSL(); + } + String points = properties.getContactPoints(); + builder.addContactPoints(StringUtils.commaDelimitedListToStringArray(points)); + return builder.build(); + } + + public static T instantiate(Class type) { + return BeanUtils.instantiate(type); + } + + private QueryOptions getQueryOptions() { + QueryOptions options = new QueryOptions(); + CassandraProperties properties = this.properties; + if (properties.getConsistencyLevel() != null) { + options.setConsistencyLevel(properties.getConsistencyLevel()); + } + if (properties.getSerialConsistencyLevel() != null) { + options.setSerialConsistencyLevel(properties.getSerialConsistencyLevel()); + } + options.setFetchSize(properties.getFetchSize()); + return options; + } + + private SocketOptions getSocketOptions() { + SocketOptions options = new SocketOptions(); + options.setConnectTimeoutMillis(this.properties.getConnectTimeoutMillis()); + options.setReadTimeoutMillis(this.properties.getReadTimeoutMillis()); + return options; + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraProperties.java new file mode 100644 index 00000000000..73251168bc4 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraProperties.java @@ -0,0 +1,224 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +import com.datastax.driver.core.ConsistencyLevel; +import com.datastax.driver.core.ProtocolOptions; +import com.datastax.driver.core.ProtocolOptions.Compression; +import com.datastax.driver.core.QueryOptions; +import com.datastax.driver.core.SocketOptions; +import com.datastax.driver.core.policies.LoadBalancingPolicy; +import com.datastax.driver.core.policies.ReconnectionPolicy; +import com.datastax.driver.core.policies.RetryPolicy; + +/** + * Configuration properties for Cassandra. + * + * @author Julien Dubois + * @author Phillip Webb + * @since 1.3.0 + */ +@ConfigurationProperties(prefix = "spring.data.cassandra") +public class CassandraProperties { + + /** + * Keyspace name to use. + */ + private String keyspaceName; + + /** + * Name of the Cassandra cluster. + */ + private String clusterName; + + /** + * Comma-separated list of cluster node addresses. + */ + private String contactPoints = "localhost"; + + /** + * Port of the Cassandra server. + */ + private int port = ProtocolOptions.DEFAULT_PORT; + + /** + * Compression supported by the Cassandra binary protocol. + */ + private Compression compression = Compression.NONE; + + /** + * Class name of the load balancing policy. + */ + private Class loadBalancingPolicy; + + /** + * Queries consistency level. + */ + private ConsistencyLevel consistencyLevel; + + /** + * Queries serial consistency level. + */ + private ConsistencyLevel serialConsistencyLevel; + + /** + * Queries default fetch size. + */ + private int fetchSize = QueryOptions.DEFAULT_FETCH_SIZE; + + /** + * Reconnection policy class. + */ + private Class reconnectionPolicy; + + /** + * Class name of the retry policy. + */ + private Class retryPolicy; + + /** + * Socket option: connection time out. + */ + private int connectTimeoutMillis = SocketOptions.DEFAULT_CONNECT_TIMEOUT_MILLIS; + + /** + * Socket option: read time out. + */ + private int readTimeoutMillis = SocketOptions.DEFAULT_READ_TIMEOUT_MILLIS; + + /** + * Enable SSL support. + */ + private boolean ssl = false; + + public String getKeyspaceName() { + return this.keyspaceName; + } + + public void setKeyspaceName(String keyspaceName) { + this.keyspaceName = keyspaceName; + } + + public String getClusterName() { + return this.clusterName; + } + + public void setClusterName(String clusterName) { + this.clusterName = clusterName; + } + + public String getContactPoints() { + return this.contactPoints; + } + + public void setContactPoints(String contactPoints) { + this.contactPoints = contactPoints; + } + + public int getPort() { + return this.port; + } + + public void setPort(int port) { + this.port = port; + } + + public Compression getCompression() { + return this.compression; + } + + public void setCompression(Compression compression) { + this.compression = compression; + } + + public Class getLoadBalancingPolicy() { + return this.loadBalancingPolicy; + } + + public void setLoadBalancingPolicy( + Class loadBalancingPolicy) { + this.loadBalancingPolicy = loadBalancingPolicy; + } + + public ConsistencyLevel getConsistencyLevel() { + return this.consistencyLevel; + } + + public void setConsistencyLevel(ConsistencyLevel consistency) { + this.consistencyLevel = consistency; + } + + public ConsistencyLevel getSerialConsistencyLevel() { + return this.serialConsistencyLevel; + } + + public void setSerialConsistencyLevel(ConsistencyLevel serialConsistency) { + this.serialConsistencyLevel = serialConsistency; + } + + public int getFetchSize() { + return this.fetchSize; + } + + public void setFetchSize(int fetchSize) { + this.fetchSize = fetchSize; + } + + public Class getReconnectionPolicy() { + return this.reconnectionPolicy; + } + + public void setReconnectionPolicy( + Class reconnectionPolicy) { + this.reconnectionPolicy = reconnectionPolicy; + } + + public Class getRetryPolicy() { + return this.retryPolicy; + } + + public void setRetryPolicy(Class retryPolicy) { + this.retryPolicy = retryPolicy; + } + + public int getConnectTimeoutMillis() { + return this.connectTimeoutMillis; + } + + public void setConnectTimeoutMillis(int connectTimeoutMillis) { + this.connectTimeoutMillis = connectTimeoutMillis; + } + + public int getReadTimeoutMillis() { + return this.readTimeoutMillis; + } + + public void setReadTimeoutMillis(int readTimeoutMillis) { + this.readTimeoutMillis = readTimeoutMillis; + } + + public boolean isSsl() { + return this.ssl; + } + + public void setSsl(boolean ssl) { + this.ssl = ssl; + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/package-info.java new file mode 100644 index 00000000000..f3a1cfc5bd5 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2015 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. + */ + +/** + * Auto-configuration for Cassandra. + */ +package org.springframework.boot.autoconfigure.cassandra; + diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java new file mode 100644 index 00000000000..88191217707 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfiguration.java @@ -0,0 +1,91 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.AutoConfigureAfter; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +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.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.cassandra.config.CassandraSessionFactoryBean; +import org.springframework.data.cassandra.config.SchemaAction; +import org.springframework.data.cassandra.convert.CassandraConverter; +import org.springframework.data.cassandra.convert.MappingCassandraConverter; +import org.springframework.data.cassandra.core.CassandraAdminOperations; +import org.springframework.data.cassandra.core.CassandraTemplate; +import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; +import org.springframework.data.cassandra.mapping.CassandraMappingContext; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra support. + * + * @author Julien Dubois + * @author Eddú Meléndez + * @since 1.3.0 + */ +@Configuration +@ConditionalOnClass({ Cluster.class, CassandraAdminOperations.class }) +@EnableConfigurationProperties(CassandraProperties.class) +@AutoConfigureAfter(CassandraAutoConfiguration.class) +public class CassandraDataAutoConfiguration { + + @Autowired + private CassandraProperties properties; + + @Autowired + private Cluster cluster; + + @Bean + @ConditionalOnMissingBean + public CassandraMappingContext cassandraMapping() { + return new BasicCassandraMappingContext(); + } + + @Bean + @ConditionalOnMissingBean + public CassandraConverter cassandraConverter(CassandraMappingContext mapping) { + return new MappingCassandraConverter(mapping); + } + + @Bean + @ConditionalOnMissingBean + 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); + return session; + } + + @Bean + @ConditionalOnMissingBean + public CassandraTemplate cassandraTemplate(Session session, + CassandraConverter converter) throws Exception { + return new CassandraTemplate(session, converter); + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfiguration.java new file mode 100644 index 00000000000..c661e3df95b --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfiguration.java @@ -0,0 +1,46 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; +import org.springframework.data.cassandra.repository.support.CassandraRepositoryFactoryBean; + +import com.datastax.driver.core.Session; + +/** + * {@link EnableAutoConfiguration Auto-configuration} for Spring Data's Cassandra + * Repositories. + * + * @author Eddú Meléndez + * @see EnableCassandraRepositories + * @since 1.3.0 + */ +@Configuration +@ConditionalOnClass({ Session.class, CassandraRepository.class }) +@ConditionalOnProperty(prefix = "spring.data.cassandra.repositories", name = "enabled", havingValue = "true", matchIfMissing = true) +@ConditionalOnMissingBean(CassandraRepositoryFactoryBean.class) +@Import(CassandraRepositoriesAutoConfigureRegistrar.class) +public class CassandraRepositoriesAutoConfiguration { + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigureRegistrar.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigureRegistrar.java new file mode 100644 index 00000000000..b672586662c --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigureRegistrar.java @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import java.lang.annotation.Annotation; + +import org.springframework.boot.autoconfigure.data.AbstractRepositoryConfigurationSourceSupport; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.data.cassandra.repository.config.CassandraRepositoryConfigurationExtension; +import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; +import org.springframework.data.repository.config.RepositoryConfigurationExtension; + +/** + * {@link ImportBeanDefinitionRegistrar} used to auto-configure Spring Data Cassandra + * Repositories. + * + * @author Eddú Meléndez + * @since 1.3.0 + */ +class CassandraRepositoriesAutoConfigureRegistrar extends + AbstractRepositoryConfigurationSourceSupport { + + @Override + protected Class getAnnotation() { + return EnableCassandraRepositories.class; + } + + @Override + protected Class getConfiguration() { + return EnableCassandraRepositoriesConfiguration.class; + } + + @Override + protected RepositoryConfigurationExtension getRepositoryConfigurationExtension() { + return new CassandraRepositoryConfigurationExtension(); + } + + @EnableCassandraRepositories + private static class EnableCassandraRepositoriesConfiguration { + } + +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/package-info.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/package-info.java new file mode 100644 index 00000000000..c9e55d7c6ba --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/data/cassandra/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2012-2015 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. + */ + +/** + * Auto-configuration for Spring Data Cassandra. + */ +package org.springframework.boot.autoconfigure.data.cassandra; + diff --git a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories index 198cc9f428f..79bb6b26467 100644 --- a/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories +++ b/spring-boot-autoconfigure/src/main/resources/META-INF/spring.factories @@ -11,9 +11,12 @@ org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration,\ org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\ org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\ +org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\ org.springframework.boot.autoconfigure.cloud.CloudAutoConfiguration,\ org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration,\ org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration,\ +org.springframework.boot.autoconfigure.data.cassandra.CassandraRepositoriesAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration,\ org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration,\ diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationTests.java new file mode 100644 index 00000000000..bac9f6d014c --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.test.EnvironmentTestUtils; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; + +import com.datastax.driver.core.Cluster; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.startsWith; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link CassandraAutoConfiguration} + * + * @author Eddú Meléndez + */ +public class CassandraAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void tearDown() throws Exception { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void createClusterWithDefault() { + this.context = doLoad(); + assertEquals(1, this.context.getBeanNamesForType(Cluster.class).length); + Cluster cluster = this.context.getBean(Cluster.class); + assertThat(cluster.getClusterName(), startsWith("cluster")); + } + + @Test + public void createClusterWithOverrides() { + this.context = doLoad("spring.data.cassandra.cluster-name=testcluster"); + assertEquals(1, this.context.getBeanNamesForType(Cluster.class).length); + Cluster cluster = this.context.getBean(Cluster.class); + assertThat(cluster.getClusterName(), equalTo("testcluster")); + } + + private AnnotationConfigApplicationContext doLoad(String... environment) { + AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(); + EnvironmentTestUtils.addEnvironment(applicationContext, environment); + applicationContext.register(PropertyPlaceholderAutoConfiguration.class, + CassandraAutoConfiguration.class); + applicationContext.refresh(); + return applicationContext; + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/cassandra/CityCassandraRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/cassandra/CityCassandraRepository.java new file mode 100644 index 00000000000..d60375b9b4e --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/alt/cassandra/CityCassandraRepository.java @@ -0,0 +1,24 @@ +/* + * Copyright 2012-2015 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.alt.cassandra; + +import org.springframework.boot.autoconfigure.data.cassandra.city.City; +import org.springframework.data.repository.Repository; + +public interface CityCassandraRepository extends Repository { + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java new file mode 100644 index 00000000000..efc878e4531 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraDataAutoConfigurationTests.java @@ -0,0 +1,77 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.junit.After; +import org.junit.Test; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +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.core.CassandraTemplate; + +import com.datastax.driver.core.Session; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link CassandraDataAutoConfiguration} + * + * @author Eddú Meléndez + */ +public class CassandraDataAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @After + public void close() { + if (this.context != null) { + this.context.close(); + } + } + + @Test + public void templateExists() { + this.context = new AnnotationConfigApplicationContext(); + this.context.register(TestExcludeConfiguration.class, TestConfiguration.class, + PropertyPlaceholderAutoConfiguration.class, + CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class); + this.context.refresh(); + assertEquals(1, this.context.getBeanNamesForType(CassandraTemplate.class).length); + } + + @Configuration + @ComponentScan(excludeFilters = @ComponentScan.Filter(classes = { Session.class }, type = FilterType.ASSIGNABLE_TYPE)) + static class TestExcludeConfiguration { + + } + + @Configuration + static class TestConfiguration { + + @Bean + public Session getObject() { + return mock(Session.class); + } + + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigurationTests.java new file mode 100644 index 00000000000..ed535b4c348 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/CassandraRepositoriesAutoConfigurationTests.java @@ -0,0 +1,119 @@ +/* + * Copyright 2012-2015 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.cassandra; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.boot.autoconfigure.PropertyPlaceholderAutoConfiguration; +import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage; +import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration; +import org.springframework.boot.autoconfigure.data.alt.cassandra.CityCassandraRepository; +import org.springframework.boot.autoconfigure.data.cassandra.city.City; +import org.springframework.boot.autoconfigure.data.cassandra.city.CityRepository; +import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage; +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.repository.config.EnableCassandraRepositories; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.Mockito.mock; + +/** + * Tests for {@link CassandraRepositoriesAutoConfiguration}. + * + * @author Eddú Meléndez + */ +public class CassandraRepositoriesAutoConfigurationTests { + + private AnnotationConfigApplicationContext context; + + @Before + public void setUp() { + this.context = new AnnotationConfigApplicationContext(); + } + + @After + public void close() { + this.context.close(); + } + + @Test + public void testDefaultRepositoryConfiguration() { + addConfigurations(TestConfiguration.class); + assertNotNull(this.context.getBean(CityRepository.class)); + assertNotNull(this.context.getBean(Cluster.class)); + } + + @Test + public void testNoRepositoryConfiguration() { + addConfigurations(TestExcludeConfiguration.class, EmptyConfiguration.class); + assertNotNull(this.context.getBean(Cluster.class)); + } + + @Test + public void doesNotTriggerDefaultRepositoryDetectionIfCustomized() { + addConfigurations(TestExcludeConfiguration.class, CustomizedConfiguration.class); + assertNotNull(this.context.getBean(CityCassandraRepository.class)); + } + + private void addConfigurations(Class... configurations) { + this.context.register(configurations); + this.context.register(CassandraAutoConfiguration.class, + CassandraRepositoriesAutoConfiguration.class, + CassandraDataAutoConfiguration.class, + PropertyPlaceholderAutoConfiguration.class); + this.context.refresh(); + } + + @Configuration + @TestAutoConfigurationPackage(City.class) + static class TestConfiguration { + + @Bean + public Session session() { + return mock(Session.class); + } + + } + + @Configuration + @TestAutoConfigurationPackage(EmptyDataPackage.class) + static class EmptyConfiguration { + + } + + @Configuration + @TestAutoConfigurationPackage(CassandraRepositoriesAutoConfigurationTests.class) + @EnableCassandraRepositories(basePackageClasses = CityCassandraRepository.class) + static class CustomizedConfiguration { + + } + + @Configuration + @ComponentScan(excludeFilters = @ComponentScan.Filter(classes = { Session.class }, type = FilterType.ASSIGNABLE_TYPE)) + static class TestExcludeConfiguration { + + } + +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/City.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/City.java new file mode 100644 index 00000000000..b785a4ec012 --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/City.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012-2015 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.cassandra.city; + +import org.springframework.data.cassandra.mapping.Column; +import org.springframework.data.cassandra.mapping.PrimaryKey; +import org.springframework.data.cassandra.mapping.Table; + +@Table +public class City { + + @PrimaryKey + private Long id; + + @Column + private String name; + + @Column + private String state; + + @Column + private String country; + + @Column + private String map; + + public Long getId() { + return this.id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public String getState() { + return this.state; + } + + public void setState(String state) { + this.state = state; + } + + public String getCountry() { + return this.country; + } + + public void setCountry(String country) { + this.country = country; + } + + public String getMap() { + return this.map; + } + + public void setMap(String map) { + this.map = map; + } +} diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/CityRepository.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/CityRepository.java new file mode 100644 index 00000000000..7b3e184753e --- /dev/null +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/data/cassandra/city/CityRepository.java @@ -0,0 +1,23 @@ +/* + * Copyright 2012-2015 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.cassandra.city; + +import org.springframework.data.repository.Repository; + +public interface CityRepository extends Repository { + +} diff --git a/spring-boot-dependencies/pom.xml b/spring-boot-dependencies/pom.xml index a033a854a04..5982f5f577a 100644 --- a/spring-boot-dependencies/pom.xml +++ b/spring-boot-dependencies/pom.xml @@ -263,6 +263,11 @@ spring-boot-starter-cloud-connectors 1.3.0.BUILD-SNAPSHOT + + org.springframework.boot + spring-boot-starter-data-cassandra + 1.3.0.BUILD-SNAPSHOT + org.springframework.boot spring-boot-starter-data-elasticsearch @@ -2135,4 +2140,4 @@ integration-test - \ No newline at end of file + diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index f4043a58f77..17c10a3c419 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -340,6 +340,22 @@ content into your application; rather pick only the properties that you need. # DAO ({sc-spring-boot-autoconfigure}/dao/PersistenceExceptionTranslationAutoConfiguration.{sc-ext}[PersistenceExceptionTranslationAutoConfiguration]) spring.dao.exceptiontranslation.enabled=true + # CASSANDRA ({sc-spring-boot-autoconfigure}/cassandra/CassandraProperties.{sc-ext}[CassandraProperties]) + spring.data.cassandra.cluster-name= # the cluster name + spring.data.cassandra.contact-points=localhost # comma-list of cluster node addresses + spring.data.cassandra.keyspace-name= # the keyspace name + spring.data.cassandra.port= # the connection port + spring.data.cassandra.compression= # compression method (none/snappy/lz4) + spring.data.cassandra.loadbalancing-policy= # class name for a LoadBalancingPolicy + spring.data.cassandra.consistency-level= # consistency level (any/one/two/three/quorum/all...) + spring.data.cassandra.serial-consistency-level= # serial consistency level (any/one/two/three/quorum/all...) + spring.data.cassandra.fetch-size= + spring.data.cassandra.reconnection-policy= # class name for a ReconnectionPolicy + spring.data.cassandra.retry-policy= # class name for a RetryPolicy + spring.data.cassandra.connect-timeout-millis= # connect timeout (ms) + spring.data.cassandra.read-timeout-millis= # read timeout (ms) + spring.data.cassandra.ssl=false + # MONGODB ({sc-spring-boot-autoconfigure}/mongo/MongoProperties.{sc-ext}[MongoProperties]) spring.data.mongodb.host= # the db host spring.data.mongodb.port=27017 # the connection port (defaults to 27107) diff --git a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc index 6304de15aac..172c61da47f 100644 --- a/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc +++ b/spring-boot-docs/src/main/asciidoc/spring-boot-features.adoc @@ -2460,9 +2460,9 @@ http://projects.spring.io/spring-data-redis/[Redis], http://projects.spring.io/spring-data-gemfire/[Gemfire], http://projects.spring.io/spring-data-couchbase/[Couchbase] and http://projects.spring.io/spring-data-cassandra/[Cassandra]. -Spring Boot provides auto-configuration for Redis, MongoDB, Elasticsearch, and Solr; you -can make use of the other projects, but you will need to configure them yourself. Refer to -the appropriate reference documentation at +Spring Boot provides auto-configuration for Redis, MongoDB, Elasticsearch, Solr and +Cassandra; you can make use of the other projects, but you will need to configure them +yourself. Refer to the appropriate reference documentation at http://projects.spring.io/spring-data[projects.spring.io/spring-data]. @@ -2781,6 +2781,63 @@ http://docs.spring.io/spring-data/elasticsearch/docs/[reference documentation]. +[[boot-features-cassandra]] +=== Cassandra +http://cassandra.apache.org/[Cassandra] is an open source, distributed database management +system designed to handle large amounts of data across many commodity servers. Spring Boot +offers auto-configuration for Cassandra and abstractions on top of it provided by +https://github.com/spring-projects/spring-data-cassandra[Spring Data Cassandra]. +There is a `spring-boot-starter-data-cassandra` '`Starter POM`' for collecting the +dependencies in a convenient way. + + + +[[boot-features-connecting-to-cassandra]] +==== Connecting to Cassandra +You can inject an auto-configured `CassandraTemplate` or a Cassandra `Session` +instance as you would any other Spring Bean. The `spring.data.cassandra.*` properties +can be used to customize the connection. Generally you will to provide `keyspace-name` +and `contact-points` properties: + +[source,properties,indent=0] +---- + spring.data.cassandra.keyspace-name=mykeyspace + spring.data.cassandra.contact-points=cassandrahost1,cassandrahost2 +---- + +[source,java,indent=0] +---- + @Component + public class MyBean { + + private CassandraTemplate template; + + @Autowired + public MyBean(CassandraTemplate template) { + this.template = template; + } + + // ... + + } +---- + +If you add a `@Bean` of your own of type `CassandraTemplate` it will replace the +default. + + + +[[boot-features-spring-data-cassandra-repositories]] +==== Spring Data Cassandra repositories +Spring Data includes basic repository support for Cassandra. Currently this is more +limited than the JPA repositories discussed earlier, and will need to annotate finder +methods with `@Query`. + +TIP: For complete details of Spring Data Cassandra, refer to their +http://docs.spring.io/spring-data/cassandra/docs/[reference documentation]. + + + [[boot-features-caching]] == Caching The Spring Framework provides support for transparently adding caching to an application. diff --git a/spring-boot-samples/pom.xml b/spring-boot-samples/pom.xml index db59230868c..5eb8551cda4 100644 --- a/spring-boot-samples/pom.xml +++ b/spring-boot-samples/pom.xml @@ -32,6 +32,7 @@ spring-boot-sample-atmosphere spring-boot-sample-batch spring-boot-sample-cache + spring-boot-sample-data-cassandra spring-boot-sample-data-elasticsearch spring-boot-sample-data-gemfire spring-boot-sample-data-jpa diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/README.adoc b/spring-boot-samples/spring-boot-sample-data-cassandra/README.adoc new file mode 100644 index 00000000000..2cee98998c9 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/README.adoc @@ -0,0 +1,4 @@ + + +CREATE KEYSPACE mykeyspace WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 }; + diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/pom.xml b/spring-boot-samples/spring-boot-sample-data-cassandra/pom.xml new file mode 100644 index 00000000000..308fdc2b85a --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/pom.xml @@ -0,0 +1,50 @@ + + + 4.0.0 + + + org.springframework.boot + spring-boot-samples + 1.3.0.BUILD-SNAPSHOT + + spring-boot-sample-data-cassandra + Spring Boot Data Cassandra Sample + Spring Boot Data Cassandra Sample + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-data-cassandra + + + org.springframework.boot + spring-boot-starter-test + test + + + org.cassandraunit + cassandra-unit-spring + 2.1.3.1 + test + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/Customer.java b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/Customer.java new file mode 100644 index 00000000000..06bd82db5d9 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/Customer.java @@ -0,0 +1,49 @@ +/* + * Copyright 2012-2013 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 sample.data.cassandra; + +import java.util.UUID; + +import org.springframework.data.cassandra.mapping.PrimaryKey; +import org.springframework.data.cassandra.mapping.Table; + +@Table +public class Customer { + + @PrimaryKey + private UUID id; + + private String firstName; + + private String lastName; + + public Customer() { + } + + public Customer(UUID id, String firstName, String lastName) { + this.id = id; + this.firstName = firstName; + this.lastName = lastName; + } + + @Override + public String toString() { + return String.format("Customer[id=%s, firstName='%s', lastName='%s']", this.id, + this.firstName, this.lastName); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/CustomerRepository.java b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/CustomerRepository.java new file mode 100644 index 00000000000..55eb59c4563 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/CustomerRepository.java @@ -0,0 +1,32 @@ +/* + * Copyright 2012-2013 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 sample.data.cassandra; + +import java.util.List; + +import org.springframework.data.cassandra.repository.Query; +import org.springframework.data.repository.CrudRepository; + +public interface CustomerRepository extends CrudRepository { + + @Query("Select * from customer where firstname=?0") + public Customer findByFirstName(String firstName); + + @Query("Select * from customer where lastname=?0") + public List findByLastName(String lastName); + +} diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/SampleCassandraApplication.java b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/SampleCassandraApplication.java new file mode 100644 index 00000000000..ced0425aa60 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/java/sample/data/cassandra/SampleCassandraApplication.java @@ -0,0 +1,64 @@ +/* + * Copyright 2012-2015 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 sample.data.cassandra; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +import com.datastax.driver.core.utils.UUIDs; + +@SpringBootApplication +public class SampleCassandraApplication implements CommandLineRunner { + + @Autowired + private CustomerRepository repository; + + @Override + public void run(String... args) throws Exception { + this.repository.deleteAll(); + + // save a couple of customers + this.repository.save(new Customer(UUIDs.timeBased(), "Alice", "Smith")); + this.repository.save(new Customer(UUIDs.timeBased(), "Bob", "Smith")); + + // fetch all customers + System.out.println("Customers found with findAll():"); + System.out.println("-------------------------------"); + for (Customer customer : this.repository.findAll()) { + System.out.println(customer); + } + System.out.println(); + + // fetch an individual customer + System.out.println("Customer found with findByFirstName('Alice'):"); + System.out.println("--------------------------------"); + System.out.println(this.repository.findByFirstName("Alice")); + + System.out.println("Customers found with findByLastName('Smith'):"); + System.out.println("--------------------------------"); + for (Customer customer : this.repository.findByLastName("Smith")) { + System.out.println(customer); + } + } + + public static void main(String[] args) { + SpringApplication.run(SampleCassandraApplication.class, args); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/resources/application.properties b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/resources/application.properties new file mode 100644 index 00000000000..74ed2fea557 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/main/resources/application.properties @@ -0,0 +1 @@ +spring.data.cassandra.keyspace-name=mykeyspace diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/java/sample/data/cassandra/SampleCassandraApplicationTests.java b/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/java/sample/data/cassandra/SampleCassandraApplicationTests.java new file mode 100644 index 00000000000..fe55131dd0d --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/java/sample/data/cassandra/SampleCassandraApplicationTests.java @@ -0,0 +1,55 @@ +/* + * Copyright 2012-2015 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 sample.data.cassandra; + +import org.cassandraunit.spring.CassandraDataSet; +import org.cassandraunit.spring.CassandraUnitTestExecutionListener; +import org.cassandraunit.spring.EmbeddedCassandra; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.IntegrationTest; +import org.springframework.boot.test.OutputCapture; +import org.springframework.boot.test.SpringApplicationConfiguration; +import org.springframework.test.context.TestExecutionListeners; +import org.springframework.test.context.TestExecutionListeners.MergeMode; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import static org.junit.Assert.assertTrue; + +/** + * Tests for {@link SampleCassandraApplication}. + */ +@RunWith(SpringJUnit4ClassRunner.class) +@TestExecutionListeners(mergeMode = MergeMode.MERGE_WITH_DEFAULTS, listeners = CassandraUnitTestExecutionListener.class) +@SpringApplicationConfiguration(SampleCassandraApplication.class) +@IntegrationTest +@CassandraDataSet(keyspace = "mykeyspace", value = "setup.cql") +@EmbeddedCassandra +public class SampleCassandraApplicationTests { + + @ClassRule + public static OutputCapture outputCapture = new OutputCapture(); + + @Test + public void testDefaultSettings() throws Exception { + String output = SampleCassandraApplicationTests.outputCapture.toString(); + assertTrue("Wrong output: " + output, + output.contains("firstName='Alice', lastName='Smith'")); + } + +} diff --git a/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/resources/setup.cql b/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/resources/setup.cql new file mode 100644 index 00000000000..de52ba67df7 --- /dev/null +++ b/spring-boot-samples/spring-boot-sample-data-cassandra/src/test/resources/setup.cql @@ -0,0 +1,3 @@ +CREATE TABLE customer (id TimeUUID PRIMARY KEY, firstname text, lastname text); +CREATE INDEX customerfistnameindex ON customer (firstname); +CREATE INDEX customersecondnameindex ON customer (lastname); diff --git a/spring-boot-starters/pom.xml b/spring-boot-starters/pom.xml index d43c5dc2627..493d9c6493e 100644 --- a/spring-boot-starters/pom.xml +++ b/spring-boot-starters/pom.xml @@ -27,6 +27,7 @@ spring-boot-starter-batch spring-boot-starter-cache spring-boot-starter-cloud-connectors + spring-boot-starter-data-cassandra spring-boot-starter-data-elasticsearch spring-boot-starter-data-gemfire spring-boot-starter-data-jpa diff --git a/spring-boot-starters/spring-boot-starter-data-cassandra/pom.xml b/spring-boot-starters/spring-boot-starter-data-cassandra/pom.xml new file mode 100644 index 00000000000..4fd92169d2f --- /dev/null +++ b/spring-boot-starters/spring-boot-starter-data-cassandra/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + org.springframework.boot + spring-boot-starters + 1.3.0.BUILD-SNAPSHOT + + spring-boot-starter-data-cassandra + Spring Boot Data Cassandra Starter + Spring Boot Data Cassandra Starter + http://projects.spring.io/spring-boot/ + + Pivotal Software, Inc. + http://www.spring.io + + + ${basedir}/../.. + + + + org.springframework.boot + spring-boot-starter + + + org.springframework + spring-tx + + + org.springframework.data + spring-data-cassandra + + + diff --git a/spring-boot-starters/spring-boot-starter-data-cassandra/src/main/resources/META-INF/spring.provides b/spring-boot-starters/spring-boot-starter-data-cassandra/src/main/resources/META-INF/spring.provides new file mode 100644 index 00000000000..baf0a5ef88c --- /dev/null +++ b/spring-boot-starters/spring-boot-starter-data-cassandra/src/main/resources/META-INF/spring.provides @@ -0,0 +1 @@ +provides: spring-data-cassandra \ No newline at end of file