Search code examples
cassandraastyanax

Astyanax session not initialized when using a keyspace built with CqlFamilyFactory


I'm writing test cases against Astyanax's EmbeddedCassandra. I tried to use CqlFamilyFactory to build the context, and getting a NPE when trying to execute dropKeyspace:

Here's the init code:

    ConnectionPoolConfiguration cpConfig = new ConnectionPoolConfigurationImpl("cassandra connection pool")
        .setPort(9171)
        .setSeeds("127.0.0.1:9171")
        .setMaxConnsPerHost(4);

    m_context = new AstyanaxContext.Builder()
        .forCluster("test-cluster")
        .forKeyspace("testkeyspace")
        .withAstyanaxConfiguration(new AstyanaxConfigurationImpl().setDiscoveryType(NodeDiscoveryType.NONE))
        .withConnectionPoolConfiguration(cpConfig)
        .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
        .buildKeyspace(CqlFamilyFactory.getInstance());

    m_context.start();

    m_context.getClient().dropKeyspace();

This will result in NPE due to session being null at CqlKeyspaceImpl:276 (astyanax-cql-2.0.1):

return new CqlOperationResultImpl<SchemaChangeResult>(session.execute("DROP KEYSPACE " + keyspaceName), null);

I'm guessing that I am not specifying something that the context would need to create a session, but I wasn't able to find many examples of CqlFamilyFactory being used.

The code works when using ThriftFamilyFactory to build the keyspace.


Solution

  • For CqlFamilyFactory to initialize session, ConnectionPoolProxy.setHosts need to be called, which can be called by NodeDiscoveryImpl.update. And it needs hostSupplier to be available.

    Following is sample code that works with either TOKEN_AWARE or DISCOVERY_SERVICE:

    Supplier<List<Host>> hostSupplier = new Supplier<List<Host>>() {
                @Override
                public List<Host> get() {
                    List<Host> hosts = new ArrayList<>();
                    for (HostAndPort hostAndPort : properties.getSeeds()) {
                        hosts.add(new Host(hostAndPort.toString(), 9160));
                    }
                    return hosts;
                }
            };
    AstyanaxConfiguration astyanaxConfiguration = new AstyanaxConfigurationImpl()
                    .setDiscoveryType(NodeDiscoveryType.TOKEN_AWARE)   
                    .setCqlVersion(properties.getCQLVersion())
                    .setTargetCassandraVersion(properties.getVersion());
    ConnectionPoolConfiguration poolConfiguration = new ConnectionPoolConfigurationImpl("MY CONNECTION POOL")
                    .setSeeds(Joiner.on(",").join(properties.getSeeds()))
                    .setPort(properties.getPort())
                    .setMaxConnsPerHost(3)
                    .setAuthenticationCredentials(new SimpleAuthenticationCredentials(properties.getUsername(), properties.getPassword()));
    context = new AstyanaxContext.Builder()
                    .forCluster(properties.getClusterName())
                    .forKeyspace(properties.getKeyspace())
                    .withHostSupplier(hostSupplier)
                    .withAstyanaxConfiguration(astyanaxConfiguration)
                    .withConnectionPoolConfiguration(poolConfiguration)
                    .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
                    .buildKeyspace(CqlFamilyFactory.getInstance());
    

    More sample code can be found https://github.com/Netflix/astyanax/blob/master/astyanax-test/src/main/java/com/netflix/astyanax/cql/test/utils/AstyanaxContextFactory.java