or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

database-configuration.mddatabase-initialization.mdindex.mdmysql-container.mdprovider-pattern.mdr2dbc-integration.md

provider-pattern.mddocs/

0

# Provider Pattern

1

2

Factory pattern implementation for creating MySQL containers from connection URLs and configuration objects, supporting integration with Testcontainers JDBC URL pattern and programmatic container creation.

3

4

## Capabilities

5

6

### MySQLContainerProvider

7

8

Factory class for creating MySQL containers through the provider pattern, enabling integration with Testcontainers JDBC URL functionality.

9

10

```java { .api }

11

/**

12

* Factory for MySQL containers implementing JdbcDatabaseContainerProvider

13

*/

14

public class MySQLContainerProvider extends JdbcDatabaseContainerProvider {

15

16

/**

17

* Checks if this provider supports the given database type

18

* @param databaseType Database type identifier (e.g., "mysql")

19

* @return true if databaseType equals "mysql", false otherwise

20

*/

21

public boolean supports(String databaseType);

22

23

/**

24

* Creates a new MySQL container instance with default configuration

25

* Uses default MySQL image tag and standard settings

26

* @return New MySQLContainer instance with default settings

27

*/

28

public JdbcDatabaseContainer newInstance();

29

30

/**

31

* Creates a new MySQL container instance with specified image tag

32

* @param tag MySQL Docker image tag (e.g., "8.0", "5.7")

33

* @return New MySQLContainer instance with specified tag

34

*/

35

public JdbcDatabaseContainer newInstance(String tag);

36

37

/**

38

* Creates a new MySQL container instance from a Testcontainers connection URL

39

* Parses the connection URL to extract configuration parameters

40

* @param connectionUrl Testcontainers connection URL with parameters

41

* @return New MySQLContainer instance configured from the URL

42

*/

43

public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl);

44

}

45

```

46

47

### Provider Registration and Discovery

48

49

The MySQLContainerProvider is automatically registered with the Testcontainers framework through Java's ServiceLoader mechanism, enabling automatic discovery and usage.

50

51

**Usage Examples:**

52

53

```java

54

// Direct provider usage

55

MySQLContainerProvider provider = new MySQLContainerProvider();

56

57

// Check if provider supports MySQL

58

boolean supportsMySQL = provider.supports("mysql"); // true

59

boolean supportsPostgres = provider.supports("postgresql"); // false

60

61

// Create container with default settings

62

JdbcDatabaseContainer container = provider.newInstance();

63

64

// Create container with specific tag

65

JdbcDatabaseContainer mysql8 = provider.newInstance("8.0");

66

JdbcDatabaseContainer mysql57 = provider.newInstance("5.7");

67

68

// Start and use the container

69

mysql8.start();

70

String jdbcUrl = mysql8.getJdbcUrl();

71

```

72

73

### JDBC URL Integration

74

75

Integration with Testcontainers JDBC URL pattern for automatic container creation and management.

76

77

**JDBC URL Pattern:**

78

79

```

80

jdbc:tc:mysql:[tag]://[host]/[database][?parameters]

81

```

82

83

**URL Parameters:**

84

85

- `TC_DAEMON=true` - Keep container running after test completion

86

- `TC_REUSABLE=true` - Reuse existing container if available

87

- `user=username` - Database username

88

- `password=password` - Database password

89

90

**Usage Examples:**

91

92

```java

93

// Using Testcontainers JDBC URL directly

94

String jdbcUrl = "jdbc:tc:mysql:8.0://localhost/testdb?user=testuser&password=testpass";

95

96

Connection connection = DriverManager.getConnection(jdbcUrl);

97

// Container is automatically created, started, and configured

98

```

99

100

**Advanced JDBC URL Usage:**

101

102

```java

103

// With container reuse and daemon mode

104

String jdbcUrl = "jdbc:tc:mysql:8.0://localhost/myapp_test" +

105

"?user=appuser&password=secret" +

106

"&TC_REUSABLE=true&TC_DAEMON=true";

107

108

// Use with connection pool

109

HikariConfig config = new HikariConfig();

110

config.setJdbcUrl(jdbcUrl);

111

config.setUsername("appuser");

112

config.setPassword("secret");

113

HikariDataSource dataSource = new HikariDataSource(config);

114

```

115

116

### ConnectionUrl Parameter Extraction

117

118

The provider extracts configuration from Testcontainers ConnectionUrl objects to configure MySQL containers.

119

120

```java { .api }

121

/**

122

* Creates container from ConnectionUrl with automatic parameter extraction

123

* Supported parameters:

124

* - user: Database username

125

* - password: Database password

126

* - Database name from URL path

127

* - Image tag from URL host specification

128

*/

129

public JdbcDatabaseContainer newInstance(ConnectionUrl connectionUrl);

130

```

131

132

**Parameter Extraction Logic:**

133

134

```java

135

// Example ConnectionUrl parsing

136

// URL: jdbc:tc:mysql:8.0://localhost/ecommerce?user=shop_user&password=shop_pass

137

138

// Extracted configuration:

139

// - Image: mysql:8.0

140

// - Database: ecommerce

141

// - Username: shop_user

142

// - Password: shop_pass

143

```

144

145

### Integration Examples

146

147

**Spring Boot Integration:**

148

149

