1

I am tyring to insert into Composite Column in Cassandra column family using Astyanax client. Below is my column family in Cassandra.

create column family USER_DATA
with key_validation_class = 'UTF8Type'
and comparator = 'CompositeType(UTF8Type,UTF8Type,DateType)'
and default_validation_class = 'UTF8Type'
and gc_grace = 86400;

I am expecting after insertion, it will look like this

user-id   column1
123      (Column1-Value  Column1-SchemaName  LastModifiedDate)

Below is my java main code-

public static void main(String[] args) {

    ComplexType ct = new ComplexType();
    ct.setVal1("Hello");
    ct.setVal2("World");
    ct.setTimestamp(System.currentTimeMillis());

    // e1 is the column-name and ct is its composite-value.
    attributesMap.put("e1", ct);

    clientDao.upsertCompositeAttributes("123", attributesMap, "USER_DATA");
}

Below is my ComplexType class-

public static class ComplexType {
    @Component(ordinal = 0)
    String val1;

    @Component(ordinal = 1)
    String val2;

    @Component(ordinal = 2)
    long timestamp;


    public String getVal1() {
        return val1;
    }
    public void setVal1(String val1) {
        this.val1 = val1;
    }
    public String getVal2() {
        return val2;
    }
    public void setVal2(String val2) {
        this.val2 = val2;
    }
    public long getTimestamp() {
        return timestamp;
    }
    public void setTimestamp(long timestamp) {
        this.timestamp = timestamp;
    }
}

Below is my upsertCompositeAttributes method in my DAOImpl class.

public void upsertCompositeAttributes(final String rowKey, final Map<String, ComplexType> ct, final String columnFamilyName) {

    try {
        AnnotatedCompositeSerializer<ComplexType> complexTypeSerializer = new AnnotatedCompositeSerializer<ComplexType>(ComplexType.class);

        ColumnFamily columnFamily = new ColumnFamily(columnFamilyName, StringSerializer.get(), StringSerializer.get());

        MutationBatch m = CassandraAstyanaxConnection.getInstance().getKeyspace().prepareMutationBatch();

        ColumnListMutation<String> mutation = m.withRow(columnFamily, rowKey);

        for (Map.Entry<String, ComplexType> entry : ct.entrySet()) {
          // entry.getKey() is the column name and entry.getValue() is its composite value.
            mutation = mutation.putColumn(entry.getKey(), entry.getValue(), complexTypeSerializer, null);
        }

        m.setConsistencyLevel(ConsistencyLevel.CL_ONE).execute();

    } catch (ConnectionException e) {

    } catch (Exception e) {

    }
}

Now I am getting the below exception-

com.netflix.astyanax.connectionpool.exceptions.BadRequestException: BadRequestException: [host=10.109.107.27(10.109.107.27):9160, latency=99(131), attempts=1]InvalidRequestException(why:Not enough bytes to read value of component 0)
    at com.netflix.astyanax.thrift.ThriftConverter.ToConnectionPoolException(ThriftConverter.java:159)
    at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:65)
    at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:28)
    at com.netflix.astyanax.thrift.ThriftSyncConnectionFactoryImpl$ThriftConnection.execute(ThriftSyncConnectionFactoryImpl.java:151)
    at com.netflix.astyanax.connectionpool.impl.AbstractExecuteWithFailoverImpl.tryOperation(AbstractExecuteWithFailoverImpl.java:69)
    at com.netflix.astyanax.connectionpool.impl.AbstractHostPartitionConnectionPool.executeWithFailover(AbstractHostPartitionConnectionPool.java:256)
    at com.netflix.astyanax.thrift.ThriftKeyspaceImpl.executeOperation(ThriftKeyspaceImpl.java:485)
    at com.netflix.astyanax.thrift.ThriftKeyspaceImpl.access$000(ThriftKeyspaceImpl.java:79)
    at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1.execute(ThriftKeyspaceImpl.java:123)
    at com.cassandra.astyanax.CassandraAstyanaxClient.upsertCompositeAttributes(CassandraAstyanaxClient.java:167)
    at com.example.AstyanaxCompositeColumns.main(AstyanaxCompositeColumns.java:24)
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:20833)
    at org.apache.thrift.TServiceClient.receiveBase(TServiceClient.java:78)
    at org.apache.cassandra.thrift.Cassandra$Client.recv_batch_mutate(Cassandra.java:964)
    at org.apache.cassandra.thrift.Cassandra$Client.batch_mutate(Cassandra.java:950)
    at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1$1.internalExecute(ThriftKeyspaceImpl.java:129)
    at com.netflix.astyanax.thrift.ThriftKeyspaceImpl$1$1.internalExecute(ThriftKeyspaceImpl.java:126)
    at com.netflix.astyanax.thrift.AbstractOperationImpl.execute(AbstractOperationImpl.java:60)
    ... 9 more

