CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-testcontainers--cassandra

Testcontainers implementation for Apache Cassandra, providing lightweight, throwaway database instances for Java integration testing

Overview
Eval results
Files

wait-strategies-delegation.mddocs/

Wait Strategies and Database Delegation

Advanced wait strategies and database operation delegation for ensuring container readiness and executing database operations.

Capabilities

Cassandra Query Wait Strategy

Custom wait strategy that ensures Cassandra is ready to accept CQL queries before considering the container ready for use.

/**
 * Waits until Cassandra returns its version by executing a query.
 * This strategy ensures the database is not only running but ready to process CQL queries.
 */
public class CassandraQueryWaitStrategy extends AbstractWaitStrategy {
    /**
     * Wait until Cassandra is ready by executing version query.
     * Executes "SELECT release_version FROM system.local" until success or timeout.
     */
    protected void waitUntilReady();
}

Usage Examples:

import org.testcontainers.cassandra.CassandraContainer;
import org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy;

// The CassandraContainer uses CassandraQueryWaitStrategy by default
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2");
// No need to explicitly set wait strategy - it's automatic

// Manual wait strategy configuration (if needed for customization)
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
    .waitingFor(new CassandraQueryWaitStrategy());

Wait Strategy Process:

  1. Container starts and basic Docker health checks pass
  2. Wait strategy begins executing test queries
  3. Retries "SELECT release_version FROM system.local" query
  4. Continues until query succeeds or timeout is reached
  5. Container is marked ready only after successful query execution

Timeout Configuration:

// Custom timeout (inherits from AbstractWaitStrategy)
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
    .waitingFor(new CassandraQueryWaitStrategy()
        .withStartupTimeout(Duration.ofMinutes(5)));

Database Delegate for Script Execution

Database delegate that handles CQL script and statement execution via the cqlsh command inside the container.

/**
 * Cassandra database delegate for executing CQL statements and scripts.
 * Uses cqlsh command directly inside the container for maximum compatibility.
 */
public class CassandraDatabaseDelegate extends AbstractDatabaseDelegate<Void> {
    /**
     * Create database delegate for the given container
     * @param container Container state for accessing the running container
     */
    public CassandraDatabaseDelegate(ContainerState container);
    
    /**
     * Execute CQL statement or script file
     * @param statement CQL statement to execute (if not null/empty)
     * @param scriptPath Path to script file inside container (if statement is null/empty) 
     * @param lineNumber Line number for error reporting
     * @param continueOnError Whether to continue execution on error
     * @param ignoreFailedDrops Whether to ignore failed DROP statements
     */
    public void execute(
        String statement,
        String scriptPath, 
        int lineNumber,
        boolean continueOnError,
        boolean ignoreFailedDrops
    );
}

Internal Usage:

The database delegate is primarily used internally by the container for:

  • Executing initialization scripts via withInitScript()
  • Wait strategy query execution
  • Internal database operations

Execution Methods:

// Statement execution (used internally)
delegate.execute("CREATE KEYSPACE test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}", 
                null, 1, false, false);

// Script file execution (used internally)  
delegate.execute(null, "/tmp/init.cql", -1, false, false);

Command Generation:

The delegate constructs cqlsh commands based on container configuration:

# Basic command
cqlsh -e "SELECT release_version FROM system.local"

# With authentication (when container has auth enabled)
cqlsh -u cassandra -p cassandra -e "SELECT release_version FROM system.local"

# Script file execution
cqlsh -f /tmp/init.cql

# With authentication for script
cqlsh -u cassandra -p cassandra -f /tmp/init.cql

Error Handling and Exceptions

Both wait strategies and database delegates handle various error conditions:

Wait Strategy Errors:

import org.testcontainers.containers.ContainerLaunchException;

try {
    cassandra.start();
} catch (ContainerLaunchException e) {
    // Wait strategy timeout or query execution failure
    if (e.getMessage().contains("Timed out waiting for Cassandra")) {
        logger.error("Cassandra failed to become ready within timeout", e);
    }
}

Database Delegate Errors:

import org.testcontainers.ext.ScriptUtils.ScriptStatementFailedException;

// These exceptions are thrown internally and propagated through container methods
try {
    cassandra.withInitScript("invalid-script.cql").start();
} catch (ScriptStatementFailedException e) {
    logger.error("CQL script execution failed at line " + e.getLineNumber(), e);
}

Custom Wait Strategy Implementation

For advanced use cases, you can extend the wait strategy:

import org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy;

public class CustomCassandraWaitStrategy extends CassandraQueryWaitStrategy {
    @Override
    protected void waitUntilReady() {
        // Custom readiness logic
        super.waitUntilReady(); // Execute standard version query
        
        // Additional custom checks
        DatabaseDelegate delegate = new CassandraDatabaseDelegate(waitStrategyTarget);
        delegate.execute("SELECT COUNT(*) FROM system.peers", "", 1, false, false);
    }
}

// Usage
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
    .waitingFor(new CustomCassandraWaitStrategy());

Deprecated Wait Strategy and Delegate

Legacy implementations in the org.testcontainers.containers package are deprecated:

/**
 * @deprecated use org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy instead
 */
@Deprecated
public class CassandraQueryWaitStrategy extends AbstractWaitStrategy {
    protected void waitUntilReady();
}

/**
 * @deprecated use org.testcontainers.cassandra.delegate.CassandraDatabaseDelegate instead
 */
@Deprecated  
public class CassandraDatabaseDelegate extends AbstractDatabaseDelegate<Session> {
    public CassandraDatabaseDelegate(ContainerState container);
    public void execute(String statement, String scriptPath, int lineNumber, 
                       boolean continueOnError, boolean ignoreFailedDrops);
}

Key Differences:

  • Current implementation: Uses cqlsh command execution, returns Void connection type
  • Deprecated implementation: Uses DataStax driver Session objects, requires driver 3.x dependency

The current implementation is more robust and doesn't require specific driver versions, making it more suitable for diverse testing environments.

Install with Tessl CLI

npx tessl i tessl/maven-org-testcontainers--cassandra

docs

configuration-initialization.md

connection-access.md

container-management.md

index.md

wait-strategies-delegation.md

tile.json