diff --git a/spring-data-cassandra/pom.xml b/spring-data-cassandra/pom.xml index 0ce25dc038..80aeb6a83f 100644 --- a/spring-data-cassandra/pom.xml +++ b/spring-data-cassandra/pom.xml @@ -11,8 +11,8 @@ UTF-8 - 1.1.0.RELEASE - 4.0.7.RELEASE + 1.3.1.RELEASE + 4.2.2.RELEASE 4.11 1.7.12 1.1.3 @@ -49,9 +49,53 @@ org.cassandraunit cassandra-unit-spring - 2.1.3.1 + 2.1.9.2 + test + + + org.cassandraunit + cassandra-unit + + + + + org.cassandraunit + cassandra-unit-shaded + 2.1.9.2 test + + org.hectorclient + hector-core + 2.0-0 + + + + + + + + + + + + + + + + + com.datastax.cassandra + cassandra-driver-core + 2.1.5 + true + + + + + + + + org.slf4j @@ -84,8 +128,8 @@ maven-compiler-plugin 2.3.2 - 1.8 - 1.8 + 1.7 + 1.7 diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java index 254de23eb6..9dda322ca3 100644 --- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java @@ -1,8 +1,12 @@ package org.baeldung.spring.data.cassandra.config; - +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; import org.springframework.data.cassandra.config.CassandraClusterFactoryBean; import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration; import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; @@ -10,19 +14,26 @@ import org.springframework.data.cassandra.mapping.CassandraMappingContext; import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; @Configuration +@PropertySource(value = { "classpath:cassandra.properties" }) @EnableCassandraRepositories(basePackages = "org.baeldung.spring.data.cassandra.repository") public class CassandraConfig extends AbstractCassandraConfiguration { + private static final Log LOGGER = LogFactory.getLog(CassandraConfig.class); + @Autowired + private Environment environment; + @Override protected String getKeyspaceName() { - return "event"; + return environment.getProperty("cassandra.keyspace"); } @Bean public CassandraClusterFactoryBean cluster() { CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean(); - cluster.setContactPoints("127.0.0.1"); - cluster.setPort(9142); + cluster.setContactPoints(environment.getProperty("cassandra.contactpoints")); + cluster.setPort(Integer.parseInt(environment.getProperty("cassandra.port"))); + LOGGER.info("Cluster created with contact points ["+ environment.getProperty("cassandra.contactpoints") +"] " + + "& port [" + Integer.parseInt(environment.getProperty("cassandra.port")) + "]."); return cluster; } diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java new file mode 100644 index 0000000000..74ea5c812b --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Book.java @@ -0,0 +1,46 @@ +package org.baeldung.spring.data.cassandra.model; + +import org.springframework.cassandra.core.Ordering; +import org.springframework.cassandra.core.PrimaryKeyType; +import org.springframework.data.cassandra.mapping.Column; +import org.springframework.data.cassandra.mapping.PrimaryKeyColumn; +import org.springframework.data.cassandra.mapping.Table; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +@Table +public class Book { + @PrimaryKeyColumn(name = "isbn", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING) + private UUID id; + @PrimaryKeyColumn(name = "title", ordinal = 0, type = PrimaryKeyType.PARTITIONED) + private String title; + @PrimaryKeyColumn(name = "publisher", ordinal = 1, type = PrimaryKeyType.PARTITIONED) + private String publisher; + @Column + private Set tags = new HashSet<>(); + + public Book(UUID id, String title, String publisher, Set tags) { + this.id = id; + this.title = title; + this.publisher = publisher; + this.tags.addAll(tags); + } + + public UUID getId() { + return id; + } + + public String getTitle() { + return title; + } + + public String getPublisher() { + return publisher; + } + + public Set getTags() { + return tags; + } +} diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Event.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Event.java deleted file mode 100644 index dd81fa071c..0000000000 --- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Event.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.baeldung.spring.data.cassandra.model; - -import org.springframework.cassandra.core.Ordering; -import org.springframework.cassandra.core.PrimaryKeyType; -import org.springframework.data.cassandra.mapping.Column; -import org.springframework.data.cassandra.mapping.PrimaryKeyColumn; -import org.springframework.data.cassandra.mapping.Table; - -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -@Table -public class Event { - @PrimaryKeyColumn(name = "id", ordinal = 2, type = PrimaryKeyType.CLUSTERED, ordering = Ordering.DESCENDING) - private UUID id; - @PrimaryKeyColumn(name = "type", ordinal = 0, type = PrimaryKeyType.PARTITIONED) - private String type; - @PrimaryKeyColumn(name = "bucket", ordinal = 1, type = PrimaryKeyType.PARTITIONED) - private String bucket; - @Column - private Set tags = new HashSet(); - - public Event(UUID id, String type, String bucket, Set tags) { - this.id = id; - this.type = type; - this.bucket = bucket; - this.tags.addAll(tags); - } - - public UUID getId() { - return id; - } - - public String getType() { - return type; - } - - public String getBucket() { - return bucket; - } - - public Set getTags() { - return tags; - } -} diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java new file mode 100644 index 0000000000..dee1f9ef88 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/BookRepository.java @@ -0,0 +1,14 @@ +package org.baeldung.spring.data.cassandra.repository; + + +import org.baeldung.spring.data.cassandra.model.Book; +import org.springframework.data.cassandra.repository.CassandraRepository; +import org.springframework.data.cassandra.repository.Query; +import org.springframework.stereotype.Repository; + +@Repository +public interface BookRepository extends CassandraRepository { + @Query("select * from book where title = ?0 and publisher=?1") + Iterable findByTitleAndPublisher(String title, String publisher); +} + diff --git a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/EventRepository.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/EventRepository.java deleted file mode 100644 index 73b96ae2ec..0000000000 --- a/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/EventRepository.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.baeldung.spring.data.cassandra.repository; - - -import org.baeldung.spring.data.cassandra.model.Event; -import org.springframework.data.cassandra.repository.CassandraRepository; -import org.springframework.data.cassandra.repository.Query; -import org.springframework.stereotype.Repository; - -@Repository -public interface EventRepository extends CassandraRepository { - @Query("select * from event where type = ?0 and bucket=?1") - Iterable findByTypeAndBucket(String type, String bucket); -} - diff --git a/spring-data-cassandra/src/main/resources/beans.xml b/spring-data-cassandra/src/main/resources/beans.xml deleted file mode 100644 index fc1fb36ee2..0000000000 --- a/spring-data-cassandra/src/main/resources/beans.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/spring-data-cassandra/src/main/resources/cassandra.properties b/spring-data-cassandra/src/main/resources/cassandra.properties new file mode 100644 index 0000000000..1550cdea4e --- /dev/null +++ b/spring-data-cassandra/src/main/resources/cassandra.properties @@ -0,0 +1,3 @@ +cassandra.contactpoints=127.0.0.1 +cassandra.port=9142 +cassandra.keyspace=testKeySpace \ No newline at end of file diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/config/CassandraTestConfig.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/config/CassandraTestConfig.java deleted file mode 100644 index facc6b43f3..0000000000 --- a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/config/CassandraTestConfig.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.baeldung.spring.data.cassandra.config; - -import com.datastax.driver.core.Cluster; -import com.datastax.driver.core.Session; -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.thrift.transport.TTransportException; -import org.cassandraunit.utils.EmbeddedCassandraServerHelper; -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.CassandraOperations; -import org.springframework.data.cassandra.core.CassandraTemplate; -import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; -import org.springframework.data.cassandra.mapping.CassandraMappingContext; -import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; - -import java.io.IOException; - -@Configuration -@EnableCassandraRepositories(basePackages = "org.baeldung.spring.data.cassandra.repository") -public class CassandraTestConfig{ - - @Bean(destroyMethod = "close") - public Cluster cluster() throws ConfigurationException, TTransportException, IOException, InterruptedException{ - EmbeddedCassandraServerHelper.startEmbeddedCassandra(); - Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build(); - Session session = cluster.connect(); - session.execute("CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = {" - + " 'class': 'SimpleStrategy', " - + " 'replication_factor': '3' " - + "};" ); -// session.execute("CREATE KEYSPACE testKeySpace WITH replication={'class' : 'SimpleStrategy', 'replication_factor':1}"); -// session.execute("USE testKeySpace"); - return cluster; - } - - @Bean - public CassandraMappingContext mappingContext() { - return new BasicCassandraMappingContext(); - } - - @Bean - public CassandraConverter converter() { - return new MappingCassandraConverter(mappingContext()); - } - - @Bean - public CassandraSessionFactoryBean session() throws Exception { - - CassandraSessionFactoryBean session = new CassandraSessionFactoryBean(); - session.setCluster(cluster()); - session.setKeyspaceName("testKeySpace"); - session.setConverter(converter()); - session.setSchemaAction(SchemaAction.NONE); - - return session; - } - - @Bean - public CassandraOperations cassandraTemplate() throws Exception { - return new CassandraTemplate(session().getObject()); - } -} diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java new file mode 100644 index 0000000000..215c6b3824 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/BookRepositoryIntegrationTest.java @@ -0,0 +1,89 @@ +package org.baeldung.spring.data.cassandra.repository; + +import com.datastax.driver.core.Cluster; +import com.datastax.driver.core.Session; +import com.datastax.driver.core.utils.UUIDs; +import com.google.common.collect.ImmutableSet; +import org.apache.cassandra.exceptions.ConfigurationException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.thrift.transport.TTransportException; +import org.baeldung.spring.data.cassandra.config.CassandraConfig; +import org.baeldung.spring.data.cassandra.model.Book; +import org.cassandraunit.utils.EmbeddedCassandraServerHelper; +import org.junit.*; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cassandra.core.cql.CqlIdentifier; +import org.springframework.data.cassandra.core.CassandraAdminOperations; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +import java.io.IOException; +import java.util.HashMap; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = CassandraConfig.class) +public class BookRepositoryIntegrationTest { + + private static final Log LOGGER = LogFactory.getLog(BookRepositoryIntegrationTest.class); + + public static final String KEYSPACE_CREATION_QUERY = + "CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };"; + + public static final String KEYSPACE_ACTIVATE_QUERY = "USE testKeySpace;"; + + public static final String DATA_TABLE_NAME = "book"; + + @Autowired private BookRepository bookRepository; + + @Autowired private CassandraAdminOperations adminTemplate; + + @BeforeClass + public static void startCassandraEmbedded() + throws InterruptedException, TTransportException, ConfigurationException, IOException { + EmbeddedCassandraServerHelper.startEmbeddedCassandra(); + Cluster cluster = Cluster.builder().addContactPoints("127.0.0.1").withPort(9142).build(); + LOGGER.info("Server Started at 127.0.0.1:9142... "); + Session session = cluster.connect(); + session.execute(KEYSPACE_CREATION_QUERY); + session.execute(KEYSPACE_ACTIVATE_QUERY); + LOGGER.info("KeySpace created and activated."); + } + + @Before + public void resetKeySpace() + throws InterruptedException, TTransportException, ConfigurationException, IOException { + adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap()); + } + + @Test + public void whenSavingBooks_thenAvailableOnRetrieval() { + Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software")); + bookRepository.save(ImmutableSet.of(javaBook)); + Iterable books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media"); + assertEquals(javaBook.getId(), books.iterator().next().getId()); + } + + @Test(expected = java.util.NoSuchElementException.class) + public void whenDeletingExistingBooks_thenNotAvailableOnRetrieval() { + Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software")); + bookRepository.save(ImmutableSet.of(javaBook)); + bookRepository.delete(javaBook); + Iterable books = bookRepository.findByTitleAndPublisher("type1", "O'Reilly Media"); + assertNotEquals(javaBook.getId(), books.iterator().next().getId()); + } + + @After + public void cleanTable() { + adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME)); + } + + @AfterClass + public static void stopCassandraEmbedded() { + EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); + } +} diff --git a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/EventRepositoryIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/EventRepositoryIntegrationTest.java deleted file mode 100644 index c1fb162570..0000000000 --- a/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/EventRepositoryIntegrationTest.java +++ /dev/null @@ -1,73 +0,0 @@ -package org.baeldung.spring.data.cassandra.repository; - -import com.datastax.driver.core.utils.UUIDs; -import com.google.common.collect.ImmutableSet; -import org.apache.cassandra.exceptions.ConfigurationException; -import org.apache.thrift.transport.TTransportException; -import org.baeldung.spring.data.cassandra.config.CassandraConfig; -import org.baeldung.spring.data.cassandra.model.Event; -import org.cassandraunit.spring.CassandraUnitTestExecutionListener; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.cassandra.core.cql.CqlIdentifier; -import org.springframework.data.cassandra.core.CassandraAdminOperations; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.TestExecutionListeners; -import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; - -import java.io.IOException; -import java.util.HashMap; - -import static org.hamcrest.CoreMatchers.hasItem; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; - -@RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(classes = {CassandraConfig.class}) -@TestExecutionListeners({CassandraUnitTestExecutionListener.class, DependencyInjectionTestExecutionListener.class}) -public class EventRepositoryIntegrationTest { - - public static final String TIME_BUCKET = "2014-01-01"; - - @Autowired - private EventRepository eventRepository; - - @Autowired - private CassandraAdminOperations adminTemplate; - - @Test - public void repositoryStoresAndRetrievesEvents() throws InterruptedException, TTransportException, ConfigurationException, IOException { - adminTemplate.execute("CREATE KEYSPACE IF NOT EXISTS testKeySpace WITH replication = {" - + " 'class': 'SimpleStrategy', " - + " 'replication_factor': '3' " - + "};" ); - adminTemplate.dropTable(CqlIdentifier.cqlId("event")); - adminTemplate.createTable(true, CqlIdentifier.cqlId("event"), Event.class, new HashMap()); - Event event1 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag1", "tag2")); - Event event2 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag3")); - eventRepository.save(ImmutableSet.of(event1, event2)); - - Iterable events = eventRepository.findByTypeAndBucket("type1", TIME_BUCKET); - - assertThat(events, hasItem(event1)); - assertThat(events, hasItem(event2)); - } - - // @Test - public void repositoryDeletesStoredEvents() { - Event event1 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag1", "tag2")); - Event event2 = new Event(UUIDs.timeBased(), "type1", TIME_BUCKET, ImmutableSet.of("tag3")); - eventRepository.save(ImmutableSet.of(event1, event2)); - - eventRepository.delete(event1); - eventRepository.delete(event2); - - Iterable events = eventRepository.findByTypeAndBucket("type1", TIME_BUCKET); - - assertThat(events, not(hasItem(event1))); - assertThat(events, not(hasItem(event2))); - } - -}