Cassandra rapid prototyping 
with Achilles 
www.achilles.io 1 
@doanduyhai
DuyHai DOAN 
Java/Cassandra freelance developer 
! 
! 
Daytime: + 
! 
! 
At night: + 
www.achilles.io 2 
@doanduyhai
What is Achilles ? 
Yet another C* object mapper 
www.achilles.io 3 
@doanduyhai
What is Achilles ? 
More than a C* object mapper 
www.achilles.io 4 
@doanduyhai
Demo 
TDD with Achilles 
www.achilles.io 5 
@doanduyhai
Main API 
•manager.insert(entity) 
! 
•manager.update(managedEntity) 
! 
•manager.remove(entity) 
! 
•manager.find(Entity.class, primaryKey) 
www.achilles.io 6 
@doanduyhai
Thread safety for persistence manager 
No JOINS means 
www.achilles.io 7 
@doanduyhai
Thread safety for persistence manager 
No JOINS means 
! 
! 
No complex object graph 
www.achilles.io 8 
@doanduyhai
Thread safety for persistence manager 
No JOINS means 
! 
! 
No complex object graph 
! 
! 
No state to keep 
www.achilles.io 9 
@doanduyhai
What’s about proxy ? 
proxifiedEntity = manager.find(Entity.class, primaryKey) 
Dirty check 
www.achilles.io 10 
@doanduyhai 
ProxifiedEntity 
Real 
Entity 
State 
Setters interception
Why proxies ? 
emc² Albert EINSTEIN GERMANY 
User einstein = manager.find(User.class,”emc²”); 
! 
einstein.setCountry(“USA”); 
! 
manager.insert(einstein); 
emc² Albert EINSTEIN GERMANY emc² Albert EINSTEIN USA 
www.achilles.io 11 
@doanduyhai 
Waste of space !!
Why proxies ? 
emc² Albert EINSTEIN GERMANY 
User einstein = manager.find(User.class,”emc²”); 
! 
einstein.setCountry(“USA”); 
! 
manager.update(einstein); 
emc² Albert EINSTEIN GERMANY USA 
www.achilles.io 12 
@doanduyhai
Slice query 
List<Message> entities = manager.sliceQuery(Message.class) 
.forSelect() 
.withPartitionComponents(10L) 
.fromClusterings(“forums”).toClusterings(“forums”, uuid1) 
.limit(10).fromInclusiveToExclusiveBounds() 
.get(); 
SELECT * FROM Message 
WHERE user_id = 10 
AND (message_folder) ≥ (‘forums’) 
AND (message_folder, date) < (‘forums’, uuid1) 
ORDER BY message_folder ASC LIMIT 10; 
www.achilles.io 13 
@doanduyhai
Typed query 
RegularStatement select = select().from(“user_messages”) 
.where(eq(“user_id”,bindMarker())) 
.and(gte(asList(“message_folder”), bindMarker())) 
.and(lt(asList(“message_folder”, “date”), bindMarker())) 
.limit(10); 
! 
List<Message> messages = manager.typedQuery(Message.class, select, 
userId, asList(“forums”), asList(“forums”, uuid1)) 
.get(); 
www.achilles.io 14 
@doanduyhai
Native query 
RegularStatement nativeQuery = new SimpleStatement(“SELECT * FROM Message 
WHERE … LIMIT 20”); 
! 
List<TypedMap> messages = manager.nativeQuery(nativeQuery).get(); 
! 
TypedMap firstMessage = messages.get(0); 
! 
// with normal Map<String, Object> 
// String interlocutor = (String) map.get(“interlocutor”); 
! 
String interlocutor = firstMessage.getTyped(“interlocutor”); 
String interlocutor = firstMessage.<String>getTyped(“interlocutor”); 
www.achilles.io 15 
@doanduyhai
Counter API 
Special proxy type 
www.achilles.io 16 
@doanduyhai 
public Long get(); 
! 
public void incr(); 
! 
public void incr(Long increment); 
! 
public void decr(); 
! 
public void decr(Long decrement);
Options 
•Setting C* special options 
•Apply to main API insert(), update(), remove() … 
www.achilles.io 17 
@doanduyhai 
manager.insert(user, 
OptionsBuilder 
.withConsistency(QUORUM) 
.ttl(10) 
.timestamp(1357949499999L) 
.ifNotExists() 
);
Lifecycle interceptors 
Hooks into persistence lifecycle 
www.achilles.io 18 
@doanduyhai 
public interface Interceptor<T> { 
public void onEvent(T entity); 
public List<Event> events(); 
} 
! 
public enum Event { 
PRE_PERSIST, POST_PERSIST, PRE_UPDATE, POST_UPDATE, PRE_REMOVE, 
POST_REMOVE, POST_LOAD; 
}
Bean Validation (JSR-303) 
Just a built-in interceptor, PRE_PERSIST, PRE_UPDATE 
@Entity(table = “entity”) 
public class Entity { 
@Id 
private Long id; 
! 
@Column 
@NotEmpty 
private String name; 
} 
www.achilles.io 19 
@doanduyhai
Batch mode 
C* 2.0 atomic batches 
Batch batch = manager.createBatch(); 
! 
batch.startBatch(); 
! 
batch.insert(new Entity(…..)); 
batch.update(…..); 
batch.remove(…..); 
batch.removeById(MyEntity.class, primaryKey); 
! 
batch.endBatch(); 
www.achilles.io 20 
@doanduyhai
Documentation 
•Comprehensive Github WIKI 
! 
•Twitter-clone demo app (demo.achilles.io) 
! 
•Versioned documentation (HTML & PDF) 
! 
•JavaDoc 
www.achilles.io 21 
@doanduyhai
Documentation 
www.achilles.io 22 
@doanduyhai
Asynchronous 
•Available for 
➡ main API ( insert(), update(), …) 
➡ slice queries 
➡ typed & native queries 
www.achilles.io 23 
@doanduyhai
Roadmap for future 
•C* 2.1 user defined types (UDT) & tuples 
! 
•Reactive programming (RxJava) 
! 
•Transparent search integration (ElasticSearch, Solr…) 
www.achilles.io 24 
@doanduyhai
Where to download ? 
•www.achilles.io 
! 
•Google “Achilles Cassandra” ☞ first result 
www.achilles.io 25 
@doanduyhai
Take away 
•More than a simple object mapper 
! 
•Productivity-oriented 
! 
•KISS 
! 
•Documented 
www.achilles.io 26 
@doanduyhai
! " 
Q & A 
www.achilles.io 27 @doanduyhai

