or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

container-configuration.mdcontainer-customization.mdcontainer-lifecycle.mddatabase-initialization.mdindex.mdjdbc-connection.mdr2dbc-support.mdurl-parameters-timeouts.md
tile.json

url-parameters-timeouts.mddocs/

URL Parameters and Timeouts

This document covers customizing JDBC URL parameters and configuring container startup and connection timeouts.

Quick Reference

URL Parameter Methods (Fluent Interface, Return SELF):

  • withUrlParam(String paramName, String paramValue) - Add custom JDBC URL parameter

Timeout Methods (Fluent Interface, Return SELF):

  • withStartupTimeoutSeconds(int startupTimeoutSeconds) - Set startup timeout (default: 120 seconds)
  • withConnectTimeoutSeconds(int connectTimeoutSeconds) - Set connection timeout (default: 120 seconds)

Automatic URL Parameters:

  • useSSL=false - Added automatically if not present
  • allowPublicKeyRetrieval=true - Added automatically if not present

Constraints:

  • All configuration methods must be called before start()
  • Timeout values are in seconds (must be positive integers)
  • URL parameters are automatically URL-encoded if necessary

Capabilities

JDBC URL Parameters

Add custom parameters to the JDBC connection URL.

/**
 * Adds a custom parameter to the JDBC connection URL.
 * Parameters are appended as query string parameters (e.g., ?param1=value1&param2=value2).
 *
 * Can be called multiple times to add multiple parameters.
 * Parameters are automatically URL-encoded if necessary.
 * If a parameter with the same name is added multiple times, the last value is used.
 *
 * @param paramName the parameter name (must not be null or empty)
 * @param paramValue the parameter value (can be null or empty)
 * @return self for method chaining (SELF extends MySQLContainer<SELF>)
 * @throws IllegalArgumentException if paramName is null or empty
 */
SELF withUrlParam(String paramName, String paramValue);

Usage Example:

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withUrlParam("serverTimezone", "UTC")
    .withUrlParam("allowMultiQueries", "true")
    .withUrlParam("useUnicode", "true")
    .withUrlParam("characterEncoding", "UTF-8");

mysql.start();

String jdbcUrl = mysql.getJdbcUrl();
// jdbc:mysql://localhost:xxxxx/test?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC&allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8

Common JDBC URL Parameters

Here are commonly used MySQL JDBC URL parameters:

Connection Behavior:

  • serverTimezone - Server timezone (e.g., "UTC", "America/New_York")
  • useSSL - Enable/disable SSL (automatically set to false by container)
  • allowPublicKeyRetrieval - Allow public key retrieval (automatically set to true by container)
  • autoReconnect - Automatically reconnect on connection loss (e.g., "true")

Query Execution:

  • allowMultiQueries - Allow multiple queries in one statement (e.g., "true")
  • rewriteBatchedStatements - Optimize batch inserts (e.g., "true")

Character Encoding:

  • useUnicode - Enable Unicode support (e.g., "true")
  • characterEncoding - Character encoding (e.g., "UTF-8", "utf8mb4")

Performance:

  • cachePrepStmts - Enable prepared statement caching (e.g., "true")
  • prepStmtCacheSize - Prepared statement cache size (e.g., "250")
  • prepStmtCacheSqlLimit - Max SQL length for caching (e.g., "2048")
  • useServerPrepStmts - Use server-side prepared statements (e.g., "true")
  • elideSetAutoCommits - Reduce round trips (e.g., "true")
  • useLocalSessionState - Use local session state (e.g., "true")

Timezone Configuration Example

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.time.ZonedDateTime;
import java.time.ZoneId;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withUrlParam("serverTimezone", "Europe/London")
    .withEnv("TZ", "Europe/London"); // Set container timezone

mysql.start();

try (Connection conn = mysql.createConnection("")) {
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT NOW()");
    rs.next();
    // Date/time returned in Europe/London timezone
}

Multiple Query Support Example

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;
import java.sql.Connection;
import java.sql.Statement;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withUrlParam("allowMultiQueries", "true");

mysql.start();

try (Connection conn = mysql.createConnection("")) {
    Statement stmt = conn.createStatement();

    // Execute multiple statements in one call
    String multiQuery = """
        DROP TABLE IF EXISTS test;
        CREATE TABLE test (id INT, name VARCHAR(50));
        INSERT INTO test VALUES (1, 'Alice'), (2, 'Bob');
        """;

    stmt.execute(multiQuery);
}

Startup Timeout Configuration

Configure how long to wait for the container to start, including image pull time.

/**
 * Sets the maximum time to wait for the container to start, including Docker image
 * pull time if the image is not already present locally.
 *
 * The timeout includes:
 * - Docker image pull time (if image not cached)
 * - Container creation time
 * - Container startup time
 * - Database initialization time
 * - Initialization script execution time
 * - Liveness check time
 *
 * Default: 120 seconds
 *
 * @param startupTimeoutSeconds timeout in seconds (must be positive)
 * @return self for method chaining (SELF extends MySQLContainer<SELF>)
 * @throws IllegalArgumentException if startupTimeoutSeconds is not positive
 */
SELF withStartupTimeoutSeconds(int startupTimeoutSeconds);

Usage Example:

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withStartupTimeoutSeconds(180); // Wait up to 3 minutes

mysql.start();
// Will wait up to 180 seconds for container to become ready

When to Increase Startup Timeout:

  • Slow network (Docker image download takes time)
  • Resource-constrained environments (CI runners, small VMs)
  • Large initialization scripts that take time to execute
  • First run on a machine (no cached Docker images)
  • Complex container configurations

Connection Timeout Configuration

