diff --git a/.travis.yml b/.travis.yml
index 9f82cf44..41503a71 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,6 +5,7 @@ jdk:
services:
- redis-server
+ - cassandra
cache:
directories:
@@ -14,4 +15,4 @@ sudo: false
install: true
-script: "mvn clean dependency:list test -Dsort"
\ No newline at end of file
+script: "mvn clean dependency:list test -Dsort"
diff --git a/cassandra/example/Readme.MD b/cassandra/example/Readme.MD
index ed96c1d5..be5d0a2b 100644
--- a/cassandra/example/Readme.MD
+++ b/cassandra/example/Readme.MD
@@ -6,8 +6,6 @@
Before we can start we have to install Cassandra, e.g. via brew on Max OS.
```
brew install cassandra
-pip install cassandra-driver
-brew install cassandra-driver
More details can be found here: https://wiki.apache.org/cassandra/GettingStarted
```
@@ -17,26 +15,5 @@ More details can be found here: https://wiki.apache.org/cassandra/GettingStarted
/usr/local/bin/cassandra -f
```
-### Start a Cassandra shell cqlsh
-```
-/usr/local/bin/cqlsh
-```
-
-### Setup Keyspace and Tables
-
-```
-CREATE KEYSPACE example
-WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };
-
-USE example;
-
-CREATE TABLE users (
- user_id int PRIMARY KEY,
- uname text,
- fname text,
- lname text
-);
-```
-
That should be enough to get you started.
-Now you can simply type ```mvn clean install``` to run the example.
\ No newline at end of file
+Now you can simply type ```mvn clean install``` to run the example.
diff --git a/cassandra/example/pom.xml b/cassandra/example/pom.xml
index 5caab14a..d3624fcc 100644
--- a/cassandra/example/pom.xml
+++ b/cassandra/example/pom.xml
@@ -12,6 +12,22 @@
Spring Data Cassandra - Example
- Small sample project showing the usage of Spring Data Cassandra.
-
+ Basic sample project showing the usage of Spring Data Cassandra.
+
+
+
+
+ ${project.groupId}
+ spring-data-cassandra-example-utils
+ ${project.version}
+ test
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+
+
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/SimpleConfiguration.java b/cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicConfiguration.java
similarity index 65%
rename from cassandra/example/src/main/java/example/springdata/cassandra/SimpleConfiguration.java
rename to cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicConfiguration.java
index 259934a2..38a27f8a 100644
--- a/cassandra/example/src/main/java/example/springdata/cassandra/SimpleConfiguration.java
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicConfiguration.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 the original author or authors.
+ * Copyright 2013-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.
@@ -13,37 +13,51 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package example.springdata.cassandra;
+package example.springdata.cassandra.basic;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.cassandra.config.java.AbstractCqlTemplateConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import org.springframework.data.cassandra.config.SchemaAction;
+import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
import com.datastax.driver.core.Session;
/**
+ * Basic {@link Configuration} to create the necessary schema for the {@link User} table.
+ *
* @author Oliver Gierke
* @author Thomas Darimont
+ * @author Mark Paluch
*/
@Configuration
@EnableAutoConfiguration
-class SimpleConfiguration {
+class BasicConfiguration {
@Configuration
@EnableCassandraRepositories
- static class CassandraConfig extends AbstractCqlTemplateConfiguration {
+ static class CassandraConfig extends AbstractCassandraConfiguration {
@Override
public String getKeyspaceName() {
return "example";
}
-
+
@Bean
public CassandraTemplate cassandraTemplate(Session session) {
return new CassandraTemplate(session);
}
+
+ @Override
+ public String[] getEntityBasePackages() {
+ return new String[] { User.class.getPackage().getName() };
+ }
+
+ @Override
+ public SchemaAction getSchemaAction() {
+ return SchemaAction.RECREATE;
+ }
}
}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicUserRepository.java b/cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicUserRepository.java
new file mode 100644
index 00000000..a02b580a
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/basic/BasicUserRepository.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2013-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 example.springdata.cassandra.basic;
+
+import java.util.List;
+
+import org.springframework.data.cassandra.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Simple repository interface for {@link User} instances. The interface is used to declare so called query methods,
+ * methods to retrieve single entities or collections of them.
+ *
+ * @author Thomas Darimont
+ */
+public interface BasicUserRepository extends CrudRepository {
+
+ /**
+ * Sample method annotated with {@link Query}. This method executes the CQL from the {@link Query} value.
+ *
+ * @param id
+ * @return
+ */
+ @Query("SELECT * from users where user_id in(?0)")
+ User findUserByIdIn(long id);
+
+ /**
+ * Derived query method. This query corresponds with {@code SELECT * FROM users WHERE uname = ?0}.
+ * {@link User#username} is not part of the primary so it requires a secondary index.
+ *
+ * @param username
+ * @return
+ */
+ User findUserByUsername(String username);
+
+ /**
+ * Derived query method using SASI (SSTable Attached Secondary Index) features through the {@code LIKE} keyword. This
+ * query corresponds with {@code SELECT * FROM users WHERE uname LIKE '?0%'}. {@link User#username} is not part of the
+ * primary so it requires a secondary index.
+ *
+ * @param lastnamePrefix
+ * @return
+ */
+ List findUsersByLastnameStartsWith(String lastnamePrefix);
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/User.java b/cassandra/example/src/main/java/example/springdata/cassandra/basic/User.java
similarity index 92%
rename from cassandra/example/src/main/java/example/springdata/cassandra/User.java
rename to cassandra/example/src/main/java/example/springdata/cassandra/basic/User.java
index e4662e1f..7203c6b3 100644
--- a/cassandra/example/src/main/java/example/springdata/cassandra/User.java
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/basic/User.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 2013-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.
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package example.springdata.cassandra;
+package example.springdata.cassandra.basic;
import lombok.Data;
import lombok.NoArgsConstructor;
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/package-info.java b/cassandra/example/src/main/java/example/springdata/cassandra/basic/package-info.java
similarity index 71%
rename from cassandra/example/src/main/java/example/springdata/cassandra/package-info.java
rename to cassandra/example/src/main/java/example/springdata/cassandra/basic/package-info.java
index 6e1df637..177b26e6 100644
--- a/cassandra/example/src/main/java/example/springdata/cassandra/package-info.java
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/basic/package-info.java
@@ -1,5 +1,5 @@
/**
* Package showing a simple repository interface to use basic query method execution functionality.
*/
-package example.springdata.cassandra;
+package example.springdata.cassandra.basic;
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/SimpleUserRepository.java b/cassandra/example/src/main/java/example/springdata/cassandra/convert/Addressbook.java
similarity index 57%
rename from cassandra/example/src/main/java/example/springdata/cassandra/SimpleUserRepository.java
rename to cassandra/example/src/main/java/example/springdata/cassandra/convert/Addressbook.java
index 3989172f..0caff593 100644
--- a/cassandra/example/src/main/java/example/springdata/cassandra/SimpleUserRepository.java
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/convert/Addressbook.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2013-2014 the original author or authors.
+ * Copyright 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.
@@ -13,14 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package example.springdata.cassandra;
+package example.springdata.cassandra.convert;
-import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.annotation.Id;
+import org.springframework.data.cassandra.mapping.Table;
+
+import lombok.Data;
+
+import java.util.List;
/**
- * Simple repository interface for {@link User} instances. The interface is used to declare so called query methods,
- * methods to retrieve single entities or collections of them.
+ * Sample Addressbook class.
*
- * @author Thomas Darimont
+ * @author Mark Paluch
*/
-public interface SimpleUserRepository extends CrudRepository {}
+@Data
+@Table
+public class Addressbook {
+
+ @Id String id;
+
+ Contact me;
+ List friends;
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/convert/Contact.java b/cassandra/example/src/main/java/example/springdata/cassandra/convert/Contact.java
new file mode 100644
index 00000000..1a4ebf58
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/convert/Contact.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 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 example.springdata.cassandra.convert;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * Sample Contact class.
+ *
+ * @author Mark Paluch
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class Contact {
+
+ String firstname;
+ String lastname;
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/convert/ConverterConfiguration.java b/cassandra/example/src/main/java/example/springdata/cassandra/convert/ConverterConfiguration.java
new file mode 100644
index 00000000..b813798b
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/convert/ConverterConfiguration.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright 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 example.springdata.cassandra.convert;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.convert.converter.Converter;
+import org.springframework.data.cassandra.config.SchemaAction;
+import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
+import org.springframework.data.cassandra.convert.CustomConversions;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+import org.springframework.util.StringUtils;
+
+import com.datastax.driver.core.Row;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * {@link Configuration} class to register custom converters.
+ *
+ * @author Mark Paluch
+ */
+@Configuration
+@EnableCassandraRepositories
+class ConverterConfiguration extends AbstractCassandraConfiguration {
+
+ @Override
+ public String getKeyspaceName() {
+ return "example";
+ }
+
+ @Override
+ public String[] getEntityBasePackages() {
+ return new String[] { Addressbook.class.getPackage().getName() };
+ }
+
+ @Override
+ public SchemaAction getSchemaAction() {
+ return SchemaAction.RECREATE;
+ }
+
+ @Override
+ public CustomConversions customConversions() {
+
+ List> converters = new ArrayList<>();
+ converters.add(new PersonWriteConverter());
+ converters.add(new PersonReadConverter());
+ converters.add(new CustomAddressbookReadConverter());
+
+ return new CustomConversions(converters);
+ }
+
+ /**
+ * Write a {@link Contact} into its {@link String} representation.
+ */
+ static class PersonWriteConverter implements Converter {
+
+ public String convert(Contact source) {
+
+ try {
+ return new ObjectMapper().writeValueAsString(source);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ /**
+ * Read a {@link Contact} from its {@link String} representation.
+ */
+ static class PersonReadConverter implements Converter {
+
+ public Contact convert(String source) {
+
+ if (StringUtils.hasText(source)) {
+ try {
+ return new ObjectMapper().readValue(source, Contact.class);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+ return null;
+ }
+ }
+
+ /**
+ * Perform custom mapping by reading a {@link Row} into a custom class.
+ */
+ static class CustomAddressbookReadConverter implements Converter {
+
+ public CustomAddressbook convert(Row source) {
+
+ CustomAddressbook result = new CustomAddressbook();
+
+ result.setTheId(source.getString("id"));
+ result.setMyDetailsAsJson(source.getString("me"));
+
+ return result;
+ }
+ }
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/convert/CustomAddressbook.java b/cassandra/example/src/main/java/example/springdata/cassandra/convert/CustomAddressbook.java
new file mode 100644
index 00000000..3a0e15ea
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/convert/CustomAddressbook.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 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 example.springdata.cassandra.convert;
+
+import lombok.Data;
+
+/**
+ * @author Mark Paluch
+ */
+@Data
+public class CustomAddressbook {
+
+ String theId;
+ String myDetailsAsJson;
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/convert/package-info.java b/cassandra/example/src/main/java/example/springdata/cassandra/convert/package-info.java
new file mode 100644
index 00000000..414f660e
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/convert/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Package showing conversion features.
+ */
+package example.springdata.cassandra.convert;
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/Customer.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/Customer.java
new file mode 100644
index 00000000..8255dfb3
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/Customer.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.cassandra.mapping.Table;
+
+import lombok.Value;
+
+/**
+ * @author Mark Paluch
+ */
+@Value
+@Table
+class Customer {
+
+ @Id String id;
+ String firstname, lastname;
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerProjection.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerProjection.java
new file mode 100644
index 00000000..4a2f9d36
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerProjection.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+/**
+ * An example projection interface containing only the firstname.
+ *
+ * @author Mark Paluch
+ */
+interface CustomerProjection {
+
+ String getFirstname();
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerRepository.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerRepository.java
new file mode 100644
index 00000000..fee61443
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerRepository.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+import java.util.Collection;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.repository.CrudRepository;
+
+/**
+ * Sample repository managing customers to show projecting functionality of Spring Data Cassandra.
+ *
+ * @author Mark Paluch
+ */
+interface CustomerRepository extends CrudRepository {
+
+ /**
+ * Uses a projection interface to indicate the fields to be returned. As the projection doesn't use any dynamic
+ * fields, the query execution will be restricted to only the fields needed by the projection.
+ *
+ * @return
+ */
+ Collection findAllProjectedBy();
+
+ /**
+ * When a projection is used that contains dynamic properties (i.e. SpEL expressions in an {@link Value} annotation),
+ * the normal target entity will be loaded but dynamically projected so that the target can be referred to in the
+ * expression.
+ *
+ * @return
+ */
+ Collection findAllSummarizedBy();
+
+ /**
+ * Passes in the projection type dynamically.
+ *
+ * @param id
+ * @param projection
+ * @return
+ */
+ Collection findById(String id, Class projection);
+
+ /**
+ * Projection for a single entity.
+ *
+ * @param id
+ * @return
+ */
+ CustomerProjection findProjectedById(String id);
+
+ /**
+ * Dynamic projection for a single entity.
+ *
+ * @param id
+ * @param projection
+ * @return
+ */
+ T findProjectedById(String id, Class projection);
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerSummary.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerSummary.java
new file mode 100644
index 00000000..f0a5c816
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/CustomerSummary.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+import org.springframework.beans.factory.annotation.Value;
+
+/**
+ * An example of using SpEL with projections.
+ *
+ * @author Mark Paluch
+ */
+interface CustomerSummary {
+
+ @Value("#{target.firstname + ' ' + target.lastname}")
+ String getFullName();
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/ProjectionConfiguration.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/ProjectionConfiguration.java
new file mode 100644
index 00000000..0758a458
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/ProjectionConfiguration.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.cassandra.config.SchemaAction;
+import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
+import org.springframework.data.cassandra.core.CassandraTemplate;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+
+import com.datastax.driver.core.Session;
+
+import example.springdata.cassandra.basic.User;
+
+/**
+ * Basic {@link Configuration} to create the necessary schema for the {@link Customer} table.
+ *
+ * @author Mark Paluch
+ */
+@Configuration
+@EnableAutoConfiguration
+class ProjectionConfiguration {
+
+ @Configuration
+ @EnableCassandraRepositories
+ static class CassandraConfig extends AbstractCassandraConfiguration {
+
+ @Override
+ public String getKeyspaceName() {
+ return "example";
+ }
+
+ @Override
+ public String[] getEntityBasePackages() {
+ return new String[] { Customer.class.getPackage().getName() };
+ }
+
+ @Override
+ public SchemaAction getSchemaAction() {
+ return SchemaAction.RECREATE;
+ }
+ }
+}
diff --git a/cassandra/example/src/main/java/example/springdata/cassandra/projection/package-info.java b/cassandra/example/src/main/java/example/springdata/cassandra/projection/package-info.java
new file mode 100644
index 00000000..e81c8c64
--- /dev/null
+++ b/cassandra/example/src/main/java/example/springdata/cassandra/projection/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Package showing projection features.
+ */
+package example.springdata.cassandra.projection;
diff --git a/cassandra/example/src/test/java/example/springdata/cassandra/SimpleUserRepositoryTests.java b/cassandra/example/src/test/java/example/springdata/cassandra/SimpleUserRepositoryTests.java
deleted file mode 100644
index 8fad8bac..00000000
--- a/cassandra/example/src/test/java/example/springdata/cassandra/SimpleUserRepositoryTests.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2013-2014 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 example.springdata.cassandra;
-
-import static org.hamcrest.CoreMatchers.*;
-import static org.junit.Assert.*;
-
-import example.springdata.cassandra.SimpleConfiguration;
-import example.springdata.cassandra.SimpleUserRepository;
-import example.springdata.cassandra.User;
-
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.test.context.ContextConfiguration;
-import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
-/**
- * Integration test showing the basic usage of {@link SimpleUserRepository}.
- *
- * @author Oliver Gierke
- * @author Thomas Darimont
- * @author Christoph Strobl
- */
-@Ignore
-@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(classes = SimpleConfiguration.class)
-public class SimpleUserRepositoryTests {
-
- @Autowired SimpleUserRepository repository;
- User user;
-
- @Before
- public void setUp() {
-
- user = new User();
- user.setId(42L);
- user.setUsername("foobar");
- user.setFirstname("firstname");
- user.setLastname("lastname");
- }
-
- @Test
- public void findSavedUserById() {
-
- user = repository.save(user);
-
- assertThat(repository.findOne(user.getId()), is(user));
- }
-}
diff --git a/cassandra/example/src/test/java/example/springdata/cassandra/basic/BasicUserRepositoryTests.java b/cassandra/example/src/test/java/example/springdata/cassandra/basic/BasicUserRepositoryTests.java
new file mode 100644
index 00000000..bcb98018
--- /dev/null
+++ b/cassandra/example/src/test/java/example/springdata/cassandra/basic/BasicUserRepositoryTests.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2013-2014 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 example.springdata.cassandra.basic;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+import static org.junit.Assume.*;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.util.Version;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.datastax.driver.core.Session;
+
+import example.springdata.cassandra.util.CassandraVersion;
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+
+/**
+ * Integration test showing the basic usage of {@link BasicUserRepository}.
+ *
+ * @author Oliver Gierke
+ * @author Thomas Darimont
+ * @author Christoph Strobl
+ * @author Mark Paluch
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = BasicConfiguration.class)
+public class BasicUserRepositoryTests {
+
+ public final static Version CASSANDRA_3_4 = Version.parse("3.4");
+
+ @ClassRule public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost();
+
+ @Autowired BasicUserRepository repository;
+ @Autowired Session session;
+ User user;
+
+ @Before
+ public void setUp() {
+
+ user = new User();
+ user.setId(42L);
+ user.setUsername("foobar");
+ user.setFirstname("firstname");
+ user.setLastname("lastname");
+ }
+
+ /**
+ * Saving an object using the Cassandra Repository will create a persistent representation of the object in Cassandra.
+ */
+ @Test
+ public void findSavedUserById() {
+
+ user = repository.save(user);
+
+ assertThat(repository.findOne(user.getId()), is(user));
+ }
+
+ /**
+ * Cassandra can be queries by using query methods annotated with {@link @Query}.
+ */
+ @Test
+ public void findByAnnotatedQueryMethod() {
+
+ repository.save(user);
+
+ assertThat(repository.findUserByIdIn(1000), is(nullValue()));
+ assertThat(repository.findUserByIdIn(42), is(equalTo(user)));
+ }
+
+ /**
+ * Spring Data Cassandra supports query derivation so annotating query methods with
+ * {@link org.springframework.data.cassandra.repository.Query} is optional. Querying columns other than the primary
+ * key requires a secondary index.
+ */
+ @Test
+ public void findByDerivedQueryMethod() throws InterruptedException {
+
+ session.execute("CREATE INDEX IF NOT EXISTS user_username ON users (uname);");
+ /*
+ Cassandra secondary indexes are created in the background without the possibility to check
+ whether they are available or not. So we are forced to just wait. *sigh*
+ */
+ Thread.sleep(1000);
+
+ repository.save(user);
+
+ assertThat(repository.findUserByUsername(user.getUsername()), is(user));
+ }
+
+ /**
+ * Spring Data Cassandra supports {@code LIKE} and {@code CONTAINS} query keywords to for SASI indexes.
+ */
+ @Test
+ public void findByDerivedQueryMethodWithSASI() throws InterruptedException {
+
+ assumeTrue(CassandraVersion.getReleaseVersion(session).isGreaterThanOrEqualTo(CASSANDRA_3_4));
+
+ session.execute("CREATE CUSTOM INDEX ON users (lname) USING 'org.apache.cassandra.index.sasi.SASIIndex';");
+ /*
+ Cassandra secondary indexes are created in the background without the possibility to check
+ whether they are available or not. So we are forced to just wait. *sigh*
+ */
+ Thread.sleep(1000);
+
+ repository.save(user);
+
+ assertThat(repository.findUsersByLastnameStartsWith("last"), hasItem(user));
+ }
+}
diff --git a/cassandra/example/src/test/java/example/springdata/cassandra/basic/CassandraOperationsIntegrationTests.java b/cassandra/example/src/test/java/example/springdata/cassandra/basic/CassandraOperationsIntegrationTests.java
new file mode 100644
index 00000000..ee007a7a
--- /dev/null
+++ b/cassandra/example/src/test/java/example/springdata/cassandra/basic/CassandraOperationsIntegrationTests.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 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 example.springdata.cassandra.basic;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.cassandra.core.CassandraOperations;
+import org.springframework.data.cassandra.core.CassandraTemplate;
+import org.springframework.data.cassandra.core.WriteListener;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.querybuilder.Insert;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+
+/**
+ * Integration test showing the basic usage of {@link CassandraTemplate}.
+ *
+ * @author Mark Paluch
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = BasicConfiguration.CassandraConfig.class)
+public class CassandraOperationsIntegrationTests {
+
+ @ClassRule public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost();
+
+ @Autowired CassandraOperations template;
+
+ @Before
+ public void setUp() throws Exception {
+ template.truncate("users");
+ }
+
+ /**
+ * Cassandra {@link com.datastax.driver.core.Statement}s can be used together with {@link CassandraTemplate} and the
+ * mapping layer.
+ */
+ @Test
+ public void insertAndSelect() {
+
+ Insert insert = QueryBuilder.insertInto("users").value("user_id", 42L) //
+ .value("uname", "heisenberg") //
+ .value("fname", "Walter") //
+ .value("lname", "White") //
+ .ifNotExists(); //
+
+ template.execute(insert);
+
+ User user = template.selectOneById(User.class, 42L);
+ assertThat(user.getUsername(), is(equalTo("heisenberg")));
+
+ List users = template.select(QueryBuilder.select().from("users"), User.class);
+ assertThat(users, hasSize(1));
+ assertThat(users.get(0), is(equalTo(user)));
+ }
+
+ /**
+ * Objects can be inserted and updated using {@link CassandraTemplate}. What you {@code update} is what you
+ * {@code select}.
+ */
+ @Test
+ public void insertAndUpdate() {
+
+ User user = new User();
+ user.setId(42L);
+ user.setUsername("heisenberg");
+ user.setFirstname("Walter");
+ user.setLastname("White");
+
+ template.insert(user);
+
+ user.setFirstname(null);
+ template.update(user);
+
+ User loaded = template.selectOneById(User.class, 42L);
+ assertThat(loaded.getUsername(), is(equalTo("heisenberg")));
+ assertThat(loaded.getFirstname(), is(nullValue()));
+ }
+
+ /**
+ * Asynchronous query execution using callbacks.
+ */
+ @Test
+ public void insertAsynchronously() throws InterruptedException {
+
+ User user = new User();
+ user.setId(42L);
+ user.setUsername("heisenberg");
+ user.setFirstname("Walter");
+ user.setLastname("White");
+
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ template.insertAsynchronously(user, new WriteListener() {
+
+ @Override
+ public void onWriteComplete(Collection entities) {
+ countDownLatch.countDown();
+ }
+
+ @Override
+ public void onException(Exception x) {}
+ });
+
+ countDownLatch.await(5, TimeUnit.SECONDS);
+
+ User loaded = template.selectOneById(User.class, user.getId());
+ assertThat(loaded, is(equalTo(user)));
+ }
+
+ /**
+ * {@link CassandraTemplate} allows selection of projections on template-level. All basic data types including
+ * {@link Row} can be selected.
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ public void selectProjections() {
+
+ User user = new User();
+ user.setId(42L);
+ user.setUsername("heisenberg");
+ user.setFirstname("Walter");
+ user.setLastname("White");
+
+ template.insert(user);
+
+ Long id = template.selectOne(QueryBuilder.select("user_id").from("users"), Long.class);
+ assertThat(id, is(user.getId()));
+
+ Row row = template.selectOne(QueryBuilder.select("user_id").from("users"), Row.class);
+ assertThat(row.getLong(0), is(user.getId()));
+
+ Map map = template.selectOne(QueryBuilder.select().from("users"), Map.class);
+ assertThat(map, hasEntry("user_id", user.getId()));
+ assertThat(map, hasEntry("fname", "Walter"));
+ }
+}
diff --git a/cassandra/example/src/test/java/example/springdata/cassandra/convert/ConversionIntegrationTests.java b/cassandra/example/src/test/java/example/springdata/cassandra/convert/ConversionIntegrationTests.java
new file mode 100644
index 00000000..7ea4777d
--- /dev/null
+++ b/cassandra/example/src/test/java/example/springdata/cassandra/convert/ConversionIntegrationTests.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 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 example.springdata.cassandra.convert;
+
+import static org.hamcrest.MatcherAssert.*;
+import static org.hamcrest.Matchers.*;
+
+import java.util.Arrays;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.cassandra.core.CassandraOperations;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.querybuilder.QueryBuilder;
+
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+
+/**
+ * @author Mark Paluch
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = ConverterConfiguration.class)
+public class ConversionIntegrationTests {
+
+ @ClassRule public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost();
+
+ @Autowired CassandraOperations operations;
+
+ @Before
+ public void setUp() throws Exception {
+ operations.truncate("addressbook");
+ }
+
+ /**
+ * Creates and stores a new {@link Addressbook} inside of Cassandra. {@link Contact} classes are converted using the
+ * custom {@link example.springdata.cassandra.convert.ConverterConfiguration.PersonWriteConverter}.
+ */
+ @Test
+ public void shouldCreateAddressbook() {
+
+ Addressbook addressbook = new Addressbook();
+ addressbook.setId("private");
+
+ addressbook.setMe(new Contact("Walter", "White"));
+ addressbook.setFriends(Arrays.asList(new Contact("Jesse", "Pinkman"), new Contact("Saul", "Goodman")));
+
+ operations.insert(addressbook);
+
+ Row row = operations.selectOne(QueryBuilder.select().from("addressbook"), Row.class);
+
+ assertThat(row, is(notNullValue()));
+
+ assertThat(row.getString("id"), is(equalTo("private")));
+ assertThat(row.getString("me"), containsString("\"firstname\":\"Walter\""));
+ assertThat(row.getList("friends", String.class), hasSize(2));
+ }
+
+ /**
+ * Creates and loads a new {@link Addressbook} inside of Cassandra. {@link Contact} classes are converted using the
+ * custom {@link example.springdata.cassandra.convert.ConverterConfiguration.PersonReadConverter}.
+ */
+ @Test
+ public void shouldReadAddressbook() {
+
+ Addressbook addressbook = new Addressbook();
+ addressbook.setId("private");
+
+ addressbook.setMe(new Contact("Walter", "White"));
+ addressbook.setFriends(Arrays.asList(new Contact("Jesse", "Pinkman"), new Contact("Saul", "Goodman")));
+
+ operations.insert(addressbook);
+
+ Addressbook loaded = operations.selectOne(QueryBuilder.select().from("addressbook"), Addressbook.class);
+
+ assertThat(loaded.getMe(), is(equalTo(addressbook.getMe())));
+ assertThat(loaded.getFriends(), is(equalTo(addressbook.getFriends())));
+ }
+
+ /**
+ * Creates and stores a new {@link Addressbook} inside of Cassandra. The {@link Addressbook} is read back to a
+ * {@link CustomAddressbook} class using the
+ * {@link example.springdata.cassandra.convert.ConverterConfiguration.CustomAddressbookReadConverter}.
+ */
+ @Test
+ public void shouldReadCustomAddressbook() {
+
+ Addressbook addressbook = new Addressbook();
+ addressbook.setId("private");
+
+ addressbook.setMe(new Contact("Walter", "White"));
+
+ operations.insert(addressbook);
+
+ CustomAddressbook loaded = operations.selectOne(QueryBuilder.select().from("addressbook"), CustomAddressbook.class);
+
+ assertThat(loaded.getTheId(), is(equalTo(addressbook.getId())));
+ assertThat(loaded.getMyDetailsAsJson(), containsString("\"firstname\":\"Walter\""));
+ }
+}
diff --git a/cassandra/example/src/test/java/example/springdata/cassandra/projection/CustomerRepositoryIntegrationTest.java b/cassandra/example/src/test/java/example/springdata/cassandra/projection/CustomerRepositoryIntegrationTest.java
new file mode 100644
index 00000000..cf197fc9
--- /dev/null
+++ b/cassandra/example/src/test/java/example/springdata/cassandra/projection/CustomerRepositoryIntegrationTest.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 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 example.springdata.cassandra.projection;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Collection;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.projection.TargetAware;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+
+/**
+ * Integration tests for {@link CustomerRepository} to show projection capabilities.
+ *
+ * @author Mark Paluch
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = ProjectionConfiguration.class)
+public class CustomerRepositoryIntegrationTest {
+
+ @ClassRule public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost();
+
+ @Autowired CustomerRepository customers;
+
+ Customer dave, carter;
+
+ @Before
+ public void setUp() {
+
+ customers.deleteAll();
+
+ this.dave = customers.save(new Customer("d", "Dave", "Matthews"));
+ this.carter = customers.save(new Customer("c", "Carter", "Beauford"));
+ }
+
+ @Test
+ public void projectsEntityIntoInterface() {
+
+ Collection result = customers.findAllProjectedBy();
+
+ assertThat(result, hasSize(2));
+ assertThat(result.iterator().next().getFirstname(), is("Carter"));
+ }
+
+ @Test
+ public void projectsDynamically() {
+
+ Collection result = customers.findById("d", CustomerProjection.class);
+
+ assertThat(result, hasSize(1));
+ assertThat(result.iterator().next().getFirstname(), is("Dave"));
+ }
+
+ @Test
+ public void projectsIndividualDynamically() {
+
+ CustomerSummary result = customers.findProjectedById(dave.getId(), CustomerSummary.class);
+
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getFullName(), is("Dave Matthews"));
+
+ // Proxy backed by original instance as the projection uses dynamic elements
+ assertThat(((TargetAware) result).getTarget(), is(instanceOf(Customer.class)));
+ }
+
+ @Test
+ public void projectIndividualInstance() {
+
+ CustomerProjection result = customers.findProjectedById(dave.getId());
+
+ assertThat(result, is(notNullValue()));
+ assertThat(result.getFirstname(), is("Dave"));
+ assertThat(((TargetAware) result).getTarget(), is(instanceOf(Customer.class)));
+ }
+
+}
diff --git a/cassandra/java8/README.md b/cassandra/java8/README.md
new file mode 100644
index 00000000..26043af9
--- /dev/null
+++ b/cassandra/java8/README.md
@@ -0,0 +1,36 @@
+# Spring Data Cassandra - Java 8 examples
+
+This project contains samples of Java 8 specific features of Spring Data (Cassandra).
+
+## Support for JDK 8's `Stream` for repository methods
+
+Repository methods can use a Java 8 `Stream` as a return type which will cause the reading of the results and the to-object-conversion of rows to happen while iterating over the stream.
+
+```java
+public interface PersonRepository extends CrudRepository {
+
+ @Override
+ List findAll();
+
+ //Custom Query method returning a Java 8 Stream
+ @Query("SELECT * FROM person")
+ Stream findAllByCustomQueryWithStream();
+}
+```
+
+The test cases in `PersonRepositoryIntegrationTest` oppose a plain `List` based query method with one that uses a `Stream` and shows how the former pulls all data into memory first and the iteration is done over the pre-populated list. The execution of the `Stream`-based method in contrast shows that the individual elements are read and converted while iterating the stream.
+
+## Preparation
+
+### Install Cassandra
+Before we can start we have to install Cassandra, e.g. via brew on Max OS.
+
+More details can be found here: https://wiki.apache.org/cassandra/GettingStarted
+
+### Start Cassandra
+```
+/usr/local/bin/cassandra -f
+```
+
+That should be enough to get you started.
+Now you can simply type ```mvn clean install``` to run the example.
diff --git a/cassandra/java8/pom.xml b/cassandra/java8/pom.xml
new file mode 100644
index 00000000..6bbc36bf
--- /dev/null
+++ b/cassandra/java8/pom.xml
@@ -0,0 +1,26 @@
+
+ 4.0.0
+
+
+ org.springframework.data.examples
+ spring-data-cassandra-examples
+ 1.0.0.BUILD-SNAPSHOT
+ ../pom.xml
+
+
+ spring-data-cassandra-java8
+ Spring Data Cassandra - Java 8 specific features
+
+
+
+
+ ${project.groupId}
+ spring-data-cassandra-example-utils
+ ${project.version}
+ test
+
+
+
+
+
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/CassandraConfiguration.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/CassandraConfiguration.java
new file mode 100644
index 00000000..c008c8a8
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/CassandraConfiguration.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.cassandra.config.SchemaAction;
+import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration;
+import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
+
+/**
+ * @author Mark Paluch
+ */
+@Configuration
+@EnableAutoConfiguration
+class CassandraConfiguration {
+
+ @Configuration
+ @EnableCassandraRepositories
+ static class CassandraConfig extends AbstractCassandraConfiguration {
+
+ @Override
+ public String getKeyspaceName() {
+ return "example";
+ }
+
+ @Override
+ public SchemaAction getSchemaAction() {
+ return SchemaAction.RECREATE;
+ }
+ }
+}
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Order.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Order.java
new file mode 100644
index 00000000..eda71bd9
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Order.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.cassandra.mapping.Table;
+
+/**
+ * @author Mark Paluch
+ */
+@Table("pizza_orders")
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Order {
+
+ @Id String id;
+ LocalDate orderDate;
+ ZoneId zoneId;
+}
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/OrderRepository.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/OrderRepository.java
new file mode 100644
index 00000000..365db253
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/OrderRepository.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+
+import org.springframework.data.cassandra.mapping.CassandraType;
+import org.springframework.data.cassandra.repository.Query;
+import org.springframework.data.repository.Repository;
+
+/**
+ * Repository to manage {@link Order} instances.
+ *
+ * @author Mark Paluch
+ */
+public interface OrderRepository extends Repository {
+
+ /**
+ * Method parameters are converted according the registered Converters into Cassandra types.
+ */
+ @Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING")
+ Order findOrderByOrderDateAndZoneId(LocalDate orderDate, ZoneId zoneId);
+
+ /**
+ * Parameter conversion can be overridden by using the {@link CassandraType} annotation.
+ */
+ @Query("SELECT * from pizza_orders WHERE orderdate = ?0 and zoneid = ?1 ALLOW FILTERING")
+ Order findOrderByDate(com.datastax.driver.core.LocalDate orderDate, String zoneId);
+
+ void deleteAll();
+
+ Order save(Order order);
+}
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Person.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Person.java
new file mode 100644
index 00000000..a313f24d
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/Person.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import org.springframework.data.annotation.Id;
+import org.springframework.data.cassandra.mapping.Table;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author Mark Paluch
+ */
+@Table
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Person {
+
+ @Id String id;
+ String firstname, lastname;
+}
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/PersonRepository.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/PersonRepository.java
new file mode 100644
index 00000000..1bf32c95
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/PersonRepository.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import java.util.Optional;
+import java.util.stream.Stream;
+
+import org.springframework.data.cassandra.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.Repository;
+
+/**
+ * Repository to manage {@link Person} instances.
+ *
+ * @author Mark Paluch
+ */
+public interface PersonRepository extends Repository {
+
+ /**
+ * Special customization of {@link CrudRepository#findOne(java.io.Serializable)} to return a JDK 8 {@link Optional}.
+ *
+ * @param id
+ * @return
+ */
+ Optional findOne(String id);
+
+ @Query("select * from person")
+ Stream streamAllPeople();
+
+ /**
+ * Sample method to derive a query from using JDK 8's {@link Optional} as return type.
+ *
+ * @param id
+ * @return
+ */
+ @Query("select * from person where id = ?0")
+ Optional findById(String id);
+
+ /**
+ * Sample default method to show JDK 8 feature support.
+ *
+ * @param person
+ * @return
+ */
+ default Optional findByPerson(Person person) {
+ return findById(person == null ? null : person.id);
+ }
+
+ void deleteAll();
+
+ Person save(Person person);
+}
diff --git a/cassandra/java8/src/main/java/example/springdata/cassandra/java8/package-info.java b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/package-info.java
new file mode 100644
index 00000000..476e1287
--- /dev/null
+++ b/cassandra/java8/src/main/java/example/springdata/cassandra/java8/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Package showing Java 8 features.
+ */
+package example.springdata.cassandra.java8;
diff --git a/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Java8IntegrationTests.java b/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Java8IntegrationTests.java
new file mode 100644
index 00000000..9d4d693e
--- /dev/null
+++ b/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Java8IntegrationTests.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.util.Version;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * Integration test to show the usage of Java 8 features with Spring Data Cassandra.
+ *
+ * @author Mark Paluch
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CassandraConfiguration.class)
+public class Java8IntegrationTests {
+
+ @ClassRule
+ public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost().atLeast(Version.parse("3.0"));
+
+ @Autowired PersonRepository repository;
+
+ @Before
+ public void setUp() throws Exception {
+ repository.deleteAll();
+ }
+
+ @Test
+ public void providesFindOneWithOptional() {
+
+ Person homer = repository.save(new Person("1", "Homer", "Simpson"));
+
+ assertThat(repository.findOne(homer.id).isPresent(), is(true));
+ assertThat(repository.findOne(homer.id + 1), is(Optional. empty()));
+ }
+
+ @Test
+ public void invokesDefaultMethod() {
+
+ Person homer = repository.save(new Person("1", "Homer", "Simpson"));
+ Optional result = repository.findByPerson(homer);
+
+ assertThat(result.isPresent(), is(true));
+ assertThat(result.get(), is(homer));
+ }
+
+ /**
+ * Streaming data from the store by using a repository method that returns a {@link Stream}. Note, that since the
+ * resulting {@link Stream} contains state it needs to be closed explicitly after use!
+ */
+ @Test
+ public void useJava8StreamsWithCustomQuery() {
+
+ Person homer = repository.save(new Person("1", "Homer", "Simpson"));
+ Person bart = repository.save(new Person("2", "Bart", "Simpson"));
+
+ try (Stream stream = repository.streamAllPeople()) {
+ assertThat(stream.collect(Collectors.toList()), hasItems(homer, bart));
+ }
+ }
+}
diff --git a/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Jsr310IntegrationTests.java b/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Jsr310IntegrationTests.java
new file mode 100644
index 00000000..76221d08
--- /dev/null
+++ b/cassandra/java8/src/test/java/example/springdata/cassandra/java8/Jsr310IntegrationTests.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 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 example.springdata.cassandra.java8;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.time.LocalDate;
+import java.time.ZoneId;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.data.util.Version;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import example.springdata.cassandra.util.RequiresCassandraKeyspace;
+
+/**
+ * Integration test to show the usage of JSR-310 date/time types with Spring Data Cassandra.
+ *
+ * @author Mark Paluch
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = CassandraConfiguration.class)
+public class Jsr310IntegrationTests {
+
+ @ClassRule public final static RequiresCassandraKeyspace CASSANDRA_KEYSPACE = RequiresCassandraKeyspace.onLocalhost()
+ .atLeast(Version.parse("3.0"));
+
+ @Autowired OrderRepository repository;
+
+ @Before
+ public void setUp() throws Exception {
+ repository.deleteAll();
+ }
+
+ @Test
+ public void findOneByJsr310Types() {
+
+ Order order = new Order("42", LocalDate.now(), ZoneId.systemDefault());
+
+ repository.save(order);
+
+ assertThat(repository.findOrderByOrderDateAndZoneId(order.getOrderDate(), order.getZoneId()), is(equalTo(order)));
+ }
+
+ @Test
+ public void findOneByConvertedTypes() {
+
+ Order order = new Order("42", LocalDate.of(2010, 1, 2), ZoneId.systemDefault());
+
+ repository.save(order);
+
+ com.datastax.driver.core.LocalDate date = com.datastax.driver.core.LocalDate.fromYearMonthDay(2010, 1, 2);
+ String zoneId = order.getZoneId().getId();
+
+ assertThat(repository.findOrderByDate(date, zoneId), is(equalTo(order)));
+ }
+}
diff --git a/cassandra/pom.xml b/cassandra/pom.xml
index a861abc0..f30cff29 100644
--- a/cassandra/pom.xml
+++ b/cassandra/pom.xml
@@ -1,5 +1,5 @@
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
spring-data-cassandra-examples
@@ -17,7 +17,9 @@
2014
+ util
example
+ java8
@@ -27,9 +29,14 @@
spring-boot-starter-aop
-
- org.springframework.data
- spring-data-cassandra
+
+ org.springframework.boot
+ spring-boot-starter-data-cassandra
+
+
+
+ com.datastax.cassandra
+ cassandra-driver-core
diff --git a/cassandra/util/pom.xml b/cassandra/util/pom.xml
new file mode 100644
index 00000000..38bd8544
--- /dev/null
+++ b/cassandra/util/pom.xml
@@ -0,0 +1,22 @@
+
+ 4.0.0
+
+
+ org.springframework.data.examples
+ spring-data-cassandra-examples
+ 1.0.0.BUILD-SNAPSHOT
+ ../pom.xml
+
+
+ spring-data-cassandra-example-utils
+ Spring Data Cassandra - Example Utilities
+
+
+
+ junit
+ junit
+
+
+
+
diff --git a/cassandra/util/src/main/java/example/springdata/cassandra/util/CassandraVersion.java b/cassandra/util/src/main/java/example/springdata/cassandra/util/CassandraVersion.java
new file mode 100644
index 00000000..c39503cd
--- /dev/null
+++ b/cassandra/util/src/main/java/example/springdata/cassandra/util/CassandraVersion.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 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 example.springdata.cassandra.util;
+
+import org.springframework.data.util.Version;
+import org.springframework.util.Assert;
+
+import com.datastax.driver.core.ResultSet;
+import com.datastax.driver.core.Row;
+import com.datastax.driver.core.Session;
+
+import lombok.experimental.UtilityClass;
+
+/**
+ * Utility to retrieve the Cassandra release version.
+ *
+ * @author Mark Paluch
+ */
+@UtilityClass
+public class CassandraVersion {
+
+ /**
+ * Retrieve the Cassandra release version.
+ *
+ * @param session must not be {@literal null}.
+ * @return the release {@link Version}.
+ */
+ public static Version getReleaseVersion(Session session) {
+
+ Assert.notNull(session, "Session must not be null");
+
+ ResultSet resultSet = session.execute("SELECT release_version FROM system.local;");
+ Row row = resultSet.one();
+
+ return Version.parse(row.getString(0));
+ }
+}
diff --git a/cassandra/util/src/main/java/example/springdata/cassandra/util/RequiresCassandraKeyspace.java b/cassandra/util/src/main/java/example/springdata/cassandra/util/RequiresCassandraKeyspace.java
new file mode 100644
index 00000000..91046b17
--- /dev/null
+++ b/cassandra/util/src/main/java/example/springdata/cassandra/util/RequiresCassandraKeyspace.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 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 example.springdata.cassandra.util;
+
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.AssumptionViolatedException;
+import org.junit.rules.ExternalResource;
+import org.springframework.data.util.Version;
+import org.springframework.util.Assert;
+
+import com.datastax.driver.core.Cluster;
+import com.datastax.driver.core.NettyOptions;
+import com.datastax.driver.core.Session;
+
+import io.netty.channel.EventLoopGroup;
+
+/**
+ * Implementation of an {@link ExternalResource} to verify Apache Cassandra is running and listening on the given
+ * contact point. This rule also creates a keyspace if it not exists.
+ *
+ * @author Mark Paluch
+ */
+public class RequiresCassandraKeyspace extends ExternalResource {
+
+ private final int timeout = 30;
+ private final String host;
+ private final int port;
+ private final String keyspaceName;
+ private Version requiresVersion;
+
+ private RequiresCassandraKeyspace(String host, int port, String keyspaceName) {
+
+ this.host = host;
+ this.port = port;
+ this.keyspaceName = keyspaceName;
+ }
+
+ /**
+ * Require a running Cassandra instance on {@code localhost:9042}.
+ *
+ * @return the {@link RequiresCassandraKeyspace} rule
+ */
+ public static RequiresCassandraKeyspace onLocalhost() {
+ return new RequiresCassandraKeyspace("localhost", 9042, "example");
+ }
+
+ /**
+ * Setup a version requirement.
+ *
+ * @param version must not be {@literal null}.
+ * @return the {@link RequiresCassandraKeyspace} rule
+ */
+ public RequiresCassandraKeyspace atLeast(Version version) {
+
+ Assert.notNull(version, "Required version must not be null!");
+
+ this.requiresVersion = version;
+ return this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.junit.rules.ExternalResource#before()
+ */
+ @Override
+ protected void before() throws Throwable {
+
+ try (Socket socket = new Socket()) {
+ socket.setTcpNoDelay(true);
+ socket.setSoLinger(true, 0);
+ socket.connect(new InetSocketAddress(host, port), timeout);
+
+ } catch (Exception e) {
+ throw new AssumptionViolatedException(String.format("Seems as Cassandra is not running at %s:%s.", host, port),
+ e);
+ }
+
+ Cluster cluster = Cluster.builder().addContactPoint(host).withPort(port).withNettyOptions(new NettyOptions() {
+ @Override
+ public void onClusterClose(EventLoopGroup eventLoopGroup) {
+ eventLoopGroup.shutdownGracefully(0, 0, TimeUnit.MILLISECONDS).syncUninterruptibly();
+ }
+ }).build();
+
+ Session session = cluster.newSession();
+
+ try {
+
+ if (requiresVersion != null) {
+
+ Version cassandraReleaseVersion = CassandraVersion.getReleaseVersion(session);
+
+ if (cassandraReleaseVersion.isLessThan(requiresVersion)) {
+ throw new AssumptionViolatedException(
+ String.format("Cassandra at %s:%s runs in Version %s but we require at least %s", host, port,
+ cassandraReleaseVersion, requiresVersion));
+ }
+ }
+
+ session.execute(String.format("CREATE KEYSPACE IF NOT EXISTS %s \n"
+ + "WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };", keyspaceName));
+ } finally {
+ session.close();
+ cluster.close();
+ }
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index b8281e98..0b03dba3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,6 +38,7 @@
Ingalls-M1
0.21.0.RELEASE
2.9.0
+ 3.0.3