or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

container-configuration.mdindex.mdjdbc-connectivity.mdr2dbc-connectivity.md

r2dbc-connectivity.mddocs/

0

# R2DBC Connectivity

1

2

Reactive database connectivity using R2DBC for non-blocking database operations. Provides factory methods and configuration options for reactive programming patterns with Oracle databases.

3

4

## Capabilities

5

6

### R2DBC Container Wrapper

7

8

Wraps Oracle XE containers to provide R2DBC connectivity with automatic connection factory configuration and lifecycle management delegation.

9

10

```java { .api }

11

public class OracleR2DBCDatabaseContainer implements R2DBCDatabaseContainer {

12

public OracleR2DBCDatabaseContainer(OracleContainer container);

13

public static ConnectionFactoryOptions getOptions(OracleContainer container);

14

public ConnectionFactoryOptions configure(ConnectionFactoryOptions options);

15

}

16

```

17

18

**Parameters:**

19

- `container (OracleContainer)`: Underlying Oracle container instance

20

21

**Returns:**

22

- `ConnectionFactoryOptions`: Configured R2DBC connection options

23

- `OracleR2DBCDatabaseContainer`: R2DBC wrapper instance

24

25

**Usage Example:**

26

```java

27

// Create Oracle container

28

OracleContainer oracleContainer = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim")

29

.withDatabaseName("r2dbc_test")

30

.withUsername("r2dbcuser")

31

.withPassword("r2dbcpass");

32

33

// Wrap with R2DBC container

34

OracleR2DBCDatabaseContainer r2dbcContainer =

35

new OracleR2DBCDatabaseContainer(oracleContainer);

36

37

// Start container (delegated to underlying Oracle container)

38

r2dbcContainer.start();

39

40

// Get connection factory options

41

ConnectionFactoryOptions options = OracleR2DBCDatabaseContainer.getOptions(oracleContainer);

42

```

43

44

### Connection Factory Configuration

45

46

Automatically configures R2DBC connection factory options with Oracle-specific driver settings, host/port mapping, and authentication credentials.

47

48

```java { .api }

49

public ConnectionFactoryOptions configure(ConnectionFactoryOptions options);

50

```

51

52

**Parameters:**

53

- `options (ConnectionFactoryOptions)`: Base connection factory options

54

55

**Returns:**

56

- `ConnectionFactoryOptions`: Configured options with Oracle container details

57

58

**Usage Example:**

59

```java

60

OracleContainer container = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim");

61

container.start();

62

63

OracleR2DBCDatabaseContainer r2dbcContainer = new OracleR2DBCDatabaseContainer(container);

64

65

// Configure connection factory options

66

ConnectionFactoryOptions baseOptions = ConnectionFactoryOptions.builder()

67

.option(ConnectionFactoryOptions.DRIVER, "oracle")

68

.build();

69

70

ConnectionFactoryOptions configuredOptions = r2dbcContainer.configure(baseOptions);

71

72

// Result includes:

73

// - HOST: container.getHost()

74

// - PORT: container.getMappedPort(OracleContainer.ORACLE_PORT)

75

// - DATABASE: container.getDatabaseName()

76

// - USER: container.getUsername()

77

// - PASSWORD: container.getPassword()

78

```

79

80

### R2DBC Container Provider

81

82

Service Provider Interface (SPI) implementation for automatic R2DBC container discovery and creation with connection factory metadata support.

83

84

```java { .api }

85

public class OracleR2DBCDatabaseContainerProvider implements R2DBCDatabaseContainerProvider {

86

static final String DRIVER = "oracle";

87

88

public boolean supports(ConnectionFactoryOptions options);

89

public R2DBCDatabaseContainer createContainer(ConnectionFactoryOptions options);

90

public ConnectionFactoryMetadata getMetadata(ConnectionFactoryOptions options);

91

}

92

```

93

94

**Parameters:**

95

- `options (ConnectionFactoryOptions)`: R2DBC connection factory options

96

97

**Returns:**

98

- `boolean`: Whether provider supports the driver type

99

- `R2DBCDatabaseContainer`: New R2DBC container instance

100

- `ConnectionFactoryMetadata`: Connection metadata with defaults

101

102

**Usage Example:**

103

```java

104

// Create connection factory options

105

ConnectionFactoryOptions options = ConnectionFactoryOptions.builder()

106

.option(ConnectionFactoryOptions.DRIVER, "oracle")

107

.option(ConnectionFactoryOptions.DATABASE, "testdb")

108

.option(IMAGE_TAG_OPTION, "18.4.0-slim")

109

.option(REUSABLE_OPTION, true)

110

.build();

111

112

// Use provider

113

OracleR2DBCDatabaseContainerProvider provider = new OracleR2DBCDatabaseContainerProvider();

114

115

// Check support

116

boolean supports = provider.supports(options); // true for oracle driver

117

118

// Create container

119

R2DBCDatabaseContainer r2dbcContainer = provider.createContainer(options);

120

121

// Get metadata with defaults

122

ConnectionFactoryMetadata metadata = provider.getMetadata(options);

123

// Automatically adds default USER and PASSWORD if not specified

124

```

125

126

### Lifecycle Management

127

128

R2DBC containers delegate lifecycle operations to the underlying Oracle container while implementing the Startable interface for seamless integration.

129

130

```java { .api }

131

// Delegated methods from Startable interface

132

public void start();

133

public void stop();

134

public boolean isRunning();

135

```

136

137

**Usage Example:**

138

