I recently wrote about my experience using Hector (a Java-Cassandra client library) from Scala. Although I found it to be workable, I was looking for something even simpler and more in the spirit of Scala.
Chris Shorrock wrote a compact, pure Scala client library for Cassandra called Cascal. You can download a precompiled binary from GitHub but I chose to build the latest version myself. If you have Git and Maven already set up on your system you can just do:
$ git clone git://github.com/shorrockin/cascal.git ... $ cd cascal $ mvn package
After Maven is done building you’ll have a target directory. Add the main jar file (I got cascal-1.2-SNAPSHOT.jar) to the Build Path in Eclipse and make sure you have other Cassandra dependencies configured (thrift, commons-pool, slf4j, log4j, etc.) I then wrote a simple test object to perform the same functions as before and I think the resulting data access code is very clean and readable:
import com.shorrockin.cascal.utils.Conversions._
import com.shorrockin.cascal.session._
object CassandraCascalTester {
def main(args : Array[String]) : Unit = {
// Set up session pool
val hosts = Host("localhost", 9160, 250) :: Nil
val params = new PoolParams(10, ExhaustionPolicy.Fail, 500L, 6, 2)
val pool = new SessionPool(hosts, params, Consistency.One)
pool.borrow { session =>
// Define column path
val colPath = "Keyspace1" \ "Standard1" \ "key" \ "column-name"
// insert
session.insert(colPath \ "value")
// read
val col = session.get(colPath)
System.out.println("Stored value: " + string(col.get.value))
}
}
}
As you can see, we don’t need to explicitly handle a try/catch block and Scala’s implicit type conversions take care of transforming strings to byte arrays and the directory-like column path syntax, all in a type-safe manner enforced by the compiler. For example, colPath will automatically become
Keyspace(value = Keyspace1) \ StandardColumnFamily(value = Standard1) \ StandardKey(value = key) \ Column(name = [B@6910fe28, value = null, time = 1272046381878)
and col will become
Some(Keyspace(value = Keyspace1) \ StandardColumnFamily(value = Standard1) \ StandardKey(value = key) \ Column(name = [B@30ec4a87, value = [B@6910fe28, time = 1272041137177))
Note that we do need to explicitly convert the retrieved value to a String because the basic get has no way of knowing what is stored in there. But Cascal has a solution for that too. Starting with version 1.1 Cascal includes a simple object mapping framework that can do the heavy lifting of populating objects from get and list results. I’ll explore this capability and its constraints in a future post.


Thank you. Very useful.