0
votes

I have a local Cassandra server (1.1.10), and a column family created with cql3:

CREATE TABLE test_columnfamily (
    key1 text,
    key2 text,
    column1 text,
    PRIMARY KEY (key1, key2));

and I'm trying to insert a row using Hector Java client (version 1.1-2)

public class Test {

    private static final CompositeSerializer compSerializer = new CompositeSerializer();
    private static final StringSerializer strSerializer = new StringSerializer();

    public static void main(String[] args) {
        CassandraHostConfigurator conf = new CassandraHostConfigurator("localhost:9160");

        conf.setCassandraThriftSocketTimeout(10000);
        conf.setRetryDownedHostsDelayInSeconds(30);
        conf.setRetryDownedHostsQueueSize(128);
        conf.setMaxWaitTimeWhenExhausted(60000);
        conf.setRetryDownedHosts(true);
        conf.setLoadBalancingPolicy(new LeastActiveBalancingPolicy());
        conf.setAutoDiscoverHosts(true);
        conf.setHostTimeoutCounter(20);

        Cluster cluster = HFactory.getOrCreateCluster("test", conf);
        Keyspace ks = HFactory.createKeyspace("test_keyspace", cluster);
        Mutator<Composite> compMutator = HFactory.createMutator(ks, compSerializer);

        ColumnFamilyDefinition cfDef = HectorUtils.getColumnFamily(cluster, "test_keyspace", "test_columnfamily");
        System.out.println("Found column family: " + cfDef.getName());

        Composite key = new Composite();
        key.addComponent("key1", strSerializer);
        key.addComponent("key2", strSerializer);
        compMutator.addInsertion(key, "test_columnfamily", HFactory.createColumn(
            "column1", "col1 value", HFactory.createClock(), strSerializer, strSerializer));
        compMutator.execute();
    }
}

I got this exception:

Exception in thread "main" me.prettyprint.hector.api.exceptions.HInvalidRequestException: InvalidRequestException(why:Not enough bytes to read value of component 0)
    at me.prettyprint.cassandra.service.ExceptionsTranslatorImpl.translate(ExceptionsTranslatorImpl.java:45)
    at me.prettyprint.cassandra.connection.HConnectionManager.operateWithFailover(HConnectionManager.java:264)
    at me.prettyprint.cassandra.model.ExecutingKeyspace.doExecuteOperation(ExecutingKeyspace.java:113)
    at me.prettyprint.cassandra.model.MutatorImpl.execute(MutatorImpl.java:243)
    at com.bninc.job.Test.main(Test.java:46)
Caused by: InvalidRequestException(why:Not enough bytes to read value of component 0)
    at org.apache.cassandra.thrift.Cassandra$batch_mutate_result.read(Cassandra.java:20350)
    at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78)
    at org.apache.cassandra.thrift.Cassandra$Client.recv_batch_mutate(Cassandra.java:926)
    at org.apache.cassandra.thrift.Cassandra$Client.batch_mutate(Cassandra.java:912)
    at me.prettyprint.cassandra.model.MutatorImpl$3.execute(MutatorImpl.java:246)
    at me.prettyprint.cassandra.model.MutatorImpl$3.execute(MutatorImpl.java:243)
    at me.prettyprint.cassandra.service.Operation.executeAndSetResult(Operation.java:104)
    at me.prettyprint.cassandra.connection.HConnectionManager.operateWithFailover(HConnectionManager.java:258)
    ... 3 more

Could you please tell me how to make my code work (to insert rows into column family with composite key)? I did see similar questions being asked here and there but couldn't find the exact answer. Thanks in advance!


Edit:

After adding WITH COMPACT STORAGE to the end of CREATE TABLE statement, the exception went away. But the row in the table is:

 key1                             | key2    | column1
----------------------------------+---------+------------
 \x00\x04key1\x00\x00\x04key2\x00 | column1 | col1 value
1

1 Answers

1
votes

You need to use a different row key and column name. For this example, your row key should be key1 and your column name should be made up of the two values key2 and "column1" (note "column1" is a literal string constant).

This is all because of a mapping that takes place under the covers with CQL3. The first primary key is used as a row (or partitioning) key and the remaining primary key values are used as part of a composite column name that also contains the name (not value) of the non-key field being stored.

To go further with this example, that means that if you store three rows that happen to have the same value for key1, you'll end up storing only one Cassandra row. That row will have three columns, one for each value of non-key field "column1" in each of the three rows.