0
# Wait Strategies and Database Delegation
1
2
Advanced wait strategies and database operation delegation for ensuring container readiness and executing database operations.
3
4
## Capabilities
5
6
### Cassandra Query Wait Strategy
7
8
Custom wait strategy that ensures Cassandra is ready to accept CQL queries before considering the container ready for use.
9
10
```java { .api }
11
/**
12
* Waits until Cassandra returns its version by executing a query.
13
* This strategy ensures the database is not only running but ready to process CQL queries.
14
*/
15
public class CassandraQueryWaitStrategy extends AbstractWaitStrategy {
16
/**
17
* Wait until Cassandra is ready by executing version query.
18
* Executes "SELECT release_version FROM system.local" until success or timeout.
19
*/
20
protected void waitUntilReady();
21
}
22
```
23
24
**Usage Examples:**
25
26
```java
27
import org.testcontainers.cassandra.CassandraContainer;
28
import org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy;
29
30
// The CassandraContainer uses CassandraQueryWaitStrategy by default
31
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2");
32
// No need to explicitly set wait strategy - it's automatic
33
34
// Manual wait strategy configuration (if needed for customization)
35
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
36
.waitingFor(new CassandraQueryWaitStrategy());
37
```
38
39
**Wait Strategy Process:**
40
41
1. Container starts and basic Docker health checks pass
42
2. Wait strategy begins executing test queries
43
3. Retries "SELECT release_version FROM system.local" query
44
4. Continues until query succeeds or timeout is reached
45
5. Container is marked ready only after successful query execution
46
47
**Timeout Configuration:**
48
49
```java
50
// Custom timeout (inherits from AbstractWaitStrategy)
51
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
52
.waitingFor(new CassandraQueryWaitStrategy()
53
.withStartupTimeout(Duration.ofMinutes(5)));
54
```
55
56
### Database Delegate for Script Execution
57
58
Database delegate that handles CQL script and statement execution via the cqlsh command inside the container.
59
60
```java { .api }
61
/**
62
* Cassandra database delegate for executing CQL statements and scripts.
63
* Uses cqlsh command directly inside the container for maximum compatibility.
64
*/
65
public class CassandraDatabaseDelegate extends AbstractDatabaseDelegate<Void> {
66
/**
67
* Create database delegate for the given container
68
* @param container Container state for accessing the running container
69
*/
70
public CassandraDatabaseDelegate(ContainerState container);
71
72
/**
73
* Execute CQL statement or script file
74
* @param statement CQL statement to execute (if not null/empty)
75
* @param scriptPath Path to script file inside container (if statement is null/empty)
76
* @param lineNumber Line number for error reporting
77
* @param continueOnError Whether to continue execution on error
78
* @param ignoreFailedDrops Whether to ignore failed DROP statements
79
*/
80
public void execute(
81
String statement,
82
String scriptPath,
83
int lineNumber,
84
boolean continueOnError,
85
boolean ignoreFailedDrops
86
);
87
}
88
```
89
90
**Internal Usage:**
91
92
The database delegate is primarily used internally by the container for:
93
- Executing initialization scripts via `withInitScript()`
94
- Wait strategy query execution
95
- Internal database operations
96
97
**Execution Methods:**
98
99
```java
100
// Statement execution (used internally)
101
delegate.execute("CREATE KEYSPACE test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}",
102
null, 1, false, false);
103
104
// Script file execution (used internally)
105
delegate.execute(null, "/tmp/init.cql", -1, false, false);
106
```
107
108
**Command Generation:**
109
110
The delegate constructs cqlsh commands based on container configuration:
111
112
```bash
113
# Basic command
114
cqlsh -e "SELECT release_version FROM system.local"
115
116
# With authentication (when container has auth enabled)
117
cqlsh -u cassandra -p cassandra -e "SELECT release_version FROM system.local"
118
119
# Script file execution
120
cqlsh -f /tmp/init.cql
121
122
# With authentication for script
123
cqlsh -u cassandra -p cassandra -f /tmp/init.cql
124
```
125
126
### Error Handling and Exceptions
127
128
Both wait strategies and database delegates handle various error conditions:
129
130
**Wait Strategy Errors:**
131
132
```java
133
import org.testcontainers.containers.ContainerLaunchException;
134
135
try {
136
cassandra.start();
137
} catch (ContainerLaunchException e) {
138
// Wait strategy timeout or query execution failure
139
if (e.getMessage().contains("Timed out waiting for Cassandra")) {
140
logger.error("Cassandra failed to become ready within timeout", e);
141
}
142
}
143
```
144
145
**Database Delegate Errors:**
146
147
```java
148
import org.testcontainers.ext.ScriptUtils.ScriptStatementFailedException;
149
150
// These exceptions are thrown internally and propagated through container methods
151
try {
152
cassandra.withInitScript("invalid-script.cql").start();
153
} catch (ScriptStatementFailedException e) {
154
logger.error("CQL script execution failed at line " + e.getLineNumber(), e);
155
}
156
```
157
158
### Custom Wait Strategy Implementation
159
160
For advanced use cases, you can extend the wait strategy:
161
162
```java
163
import org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy;
164
165
public class CustomCassandraWaitStrategy extends CassandraQueryWaitStrategy {
166
@Override
167
protected void waitUntilReady() {
168
// Custom readiness logic
169
super.waitUntilReady(); // Execute standard version query
170
171
// Additional custom checks
172
DatabaseDelegate delegate = new CassandraDatabaseDelegate(waitStrategyTarget);
173
delegate.execute("SELECT COUNT(*) FROM system.peers", "", 1, false, false);
174
}
175
}
176
177
// Usage
178
CassandraContainer cassandra = new CassandraContainer("cassandra:3.11.2")
179
.waitingFor(new CustomCassandraWaitStrategy());
180
```
181
182
## Deprecated Wait Strategy and Delegate
183
184
Legacy implementations in the `org.testcontainers.containers` package are deprecated:
185
186
```java { .api }
187
/**
188
* @deprecated use org.testcontainers.cassandra.wait.CassandraQueryWaitStrategy instead
189
*/
190
@Deprecated
191
public class CassandraQueryWaitStrategy extends AbstractWaitStrategy {
192
protected void waitUntilReady();
193
}
194
195
/**
196
* @deprecated use org.testcontainers.cassandra.delegate.CassandraDatabaseDelegate instead
197
*/
198
@Deprecated
199
public class CassandraDatabaseDelegate extends AbstractDatabaseDelegate<Session> {
200
public CassandraDatabaseDelegate(ContainerState container);
201
public void execute(String statement, String scriptPath, int lineNumber,
202
boolean continueOnError, boolean ignoreFailedDrops);
203
}
204
```
205
206
**Key Differences:**
207
208
- **Current implementation**: Uses cqlsh command execution, returns `Void` connection type
209
- **Deprecated implementation**: Uses DataStax driver Session objects, requires driver 3.x dependency
210
211
The current implementation is more robust and doesn't require specific driver versions, making it more suitable for diverse testing environments.