```java

150

// application-test.properties

151

spring.datasource.url=jdbc:tc:mysql:8.0://localhost/testdb?user=test&password=test

152

spring.datasource.driver-class-name=org.testcontainers.jdbc.ContainerDatabaseDriver

153

154

// Spring will automatically create and manage the MySQL container

155

@SpringBootTest

156

class SpringIntegrationTest {

157

158

@Autowired

159

private DataSource dataSource;

160

161

@Test

162

void testDatabaseConnection() throws SQLException {

163

try (Connection conn = dataSource.getConnection()) {

164

assertTrue(conn.isValid(5));

165

}

166

}

167

}

168

```

169

170

**JUnit 5 with Provider Pattern:**

171

172

```java

173

class ProviderBasedTest {

174

175

private static MySQLContainerProvider provider;

176

private static JdbcDatabaseContainer mysql;

177

178

@BeforeAll

179

static void setup() {

180

provider = new MySQLContainerProvider();

181

mysql = provider.newInstance("8.0");

182

mysql.start();

183

}

184

185

@AfterAll

186

static void cleanup() {

187

if (mysql != null) {

188

mysql.stop();

189

}

190

}

191

192

@Test

193

void testProviderCreatedContainer() throws SQLException {

194

String jdbcUrl = mysql.getJdbcUrl();

195

assertNotNull(jdbcUrl);

196

assertTrue(jdbcUrl.contains("mysql"));

197

198

try (Connection conn = mysql.createConnection("")) {

199

assertTrue(conn.isValid(5));

200

}

201

}

202

}

203

```

204

205

**Multiple Database Versions:**

206

207

```java

208

class MultiVersionTest {

209

210

@ParameterizedTest

211

@ValueSource(strings = {"5.7", "8.0", "8.1"})

212

void testWithDifferentMySQLVersions(String version) {

213

MySQLContainerProvider provider = new MySQLContainerProvider();

214

215

try (JdbcDatabaseContainer mysql = provider.newInstance(version)) {

216

mysql.start();

217

218

// Test MySQL version-specific features

219

try (Connection conn = mysql.createConnection("")) {

220

DatabaseMetaData metaData = conn.getMetaData();

221

String dbVersion = metaData.getDatabaseProductVersion();

222

assertTrue(dbVersion.startsWith(version));

223

}

224

}

225

}

226

}

227

```

228

229

### Provider Constants and Configuration

230

231

```java { .api }

232

// Internal provider constants

233

private static final String USER_PARAM = "user";

234

private static final String PASSWORD_PARAM = "password";

235

236

// Default behavior

237

// - Uses MySQLContainer.DEFAULT_TAG for default instances

238

// - Uses MySQLContainer.IMAGE for base image name

239

// - Supports MySQLContainer.NAME ("mysql") as database type identifier

240

```

241

242

**Provider Behavior:**

243

244

1. **Database Type Support**: Only responds to "mysql" database type

245

2. **Default Configuration**: Uses deprecated DEFAULT_TAG for backward compatibility

246

3. **Parameter Extraction**: Automatically extracts user/password from connection URLs

247

4. **Container Creation**: Always returns MySQLContainer instances cast to JdbcDatabaseContainer

248

249

### Error Handling

250

251

**Provider Validation:**

252

253

```java

254

MySQLContainerProvider provider = new MySQLContainerProvider();

255

256

// Unsupported database type

257

boolean supported = provider.supports("postgresql"); // false

258

259

// Null tag handling

260

JdbcDatabaseContainer container = provider.newInstance(null); // Falls back to default

261

262

// Invalid connection URL handling

263

try {

264

ConnectionUrl invalidUrl = /* malformed URL */;

265

JdbcDatabaseContainer container = provider.newInstance(invalidUrl);

266

} catch (Exception e) {

267

// Handle URL parsing errors

268

}

269

```

270

271

**JDBC URL Error Handling:**

272

273

```java

274

try {

275

String invalidUrl = "jdbc:tc:mysql:invalid-tag://localhost/db";

276

Connection conn = DriverManager.getConnection(invalidUrl);

277

} catch (SQLException e) {

278

// Handle container creation or connection failures

279

System.err.println("Failed to create MySQL container: " + e.getMessage());

280

}

281

```

282

283

### Best Practices

284

285

**Provider Usage Patterns:**

286

287

```java

288

// Prefer direct MySQLContainer creation for complex configurations

289

MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0")

290

.withDatabaseName("complex_app")

291

.withConfigurationOverride("custom-mysql.cnf")

292

.withInitScript("complex-schema.sql");

293

294

// Use provider pattern for simple, URL-driven configurations

295

String simpleUrl = "jdbc:tc:mysql:8.0://localhost/simple_db?user=test&password=test";

296

Connection conn = DriverManager.getConnection(simpleUrl);

297

298

// Use provider for multiple similar containers

299

MySQLContainerProvider provider = new MySQLContainerProvider();

300

List<JdbcDatabaseContainer> containers = Arrays.asList("5.7", "8.0", "8.1")

301

.stream()

302

.map(provider::newInstance)

303

.collect(Collectors.toList());

304

```

305

306

**Integration Considerations:**

307

308

- Provider pattern is ideal for framework integration (Spring, etc.)

309

- Direct container creation offers more configuration flexibility

310

- JDBC URL pattern provides the simplest setup for basic use cases

311

- Container reuse and daemon modes are valuable for development environments