Question

I am tyring to insert into Composite Column in Cassandra column family using Astyanax client. Each column will be a composite column meaning its value will be made of three values as shown in my ComplexType class. 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. (Let me know if my above column family is not right for my below use case.)

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) {

    }
}

Below is the exception, I am getting everytime from the upsertCompositeAttributes method.

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());
}

I am running Cassandra 1.2.9 and Astyanax 1.56.37

Was it helpful?

Solution

Comparator element in schema definition describes column name, not column value.

In case of your schema, Cassandra expects you to give it a complex key with 3 components, but gets a simple string and complains about it by saying:

Not enough bytes to read value of component 0.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top