Java 8 and Scala Cassandra client.
Find a file
Greg Burd 715fb0e673 Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database.
- move to 3.x DataStax drivers (NOTE, this broke the Casser.dsl() API a bit)
 - introduce UnitOfWork-style pseudo transactional scoping (WIP as of this commit)
 - introduce session and UnitOfWork scoped caches (WIP as of this commit)
 - add support for SASI-based secondary index types (such as case insensitive matching, etc.)
 - add support for Lucene-based secondary index types (WIP https://github.com/Stratio/cassandra-lucene-index)
 - update types for Java 8 (WIP)
 - add in Codahale/Dropwizard and Zipkin metrics/tracing support (WIP)
 - and a lot more...
2017-07-27 15:02:17 -04:00
.idea Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
src Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
.gitignore added pom.xml 2015-03-14 10:22:57 -07:00
.travis-oss-settings.xml enable travis 2015-03-25 19:27:35 -07:00
.travis.yml update travis settings 2015-03-30 12:28:37 -07:00
AUTHORS Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
deploy.sh 1.2.0_2.11-SNAPSHOT 2015-06-16 15:50:14 -07:00
eclipse-formatting.xml eclipse-formatting 2015-03-16 17:03:17 -07:00
helenus-core.iml Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
LICENSE Initial commit 2015-02-26 12:42:59 -08:00
pom.xml Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
README.md Helenus was the son of King Priam and Queen Hecuba of Troy, and the twin brother of the prophetess Cassandra. Like Cassandra, he was always right, but unlike her, others believed him. Seems like a good name for a layer to access DataStax, Apache, or ScyllaDB's implementations of the Cassandra database. 2017-07-27 15:02:17 -04:00
sign.sh 1.2.0_2.11-SNAPSHOT 2015-06-16 15:50:14 -07:00

helenus

Fast and easy, functional style cutting edge Java 8 and Scala 2.11 Cassandra client

Current status: First application in production (may be more)

Features

  • Leverages Java 8 language capabilities to build CQL queries
  • Simple function-style stream API
  • Reactive asynchronous and synchronous API
  • Provides Java mapping for Tables, Tuples, UDTs (User Defined Type), Collections, UDT Collections, Tuple Collections
  • Uses lazy mapping in all cases where possible
  • Supports Guava ListenableFuture and Scala Future

Requirements

  • Latest JVM 8
  • Latest Datastax Driver 2.1.5
  • Latest Cassandra 2.1.4
  • Latest Scala 2.11
  • Latest Maven as well

Maven

Latest release dependency:

<dependencies>
	<dependency>
		<groupId>net.helenus</groupId>
		<artifactId>helenus-core</artifactId>
		<version>1.1.0_2.11</version>
	</dependency>
</dependencies>

Active development dependency for Scala 2.11:

<dependencies>
	<dependency>
		<groupId>net.helenus</groupId>
		<artifactId>helenus-core</artifactId>
		<version>1.2.0_2.11-SNAPSHOT</version>
	</dependency>
</dependencies>

<repositories>
    <repository>
        <id>oss-sonatype</id>
        <name>oss-sonatype</name>
        <url>https://oss.sonatype.org/content/repositories/snapshots/</url>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>

Simple Example

Model definition:

@Table("timelines")
public interface Timeline {

	@PartitionKey
	UUID userId();

	@ClusteringColumn
	@Types.Timeuuid
	Date timestamp();

	@Column
	String text();

}

Session initialization:

Timeline timeline = Helenus.dsl(Timeline.class);
HelenusSession session = Helenus.init(getSession()).showCql().add(Timeline.class).autoCreateDrop().get();

Select example:

session.select(timeline::userId, timeline::timestamp, timeline::text)
  .where(timeline::userId, Query.eq(userId))
  .orderBy(Query.desc(timeline::timestamp)).limit(5).sync()
  .forEach(System.out::println);

Insert example:

TimelineImpl post = new TimelineImpl();
post.userId=userId;
post.timestamp=new Date(postTime+1000L*i);
post.text="hello";
session.upsert(post).sync();

Model and Repository Example

Account model:

@Table
public interface Account {

	@PartitionKey
	String accountId();
	
	Date createdAt();
	
	String organization();
	
	String team();
	
	String timezone();

	Map<String, AccountUser> users();
}

AccountUser model:

@UDT
public interface AccountUser {

	String email();
	
	String firstName();

	String lastName();
	
}

Abstract repository:

public interface AbstractRepository {

	HelenusSession session();
	
}

Account repository:

import scala.concurrent.Future;

public interface AccountRepository extends AbstractRepository {

	static final Account account = Helenus.dsl(Account.class);
	
	static final String DEFAULT_TIMEZONE = "America/Los_Angeles";
	
	default Future<Optional<Account>> findAccount(String accountId) {
		
		return session()
				.select(Account.class)
				.where(account::accountId, eq(accountId))
				.single()
				.future();
		
	}
	
	default Future<Fun.Tuple2<ResultSet, String>> createAccount(
			String email,
			AccountUser user,
			String organization,
			String team,
			String timezone) {
		
		String accountId = AccountId.next();

		if (timezone == null || timezone.isEmpty()) {
			timezone = DEFAULT_TIMEZONE;
		}
		
		return session()
			.insert()
			.value(account::accountId, accountId)
			.value(account::createdAt, new Date())
			.value(account::organization, organization)
			.value(account::team, team)
			.value(account::timezone, timezone)
			.value(account::users, ImmutableMap.of(email, user))
			.future(accountId);
		
	}
	
	default Future<ResultSet> putAccountUser(String accountId, String email, AccountUser user) {
		
		return session()
				.update()
				.put(account::users, email.toLowerCase(), user)
				.where(account::accountId, eq(accountId))
				.future();
		
	}
	
	default Future<ResultSet> removeAccountUser(String accountId, String email) {
		
		return session()
				.update()
				.put(account::users, email.toLowerCase(), null)
				.where(account::accountId, eq(accountId))
				.future();
		
	}
	
	default Future<ResultSet> dropAccount(String accountId) {
		
		return session()
				.delete()
				.where(account::accountId, eq(accountId))
				.future();
		
	}

}