Errors and Solutions for Cassandra with Astyanax

I’m building a DAO using Astyanax, Netflix’s Java client for Cassandra, and I’ve run into a couple issues.

Following their Getting Started guide, I was able to create my `keyspace` object through which I’ll be executing reads and writes. Retrieval by id (getKey()) and multiple ids (getKeySlice(Collection)) worked fine. I created a simple row mapper to create my objects from the `ColumnList` returned. So before getting into the errors, here are some instantiations:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Cassandra table and keyspace constructed:
CREATE TABLE users (
user_id text,
username text,
department int,
PRIMARY KEY (user_id));
# Additional index for department
CREATE INDEX department_key ON users (department);
# Cassandra table and keyspace constructed: CREATE TABLE users ( user_id text, username text, department int, PRIMARY KEY (user_id)); # Additional index for department CREATE INDEX department_key ON users (department);
# Cassandra table and keyspace constructed:
CREATE TABLE users (
  user_id text,
  username text,
  department int,
  PRIMARY KEY (user_id));
# Additional index for department
CREATE INDEX department_key ON users (department);
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
private final ColumnFamily<String, String> USERS = new ColumnFamily<String, String>(
"users", // Column Family Name
StringSerializer.get(), // Key Serializer
StringSerializer.get()); // Column Serializer
private final ColumnFamily<String, String> USERS = new ColumnFamily<String, String>( "users", // Column Family Name StringSerializer.get(), // Key Serializer StringSerializer.get()); // Column Serializer
private final ColumnFamily<String, String> USERS = new ColumnFamily<String, String>(
   "users", // Column Family Name
   StringSerializer.get(), // Key Serializer
   StringSerializer.get()); // Column Serializer

Bad Request: No indexed columns present in by-columns clause with Equal operator

My first error came from the execution of this CQL query:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
OperationResult<CqlResult<String, String>> result = keyspace
.prepareQuery(USERS)
.withCql("SELECT * FROM users WHERE user_id = 'abc123'")
.execute();
// Also this fails:
OperationResult<CqlResult<String, String>> result = keyspace
.prepareQuery(USERS)
.withCql("SELECT * FROM users WHERE user_id = ?")
.asPreparedStatement()
.withStringValue(userId)
.execute();
OperationResult<CqlResult<String, String>> result = keyspace .prepareQuery(USERS) .withCql("SELECT * FROM users WHERE user_id = 'abc123'") .execute(); // Also this fails: OperationResult<CqlResult<String, String>> result = keyspace .prepareQuery(USERS) .withCql("SELECT * FROM users WHERE user_id = ?") .asPreparedStatement() .withStringValue(userId) .execute();
OperationResult<CqlResult<String, String>> result = keyspace
        .prepareQuery(USERS)
        .withCql("SELECT * FROM users WHERE user_id = 'abc123'")
        .execute();

// Also this fails:
OperationResult<CqlResult<String, String>> result = keyspace
        .prepareQuery(USERS)
        .withCql("SELECT * FROM users WHERE user_id = ?")
        .asPreparedStatement()
        .withStringValue(userId)
        .execute();

Another problem I saw was the connection would simply timeout.

Solution

Set the CQL version (.setCqlVersion("3.0.0")) and Cassandra version (.setTargetCassandraVersion("2.0.7")) on my keyspace:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public void init() {
context = new AstyanaxContext.Builder()
.forKeyspace(keyspaceName)
.withAstyanaxConfiguration(
new AstyanaxConfigurationImpl()
.setTargetCassandraVersion("2.0.7")
.setCqlVersion("3.0.0")
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE))
.withConnectionPoolConfiguration(
new ConnectionPoolConfigurationImpl("MyConnectionPool").setPort(port)
.setMaxConnsPerHost(1).setSeeds(host + ":" + port))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getClient();
}
public void init() { context = new AstyanaxContext.Builder() .forKeyspace(keyspaceName) .withAstyanaxConfiguration( new AstyanaxConfigurationImpl() .setTargetCassandraVersion("2.0.7") .setCqlVersion("3.0.0") .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)) .withConnectionPoolConfiguration( new ConnectionPoolConfigurationImpl("MyConnectionPool").setPort(port) .setMaxConnsPerHost(1).setSeeds(host + ":" + port)) .withConnectionPoolMonitor(new CountingConnectionPoolMonitor()) .buildKeyspace(ThriftFamilyFactory.getInstance()); context.start(); keyspace = context.getClient(); }
public void init() {
    context = new AstyanaxContext.Builder()
            .forKeyspace(keyspaceName)
            .withAstyanaxConfiguration(
                    new AstyanaxConfigurationImpl()
                            .setTargetCassandraVersion("2.0.7")
                            .setCqlVersion("3.0.0")
                            .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE))
            .withConnectionPoolConfiguration(
                    new ConnectionPoolConfigurationImpl("MyConnectionPool").setPort(port)
                            .setMaxConnsPerHost(1).setSeeds(host + ":" + port))
            .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
            .buildKeyspace(ThriftFamilyFactory.getInstance());

    context.start();
    keyspace = context.getClient();
}

Not enough bytes to read value of component 0

Another problem is when trying to write to the table using a MutationBatch.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
MutationBatch m = keyspace.prepareMutationBatch();
m.withRow(CF_USERS, u.getId())
.putColumn("user_id", u.getId())
.putColumn("username", u.getUsername())
.putColumn("department", u.getDepartment());
m.execute();
MutationBatch m = keyspace.prepareMutationBatch(); m.withRow(CF_USERS, u.getId()) .putColumn("user_id", u.getId()) .putColumn("username", u.getUsername()) .putColumn("department", u.getDepartment()); m.execute();
MutationBatch m = keyspace.prepareMutationBatch();

m.withRow(CF_USERS, u.getId())
   .putColumn("user_id", u.getId())
   .putColumn("username", u.getUsername())
   .putColumn("department", u.getDepartment());

m.execute();

But it works with the preparedQuery:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
String INSERT_STATEMENT = "INSERT INTO users (user_id, username, department) VALUES (?, ?, ?);";
keyspace.prepareQuery(CF_CONTENT_URL).withCql(INSERT_STATEMENT).asPreparedStatement()
.withIntegerValue(u.getId()).withStringValue(u.getUsername())
.withIntegerValue(u.getDepartment()).execute();
String INSERT_STATEMENT = "INSERT INTO users (user_id, username, department) VALUES (?, ?, ?);"; keyspace.prepareQuery(CF_CONTENT_URL).withCql(INSERT_STATEMENT).asPreparedStatement() .withIntegerValue(u.getId()).withStringValue(u.getUsername()) .withIntegerValue(u.getDepartment()).execute();
String INSERT_STATEMENT = "INSERT INTO users (user_id, username, department) VALUES (?, ?, ?);";

keyspace.prepareQuery(CF_CONTENT_URL).withCql(INSERT_STATEMENT).asPreparedStatement()
    .withIntegerValue(u.getId()).withStringValue(u.getUsername())
    .withIntegerValue(u.getDepartment()).execute();

Solution

Create the table with COMPACT STORAGE. This unfortunately demands recreating your table, but then the MutationBatch runs fine. There is a warning in the documentation that you cannot update data in tables created with compact storage, but my tests do not confirm that.

1 thought on “Errors and Solutions for Cassandra with Astyanax

Comments are closed.