Skip to content

Commit

Permalink
Merge pull request eugenp#291 from sameira/master
Browse files Browse the repository at this point in the history
Spring Data Cassandra
  • Loading branch information
Eugen committed Dec 5, 2015
2 parents cdcc25e + 68c7e86 commit ccd1824
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 0 deletions.
110 changes: 110 additions & 0 deletions spring-data-cassandra/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.baeldung</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>spring-data-cassandra</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<org.springframework.data.version>1.3.1.RELEASE</org.springframework.data.version>
<org.springframework.version>4.2.2.RELEASE</org.springframework.version>
<junit.version>4.11</junit.version>
<org.slf4j.version>1.7.12</org.slf4j.version>
<logback.version>1.1.3</logback.version>
<cassandra-driver-core.version>2.1.5</cassandra-driver-core.version>
<cassandra-unit-spring.version>2.1.9.2</cassandra-unit-spring.version>
<cassandra-unit-shaded>2.1.9.2</cassandra-unit-shaded>
<hector-core.version>2.0-0</hector-core.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-cassandra</artifactId>
<version>${org.springframework.data.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${org.springframework.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit-dep</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${org.springframework.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit-spring</artifactId>
<version>${cassandra-unit-spring.version}</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.cassandraunit</groupId>
<artifactId>cassandra-unit-shaded</artifactId>
<version>${cassandra-unit-shaded}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hectorclient</groupId>
<artifactId>hector-core</artifactId>
<version>${hector-core.version}</version>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>${cassandra-driver-core.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${org.slf4j.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
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;
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 environment.getProperty("cassandra.keyspace");
}

@Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
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;
}

@Bean
public CassandraMappingContext cassandraMapping() throws ClassNotFoundException {
return new BasicCassandraMappingContext();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
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<String> tags = new HashSet<>();

public Book(UUID id, String title, String publisher, Set<String> 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;
}

public void setId(UUID id) {
this.id = id;
}

public void setTitle(String title) {
this.title = title;
}

public void setPublisher(String publisher) {
this.publisher = publisher;
}

public void setTags(Set<String> tags) {
this.tags = tags;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
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<Book> {
@Query("select * from book where title = ?0 and publisher=?1")
Iterable<Book> findByTitleAndPublisher(String title, String publisher);
}
3 changes: 3 additions & 0 deletions spring-data-cassandra/src/main/resources/cassandra.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cassandra.contactpoints=127.0.0.1
cassandra.port=9142
cassandra.keyspace=testKeySpace
20 changes: 20 additions & 0 deletions spring-data-cassandra/src/main/resources/logback.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<configuration>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>web - %date [%thread] %-5level %logger{36} - %message%n
</pattern>
</encoder>
</appender>

<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />

<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />

<root level="INFO">
<appender-ref ref="STDOUT" />
</root>

</configuration>
Binary file added spring-data-cassandra/src/main/resources/test.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
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(session.execute("Select * from Book").all().toArray());
Thread.sleep(5000);
LOGGER.info("KeySpace created and activated.");
}

@Before
public void createTable() throws InterruptedException, TTransportException, ConfigurationException, IOException {
adminTemplate.createTable(true, CqlIdentifier.cqlId(DATA_TABLE_NAME), Book.class, new HashMap<String, Object>());
}

@Test
public void whenSavingBook_thenAvailableOnRetrieval() {
Book javaBook = new Book(UUIDs.timeBased(), "Head First Java",
"O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
Iterable<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
assertEquals(javaBook.getId(), books.iterator().next().getId());
}

@Test
public void whenUpdatingBooks_thenAvailableOnRetrieval() {
Book javaBook = new Book(UUIDs.timeBased(), "Head First Java", "O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
Iterable<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
javaBook.setTitle("Head First Java Second Edition");
bookRepository.save(ImmutableSet.of(javaBook));
Iterable<Book> updateBooks = bookRepository.findByTitleAndPublisher("Head First Java Second Edition", "O'Reilly Media");
assertEquals(javaBook.getTitle(), updateBooks.iterator().next().getTitle());
}

@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<Book> books = bookRepository.findByTitleAndPublisher("Head First Java", "O'Reilly Media");
assertNotEquals(javaBook.getId(), books.iterator().next().getId());
}

@Test
public void whenSavingBooks_thenAllShouldAvailableOnRetrieval() {
Book javaBook = new Book(UUIDs.timeBased(), "Head First Java",
"O'Reilly Media", ImmutableSet.of("Computer", "Software"));
Book dPatternBook = new Book(UUIDs.timeBased(), "Head Design Patterns",
"O'Reilly Media", ImmutableSet.of("Computer", "Software"));
bookRepository.save(ImmutableSet.of(javaBook));
bookRepository.save(ImmutableSet.of(dPatternBook));
Iterable<Book> books = bookRepository.findAll();
int bookCount = 0;
for (Book book : books) bookCount++;
assertEquals(bookCount, 2);
}

@After
public void dropTable() {
adminTemplate.dropTable(CqlIdentifier.cqlId(DATA_TABLE_NAME));
}

@AfterClass
public static void stopCassandraEmbedded() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}

0 comments on commit ccd1824

Please sign in to comment.