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 new file mode 100644 index 0000000000..254de23eb6 --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/config/CassandraConfig.java @@ -0,0 +1,33 @@ +package org.baeldung.spring.data.cassandra.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.cassandra.config.CassandraClusterFactoryBean; +import org.springframework.data.cassandra.config.java.AbstractCassandraConfiguration; +import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext; +import org.springframework.data.cassandra.mapping.CassandraMappingContext; +import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories; + +@Configuration +@EnableCassandraRepositories(basePackages = "org.baeldung.spring.data.cassandra.repository") +public class CassandraConfig extends AbstractCassandraConfiguration { + + @Override + protected String getKeyspaceName() { + return "event"; + } + + @Bean + public CassandraClusterFactoryBean cluster() { + CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean(); + cluster.setContactPoints("127.0.0.1"); + cluster.setPort(9142); + return cluster; + } + + @Bean + public CassandraMappingContext cassandraMapping() throws ClassNotFoundException { + return new BasicCassandraMappingContext(); + } +} \ No newline at end of file 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 new file mode 100644 index 0000000000..dd81fa071c --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/model/Event.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 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/EventRepository.java b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/EventRepository.java new file mode 100644 index 0000000000..73b96ae2ec --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/baeldung/spring/data/cassandra/repository/EventRepository.java @@ -0,0 +1,14 @@ +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 new file mode 100644 index 0000000000..fc1fb36ee2 --- /dev/null +++ b/spring-data-cassandra/src/main/resources/beans.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-cassandra/src/main/resources/logback.xml b/spring-data-cassandra/src/main/resources/logback.xml new file mode 100644 index 0000000000..215eeede64 --- /dev/null +++ b/spring-data-cassandra/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-data-cassandra/src/main/resources/test.png b/spring-data-cassandra/src/main/resources/test.png new file mode 100644 index 0000000000..c3b5e80276 Binary files /dev/null and b/spring-data-cassandra/src/main/resources/test.png differ 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 new file mode 100644 index 0000000000..facc6b43f3 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/config/CassandraTestConfig.java @@ -0,0 +1,66 @@ +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/EventRepositoryIntegrationTest.java b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/EventRepositoryIntegrationTest.java new file mode 100644 index 0000000000..c1fb162570 --- /dev/null +++ b/spring-data-cassandra/src/test/java/org/baeldung/spring/data/cassandra/repository/EventRepositoryIntegrationTest.java @@ -0,0 +1,73 @@ +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))); + } + +}