Configure how long to wait for the database to become ready and accept connections.

/**
 * Sets the maximum time to wait for the database to start and establish an initial
 * connection after the container is running.
 *
 * This timeout applies to the connection establishment phase, which includes:
 * - Database server readiness check
 * - Initial connection attempt
 * - Authentication
 *
 * Default: 120 seconds
 *
 * @param connectTimeoutSeconds timeout in seconds (must be positive)
 * @return self for method chaining (SELF extends MySQLContainer<SELF>)
 * @throws IllegalArgumentException if connectTimeoutSeconds is not positive
 */
SELF withConnectTimeoutSeconds(int connectTimeoutSeconds);

Usage Example:

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withConnectTimeoutSeconds(60); // Wait up to 1 minute for connection

mysql.start();
// Will attempt to connect for up to 60 seconds

When to Increase Connection Timeout:

  • Large initialization scripts
  • Slow storage (network-attached storage)
  • Resource-constrained environments
  • Heavy database workloads on container startup
  • Network latency issues

Combined Configuration Example

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withDatabaseName("myapp_test")
    .withUsername("testuser")
    .withPassword("testpass")

    // JDBC URL parameters
    .withUrlParam("serverTimezone", "UTC")
    .withUrlParam("allowMultiQueries", "true")
    .withUrlParam("useUnicode", "true")
    .withUrlParam("characterEncoding", "UTF-8")
    .withUrlParam("cachePrepStmts", "true")
    .withUrlParam("prepStmtCacheSize", "250")

    // Timeout configuration
    .withStartupTimeoutSeconds(180)
    .withConnectTimeoutSeconds(90)

    // Initialization
    .withInitScript("schema.sql");

mysql.start();

String jdbcUrl = mysql.getJdbcUrl();
// All URL parameters are included in the JDBC URL

Performance Optimization Example

Configure JDBC URL parameters for optimal performance in tests:

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withDatabaseName("perftest")

    // Enable prepared statement caching
    .withUrlParam("cachePrepStmts", "true")
    .withUrlParam("prepStmtCacheSize", "250")
    .withUrlParam("prepStmtCacheSqlLimit", "2048")

    // Optimize batch operations
    .withUrlParam("rewriteBatchedStatements", "true")

    // Enable server-side prepared statements
    .withUrlParam("useServerPrepStmts", "true")

    // Reduce round trips
    .withUrlParam("elideSetAutoCommits", "true")
    .withUrlParam("useLocalSessionState", "true")

    .withInitScript("schema.sql");

mysql.start();

Automatic URL Parameters

The MySQL module automatically adds these parameters to the JDBC URL if not already present:

  • useSSL=false: Disables SSL for testing environments where SSL certificates are not configured
  • allowPublicKeyRetrieval=true: Allows the driver to retrieve public keys from the server for authentication

These parameters are added automatically and do not need to be specified via withUrlParam(). However, if you explicitly set them via withUrlParam(), your values will take precedence.

Example:

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"));
mysql.start();

String url = mysql.getJdbcUrl();
// url includes "?useSSL=false&allowPublicKeyRetrieval=true" automatically

To enable SSL (override the automatic parameter):

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withUrlParam("useSSL", "true")
    .withUrlParam("trustCertificateKeyStoreUrl", "file:/path/to/keystore")
    .withUrlParam("trustCertificateKeyStorePassword", "password");

mysql.start();
// SSL is now enabled with custom certificate configuration

CI/CD Environment Configuration

For CI/CD environments with limited resources or slow networks:

import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.utility.DockerImageName;

boolean isCiEnvironment = System.getenv("CI") != null;

MySQLContainer<?> mysql = new MySQLContainer<>(DockerImageName.parse("mysql:8.0"))
    .withDatabaseName("ci_test");

if (isCiEnvironment) {
    mysql
        .withStartupTimeoutSeconds(300)  // 5 minutes for slow CI runners
        .withConnectTimeoutSeconds(120); // 2 minutes for connection
}

mysql.start();

Timeout Troubleshooting

If you encounter timeout-related exceptions:

IllegalStateException: "Container is started, but cannot be accessed"

This typically means the connection timeout was reached. Try:

  1. Increase connection timeout:

    .withConnectTimeoutSeconds(180)
  2. Check container logs for errors:

    .withLogConsumer(new Slf4jLogConsumer(logger))
  3. Verify Docker resources (memory, CPU)

  4. Check network connectivity

  5. Ensure no firewall blocks container ports

Container startup timeout

If the container fails to start within the startup timeout:

  1. Increase startup timeout:

    .withStartupTimeoutSeconds(300)
  2. Check Docker image pull progress (slow network)

  3. Reduce initialization script size or complexity

  4. Verify sufficient Docker resources

  5. Check for port conflicts (rare, as ports are dynamically assigned)

Best Practices

  1. Set Timezone Explicitly: Use withUrlParam("serverTimezone", "UTC") for consistent behavior
  2. Enable Connection Pooling Parameters: Improve performance with prepared statement caching
  3. Configure Timeouts for Environment: Adjust timeouts based on CI vs local development
  4. Use Batch Optimization: Enable rewriteBatchedStatements for bulk inserts
  5. Monitor Parameter Impact: Test performance before and after adding URL parameters
  6. Document Custom Parameters: Explain why specific parameters were chosen
  7. Keep Automatic Parameters: Don't override useSSL=false and allowPublicKeyRetrieval=true unless necessary
  8. Use Environment Detection: Adjust timeouts based on environment (CI vs local)
  9. Call Methods Before Start: All configuration methods must be called before start()
  10. Handle Timeout Exceptions: Catch and handle IllegalStateException for timeout scenarios