Search code examples
javacassandrahikaricpcassandra-jdbc-driver

How can we upgrade our Java 7 code which uses JDBC connection to Cassandra?


Iam trying to connect to Cassandra DB using Java JDBC. I have a ConnectionManager class with a constructor accepting all the required params for connectivity.

The application uses JDK 7 and now are planning to upgrade the project to JDK 11.

We have configured 24 Cassandra database IPs and we have set out retry value to 10.

We have loaded the IPs into an arraylist and we have looped it and using Java Random utils we are picking the IPs based on arraylist size. Below executeQuery method will loop untill the connection is established for the given IP and will retry for 10times.

  private Connection getConnection() throws SQLException
{
    if (con != null && !con.isClosed()){
        LOG.debug("","Returning existing connection...");
        return con;
    }
    ArrayList<String> hostsCopy = new ArrayList<String>();
    hostsCopy.addAll(hosts);

    while (!hostsCopy.isEmpty())
    {
        String hostToTry = hostsCopy.get(random.nextInt(hostsCopy.size()));
        try
        {
            LOG.debug("","Before connecting : "+CommonUtils.formatDate(Calendar.getInstance().getTime(),"dd-MM-yyyy HH:mm:ss" ));
            con = DriverManager.getConnection("jdbc:cassandra://" + hostToTry + ":" + thriftPort + "/" + keyspace);
            LOG.debug("","After connecting : "+CommonUtils.formatDate(Calendar.getInstance().getTime(),"dd-MM-yyyy HH:mm:ss" ));
            return con;
        } catch (SQLException e)
        {
           LOG.error("", "Unable to connect to " + hostToTry);
            hostsCopy.remove(hostToTry);
        }
        
        try {
            Thread.currentThread().sleep(cassandraConnectionSleepforDifferentHost);
        } catch (InterruptedException e) {
            LOG.error("", "Thread interrupted ");
            e.printStackTrace();
        }
    }

    LOG.error("", "No remaining servers to connect to");
    throw new RuntimeException(CommonServicesErrorConstants.CASSANDRA_DA_002);
}

Look at the execute query method :

public Pair<ResultSet, Statement> executeQuery(String query) throws SQLException 
{
    
    int retryCount = 0;
    while (retryCount < retries)
    {
        try
        {
            Connection con = getConnection();
           
            Statement stmt = con.createStatement();
            
            
            ResultSet rs = stmt.executeQuery(query);
        
            
            return new Pair<ResultSet, Statement>(rs, stmt);
        } catch (SQLTransientConnectionException e0)
        {
            LOG.error("","Transient error executing query, retrying. Retry count " + retryCount);
            e0.printStackTrace();
        } catch (SQLNonTransientConnectionException e1)
        {
            // this means the consistency level cannot be satisfied.
            if (e1.getCause() instanceof UnavailableException)
            {
                LOG.error("","Unavailable exception executing query, giving up");
                throw e1;
            } else
            {
                LOG.error("","Exception executing query");
                e1.printStackTrace();
                LOG.error("","Retrying a different host");

                // we can swallow this, we're getting a new connection anyway
                try
                {
                    close();
                } catch (SQLException e)
                {
                    e.printStackTrace();
                }
            }
        } catch (SQLSyntaxErrorException e2)
        {
            if (UnconfiguredColumnFamilyException.isUnconfiguredColumnFamilyException(e2))
                throw new UnconfiguredColumnFamilyException(e2);
            else
                throw e2;
        }

        retryCount++;
        
        try {
            Thread.currentThread().sleep(cassandraConnectionSleepforRetry);
        } catch (InterruptedException e) {
            LOG.error("", "Thread interrupted ");
            e.printStackTrace();
        }
    }
    
    // Close the connection when all the retries are done
    try
    {
        close();
    } catch (SQLException e)
    {
        e.printStackTrace();
    }
    throw new RuntimeException(CommonServicesErrorConstants.CASSANDRA_DA_004);
}

Question: How can I upgrade this piece of code?

Can we use HikariCp connection pool concept?

Thanks in advance!!


Solution

  • DataStax provides JDBC and ODBC drivers for connecting legacy apps to Apache Cassandra, DataStax Enterprise and Astra DB.

    However, it makes more sense to use the Cassandra Java driver since you will be doing a significant refactoring of your code anyway to upgrade from Java 7.

    Refactoring your code for newer versions of Java but continuing to use JDBC [in my opinion] is a bad decision since you are limited in the Cassandra features you can access compared to the CQL API available in the Java driver. Cheers!