Below is my CassandraAstyanaxConnection class-

private CassandraAstyanaxConnection() {

    context = new AstyanaxContext.Builder()
    .forCluster(Constants.CLUSTER)
    .forKeyspace(Constants.KEYSPACE)
    .withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
        .setPort(9160)
        .setMaxConnsPerHost(1000)
        .setSeeds("host:9160")
    )
    .withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
        .setCqlVersion("3.0.0")
        .setTargetCassandraVersion("1.2")
        .setConnectionPoolType(ConnectionPoolType.ROUND_ROBIN)
        .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE))
    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
    .buildKeyspace(ThriftFamilyFactory.getInstance());

    context.start();
    keyspace = context.getEntity();

    emp_cf = ColumnFamily.newColumnFamily(
        Constants.COLUMN_FAMILY, 
        StringSerializer.get(), 
        StringSerializer.get());
}

First of all, my column family is correct or not?

create column family USER_DATA
with key_validation_class = 'UTF8Type'
and comparator = 'CompositeType(UTF8Type,UTF8Type,DateType)'
and default_validation_class = 'UTF8Type'
and gc_grace = 86400;

Below is my requirement per our use case-

user-id   column1                                        column2                                     column3
123      (Column1-Value  Column1-SchemaName  LMD)       (Column2-Value Column2-SchemaName  LMD)     (Column3-Value  Column3-SchemaName  LMD)

For each user-id, we will be storing column1 and its value and that value will store these three things always-

(Column1-Value   Column1-SchemaName     LMD)

In my above example, I have show only three columns but it might have more columns.

I am running Cassandra 1.2.9

arsenal
  • 23,366
  • 85
  • 225
  • 331
  • since this is follow on to your previous question (whose answer you have not upvoted or accepted but have used), why don't continue this there? – Martin Serrano Sep 19 '13 at 23:02
  • I thought its a good way to open a new question? I think, I should accept that answer and continue it here? Let me know what do you think? – arsenal Sep 19 '13 at 23:04
  • i guess it could work either way. whatever we do here on this question will probably end up as edits to my answer there. anyway, what version of Astyanax are you using – Martin Serrano Sep 19 '13 at 23:07
  • I am using `1.56.37`. – arsenal Sep 19 '13 at 23:08

1 Answers1

2

When you create the ColumnFamily, the arguments are for the columnName, the rowKey serializer and the column name serializer. The column type serializer (complexTypeSerializer) is only used in the putColumn. You should have:

ColumnFamily columnFamily = new ColumnFamily(columnFamilyName, StringSerializer.get(), StringSerializer.get());

since you are not using composite column names but composite column values.

Martin Serrano
  • 3,727
  • 1
  • 35
  • 48
  • 1
    Ok. After making that change, now I am getting this error `InvalidRequestException(why:Not enough bytes to read value of component 0)`. I have updated my question with the new method that I am using now. Any idea why it is throwing this exception? – arsenal Sep 19 '13 at 23:32
  • can you post the new exception? i will research. – Martin Serrano Sep 19 '13 at 23:34
  • that error is associated with the difference between the CQL column definition and the composite type that is inserted. see http://stackoverflow.com/questions/15446187/astyanax-simple-write-throwing-this-exception-not-enough-bytes-to-read-value-o. I think this is because ComplexType has a long versus a Date – Martin Serrano Sep 19 '13 at 23:52
  • I believe it is something else.. I just changed that method to String and change the column family accordingly as well to have UTF8 instead of DateType. But still I got the same error.. – arsenal Sep 19 '13 at 23:56
  • If possible, you can also try at your end, then it will give much better idea what wrong is going on.. – arsenal Sep 20 '13 at 00:22