```java

139

OracleContainer oracleContainer = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim");

140

OracleR2DBCDatabaseContainer r2dbcContainer = new OracleR2DBCDatabaseContainer(oracleContainer);

141

142

// Lifecycle operations (delegated to Oracle container)

143

r2dbcContainer.start();

144

boolean running = r2dbcContainer.isRunning();

145

r2dbcContainer.stop();

146

147

// Container state is managed by underlying Oracle container

148

assertEquals(oracleContainer.isRunning(), r2dbcContainer.isRunning());

149

```

150

151

## Integration Patterns

152

153

### Spring WebFlux Integration

154

155

```java

156

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)

157

@Testcontainers

158

class ReactiveOracleTest {

159

160

@Container

161

static OracleContainer oracle = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim")

162

.withDatabaseName("reactive_test");

163

164

@DynamicPropertySource

165

static void configureProperties(DynamicPropertyRegistry registry) {

166

ConnectionFactoryOptions options = OracleR2DBCDatabaseContainer.getOptions(oracle);

167

168

registry.add("spring.r2dbc.url", () ->

169

"r2dbc:oracle://" + options.getRequiredValue(ConnectionFactoryOptions.HOST) +

170

":" + options.getRequiredValue(ConnectionFactoryOptions.PORT) +

171

"/" + options.getRequiredValue(ConnectionFactoryOptions.DATABASE)

172

);

173

registry.add("spring.r2dbc.username", oracle::getUsername);

174

registry.add("spring.r2dbc.password", oracle::getPassword);

175

}

176

177

@Autowired

178

private R2dbcEntityTemplate template;

179

180

@Test

181

void testReactiveConnection() {

182

StepVerifier.create(

183

template.getDatabaseClient()

184

.sql("SELECT 1 FROM DUAL")

185

.map(row -> row.get(0, Integer.class))

186

.one()

187

)

188

.expectNext(1)

189

.verifyComplete();

190

}

191

}

192

```

193

194

### Direct R2DBC Usage

195

196

```java

197

@Test

198

void testDirectR2DBCUsage() {

199

OracleContainer container = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim");

200

container.start();

201

202

// Get connection factory options

203

ConnectionFactoryOptions options = OracleR2DBCDatabaseContainer.getOptions(container);

204

205

// Create connection factory

206

ConnectionFactory connectionFactory = ConnectionFactories.get(options);

207

208

// Use reactive connection

209

Mono.from(connectionFactory.create())

210

.flatMap(connection ->

211

Mono.from(connection.createStatement("SELECT SYSDATE FROM DUAL")

212

.execute())

213

.flatMap(result ->

214

Mono.from(result.map((row, metadata) ->

215

row.get(0, LocalDateTime.class))))

216

.doFinally(signal -> connection.close())

217

)

218

.as(StepVerifier::create)

219

.expectNextMatches(timestamp -> timestamp != null)

220

.verifyComplete();

221

}

222

```

223

224

### Reactive Repository Pattern

225

226

```java

227

@Repository

228

public class ReactiveUserRepository {

229

230

private final R2dbcEntityTemplate template;

231

232

public ReactiveUserRepository(R2dbcEntityTemplate template) {

233

this.template = template;

234

}

235

236

public Flux<User> findAllUsers() {

237

return template.select(User.class)

238

.from("users")

239

.all();

240

}

241

242

public Mono<User> saveUser(User user) {

243

return template.insert(User.class)

244

.using(user);

245

}

246

247

public Mono<User> findUserById(Long id) {

248

return template.select(User.class)

249

.from("users")

250

.matching(query(where("id").is(id)))

251

.one();

252

}

253

}

254

255

@Test

256

void testReactiveRepository() {

257

// Container setup

258

OracleContainer container = new OracleContainer("gvenzl/oracle-xe:18.4.0-slim")

259

.withInitScript("classpath:schema.sql");

260

container.start();

261

262

// Configure R2DBC

263

ConnectionFactoryOptions options = OracleR2DBCDatabaseContainer.getOptions(container);

264

ConnectionFactory connectionFactory = ConnectionFactories.get(options);

265

R2dbcEntityTemplate template = new R2dbcEntityTemplate(connectionFactory);

266

267

ReactiveUserRepository repository = new ReactiveUserRepository(template);

268

269

// Test reactive operations

270

User newUser = new User("Alice", "alice@example.com");

271

272

StepVerifier.create(

273

repository.saveUser(newUser)

274

.then(repository.findAllUsers().collectList())

275

)

276

.expectNextMatches(users -> users.size() == 1)

277

.verifyComplete();

278

}

279

```

280

281

## Connection Factory Options

282

283

The R2DBC Oracle connection factory supports the following standard options:

284

285

```java { .api }

286

// Standard R2DBC options

287

ConnectionFactoryOptions.DRIVER = "oracle"

288

ConnectionFactoryOptions.HOST = container.getHost()

289

ConnectionFactoryOptions.PORT = container.getMappedPort(OracleContainer.ORACLE_PORT)

290

ConnectionFactoryOptions.DATABASE = container.getDatabaseName()

291

ConnectionFactoryOptions.USER = container.getUsername()

292

ConnectionFactoryOptions.PASSWORD = container.getPassword()

293

294

// Testcontainers-specific options

295

IMAGE_TAG_OPTION = "18.4.0-slim" // Docker image tag

296

REUSABLE_OPTION = true // Container reuse flag

297

```

298

299

## Default Credentials

300

301

When connection factory options don't specify user credentials, the R2DBC provider automatically applies default values:

302

303

- **Default User**: "test" (OracleContainer.APP_USER)

304

- **Default Password**: "test" (OracleContainer.APP_USER_PASSWORD)

305

306

This ensures seamless integration even when credentials are not explicitly configured in the connection factory options.