Cassandra rapid prototyping with achilles

  • 1.
    Cassandra rapid prototyping with Achilles www.achilles.io 1 @doanduyhai
  • 2.
    DuyHai DOAN Java/Cassandrafreelance developer ! ! Daytime: + ! ! At night: + www.achilles.io 2 @doanduyhai
  • 3.
    What is Achilles? Yet another C* object mapper www.achilles.io 3 @doanduyhai
  • 4.
    What is Achilles? More than a C* object mapper www.achilles.io 4 @doanduyhai
  • 5.
    Demo TDD withAchilles www.achilles.io 5 @doanduyhai
  • 6.
    Main API •manager.insert(entity) ! •manager.update(managedEntity) ! •manager.remove(entity) ! •manager.find(Entity.class, primaryKey) www.achilles.io 6 @doanduyhai
  • 7.
    Thread safety forpersistence manager No JOINS means www.achilles.io 7 @doanduyhai
  • 8.
    Thread safety forpersistence manager No JOINS means ! ! No complex object graph www.achilles.io 8 @doanduyhai
  • 9.
    Thread safety forpersistence manager No JOINS means ! ! No complex object graph ! ! No state to keep www.achilles.io 9 @doanduyhai
  • 10.
    What’s about proxy? proxifiedEntity = manager.find(Entity.class, primaryKey) Dirty check www.achilles.io 10 @doanduyhai ProxifiedEntity Real Entity State Setters interception
  • 11.
    Why proxies ? emc² Albert EINSTEIN GERMANY User einstein = manager.find(User.class,”emc²”); ! einstein.setCountry(“USA”); ! manager.insert(einstein); emc² Albert EINSTEIN GERMANY emc² Albert EINSTEIN USA www.achilles.io 11 @doanduyhai Waste of space !!
  • 12.
    Why proxies ? emc² Albert EINSTEIN GERMANY User einstein = manager.find(User.class,”emc²”); ! einstein.setCountry(“USA”); ! manager.update(einstein); emc² Albert EINSTEIN GERMANY USA www.achilles.io 12 @doanduyhai
  • 13.
    Slice query List<Message>entities = manager.sliceQuery(Message.class) .forSelect() .withPartitionComponents(10L) .fromClusterings(“forums”).toClusterings(“forums”, uuid1) .limit(10).fromInclusiveToExclusiveBounds() .get(); SELECT * FROM Message WHERE user_id = 10 AND (message_folder) ≥ (‘forums’) AND (message_folder, date) < (‘forums’, uuid1) ORDER BY message_folder ASC LIMIT 10; www.achilles.io 13 @doanduyhai
  • 14.
    Typed query RegularStatementselect = select().from(“user_messages”) .where(eq(“user_id”,bindMarker())) .and(gte(asList(“message_folder”), bindMarker())) .and(lt(asList(“message_folder”, “date”), bindMarker())) .limit(10); ! List<Message> messages = manager.typedQuery(Message.class, select, userId, asList(“forums”), asList(“forums”, uuid1)) .get(); www.achilles.io 14 @doanduyhai
  • 15.
    Native query RegularStatementnativeQuery = new SimpleStatement(“SELECT * FROM Message WHERE … LIMIT 20”); ! List<TypedMap> messages = manager.nativeQuery(nativeQuery).get(); ! TypedMap firstMessage = messages.get(0); ! // with normal Map<String, Object> // String interlocutor = (String) map.get(“interlocutor”); ! String interlocutor = firstMessage.getTyped(“interlocutor”); String interlocutor = firstMessage.<String>getTyped(“interlocutor”); www.achilles.io 15 @doanduyhai
  • 16.
    Counter API Specialproxy type www.achilles.io 16 @doanduyhai public Long get(); ! public void incr(); ! public void incr(Long increment); ! public void decr(); ! public void decr(Long decrement);
  • 17.
    Options •Setting C*special options •Apply to main API insert(), update(), remove() … www.achilles.io 17 @doanduyhai manager.insert(user, OptionsBuilder .withConsistency(QUORUM) .ttl(10) .timestamp(1357949499999L) .ifNotExists() );
  • 18.
    Lifecycle interceptors Hooksinto persistence lifecycle www.achilles.io 18 @doanduyhai public interface Interceptor<T> { public void onEvent(T entity); public List<Event> events(); } ! public enum Event { PRE_PERSIST, POST_PERSIST, PRE_UPDATE, POST_UPDATE, PRE_REMOVE, POST_REMOVE, POST_LOAD; }
  • 19.
    Bean Validation (JSR-303) Just a built-in interceptor, PRE_PERSIST, PRE_UPDATE @Entity(table = “entity”) public class Entity { @Id private Long id; ! @Column @NotEmpty private String name; } www.achilles.io 19 @doanduyhai
  • 20.
    Batch mode C*2.0 atomic batches Batch batch = manager.createBatch(); ! batch.startBatch(); ! batch.insert(new Entity(…..)); batch.update(…..); batch.remove(…..); batch.removeById(MyEntity.class, primaryKey); ! batch.endBatch(); www.achilles.io 20 @doanduyhai
  • 21.
    Documentation •Comprehensive GithubWIKI ! •Twitter-clone demo app (demo.achilles.io) ! •Versioned documentation (HTML & PDF) ! •JavaDoc www.achilles.io 21 @doanduyhai
  • 22.
  • 23.
    Asynchronous •Available for ➡ main API ( insert(), update(), …) ➡ slice queries ➡ typed & native queries www.achilles.io 23 @doanduyhai
  • 24.
    Roadmap for future •C* 2.1 user defined types (UDT) & tuples ! •Reactive programming (RxJava) ! •Transparent search integration (ElasticSearch, Solr…) www.achilles.io 24 @doanduyhai
  • 25.
    Where to download? •www.achilles.io ! •Google “Achilles Cassandra” ☞ first result www.achilles.io 25 @doanduyhai
  • 26.
    Take away •Morethan a simple object mapper ! •Productivity-oriented ! •KISS ! •Documented www.achilles.io 26 @doanduyhai
  • 27.
    ! " Q& A www.achilles.io 27 @doanduyhai