Skip to content

Commit 1c7d998

Browse files
Stern, Ittay (is9613)philwebb
Stern, Ittay (is9613)
authored andcommitted
Allow spring.data.cassandra.config file to override default values
Update `CassandraAutoConfiguration` so that properties in a `spring.data.cassandra.config` file can override the default values defined in `CassandraProperties`. This commit changes two things: 1. Any primitive on `CassandraProperties` are replaced with object values. This allows distinguishing between defaults values and no-values. Then CassandraAutoConfiguration.mapConfig() can use whenNonNull() predicate to ignore those. 2. `CassandraProperties` no longer populate default values on any property. With that, the defaults can be applied on top of the file spring.data.cassandra.config; i.e. the config file have higher precedence than the defaults, but lower that any spring.data.cassandra.* property. See gh-31238
1 parent 7017e10 commit 1c7d998

File tree

4 files changed

+92
-15
lines changed

4 files changed

+92
-15
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfiguration.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ private Config cassandraConfiguration(CassandraProperties properties) {
126126

127127
private Config applyDefaultFallback(Config config) {
128128
ConfigFactory.invalidateCaches();
129-
return ConfigFactory.defaultOverrides().withFallback(config).withFallback(ConfigFactory.defaultReference())
129+
return ConfigFactory.defaultOverrides().withFallback(config)
130+
.withFallback(mapConfig(CassandraProperties.defaults())).withFallback(ConfigFactory.defaultReference())
130131
.resolve();
131132
}
132133

@@ -153,9 +154,9 @@ private Config mapConfig(CassandraProperties properties) {
153154
mapPoolingOptions(properties, options);
154155
mapRequestOptions(properties, options);
155156
mapControlConnectionOptions(properties, options);
156-
map.from(mapContactPoints(properties))
157+
map.from(mapContactPoints(properties)).whenNonNull()
157158
.to((contactPoints) -> options.add(DefaultDriverOption.CONTACT_POINTS, contactPoints));
158-
map.from(properties.getLocalDatacenter()).to(
159+
map.from(properties.getLocalDatacenter()).whenHasText().to(
159160
(localDatacenter) -> options.add(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, localDatacenter));
160161
return options.build();
161162
}
@@ -210,7 +211,8 @@ private void mapControlConnectionOptions(CassandraProperties properties, Cassand
210211
}
211212

212213
private List<String> mapContactPoints(CassandraProperties properties) {
213-
return properties.getContactPoints().stream()
214+
List<String> contactPoints = properties.getContactPoints();
215+
return (contactPoints == null) ? null : contactPoints.stream()
214216
.map((candidate) -> formatContactPoint(candidate, properties.getPort())).collect(Collectors.toList());
215217
}
216218

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cassandra/CassandraProperties.java

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,16 @@
3838
@ConfigurationProperties(prefix = "spring.data.cassandra")
3939
public class CassandraProperties {
4040

41+
static CassandraProperties defaults() {
42+
CassandraProperties properties = new CassandraProperties();
43+
44+
properties.setContactPoints(new ArrayList<>(Collections.singleton("127.0.0.1:9042")));
45+
properties.setCompression(Compression.NONE);
46+
properties.getControlconnection().setTimeout(Duration.ofSeconds(5));
47+
48+
return properties;
49+
}
50+
4151
/**
4252
* Location of the configuration file to use.
4353
*/
@@ -57,7 +67,7 @@ public class CassandraProperties {
5767
* Cluster node addresses in the form 'host:port', or a simple 'host' to use the
5868
* configured port.
5969
*/
60-
private final List<String> contactPoints = new ArrayList<>(Collections.singleton("127.0.0.1:9042"));
70+
private List<String> contactPoints;
6171

6272
/**
6373
* Port to use if a contact point does not specify one.
@@ -83,7 +93,7 @@ public class CassandraProperties {
8393
/**
8494
* Compression supported by the Cassandra binary protocol.
8595
*/
86-
private Compression compression = Compression.NONE;
96+
private Compression compression;
8797

8898
/**
8999
* Schema action to take at startup.
@@ -143,6 +153,10 @@ public List<String> getContactPoints() {
143153
return this.contactPoints;
144154
}
145155

156+
public void setContactPoints(List<String> contactPoints) {
157+
this.contactPoints = contactPoints;
158+
}
159+
146160
public int getPort() {
147161
return this.port;
148162
}
@@ -266,7 +280,7 @@ public static class Request {
266280
/**
267281
* How many rows will be retrieved simultaneously in a single network round-trip.
268282
*/
269-
private int pageSize;
283+
private Integer pageSize;
270284

271285
private final Throttler throttler = new Throttler();
272286

@@ -294,7 +308,7 @@ public void setSerialConsistency(DefaultConsistencyLevel serialConsistency) {
294308
this.serialConsistency = serialConsistency;
295309
}
296310

297-
public int getPageSize() {
311+
public Integer getPageSize() {
298312
return this.pageSize;
299313
}
300314

@@ -347,7 +361,7 @@ public static class Controlconnection {
347361
/**
348362
* Timeout to use for control queries.
349363
*/
350-
private Duration timeout = Duration.ofSeconds(5);
364+
private Duration timeout;
351365

352366
public Duration getTimeout() {
353367
return this.timeout;
@@ -370,17 +384,17 @@ public static class Throttler {
370384
* Maximum number of requests that can be enqueued when the throttling threshold
371385
* is exceeded.
372386
*/
373-
private int maxQueueSize;
387+
private Integer maxQueueSize;
374388

375389
/**
376390
* Maximum number of requests that are allowed to execute in parallel.
377391
*/
378-
private int maxConcurrentRequests;
392+
private Integer maxConcurrentRequests;
379393

380394
/**
381395
* Maximum allowed request rate.
382396
*/
383-
private int maxRequestsPerSecond;
397+
private Integer maxRequestsPerSecond;
384398

385399
/**
386400
* How often the throttler attempts to dequeue requests. Set this high enough that
@@ -397,23 +411,23 @@ public void setType(ThrottlerType type) {
397411
this.type = type;
398412
}
399413

400-
public int getMaxQueueSize() {
414+
public Integer getMaxQueueSize() {
401415
return this.maxQueueSize;
402416
}
403417

404418
public void setMaxQueueSize(int maxQueueSize) {
405419
this.maxQueueSize = maxQueueSize;
406420
}
407421

408-
public int getMaxConcurrentRequests() {
422+
public Integer getMaxConcurrentRequests() {
409423
return this.maxConcurrentRequests;
410424
}
411425

412426
public void setMaxConcurrentRequests(int maxConcurrentRequests) {
413427
this.maxConcurrentRequests = maxConcurrentRequests;
414428
}
415429

416-
public int getMaxRequestsPerSecond() {
430+
public Integer getMaxRequestsPerSecond() {
417431
return this.maxRequestsPerSecond;
418432
}
419433

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cassandra/CassandraAutoConfigurationTests.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package org.springframework.boot.autoconfigure.cassandra;
1818

1919
import java.time.Duration;
20+
import java.util.Collections;
21+
import java.util.List;
2022

2123
import com.datastax.oss.driver.api.core.CqlIdentifier;
2224
import com.datastax.oss.driver.api.core.CqlSession;
@@ -28,6 +30,7 @@
2830
import com.datastax.oss.driver.internal.core.session.throttling.ConcurrencyLimitingRequestThrottler;
2931
import com.datastax.oss.driver.internal.core.session.throttling.PassThroughRequestThrottler;
3032
import com.datastax.oss.driver.internal.core.session.throttling.RateLimitingRequestThrottler;
33+
import org.assertj.core.api.SoftAssertions;
3134
import org.junit.jupiter.api.Test;
3235

3336
import org.springframework.boot.autoconfigure.AutoConfigurations;
@@ -244,6 +247,44 @@ void driverConfigLoaderWithConfigComplementSettings() {
244247
});
245248
}
246249

250+
@Test // gh-31025
251+
void driverConfigLoaderWithConfigOverridesDefaults() {
252+
String configLocation = "org/springframework/boot/autoconfigure/cassandra/override-defaults.conf";
253+
this.contextRunner.withPropertyValues("spring.data.cassandra.config=" + configLocation).run((context) -> {
254+
assertThat(context).hasSingleBean(DriverConfigLoader.class);
255+
256+
SoftAssertions softly = new SoftAssertions();
257+
258+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
259+
.getString(DefaultDriverOption.SESSION_NAME)).isEqualTo("advanced session");
260+
261+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
262+
.getDuration(DefaultDriverOption.REQUEST_TIMEOUT)).isEqualTo(Duration.ofSeconds(2)); // default
263+
264+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
265+
.getStringList(DefaultDriverOption.CONTACT_POINTS)).isEqualTo(Collections.singletonList("1.2.3.4:5678"));
266+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
267+
.getBoolean(DefaultDriverOption.RESOLVE_CONTACT_POINTS)).isFalse();
268+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
269+
.getInt(DefaultDriverOption.REQUEST_PAGE_SIZE)).isEqualTo(11);
270+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
271+
.getString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)).isEqualTo("datacenter1");
272+
273+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
274+
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_CONCURRENT_REQUESTS)).isEqualTo(22);
275+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
276+
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_REQUESTS_PER_SECOND)).isEqualTo(33);
277+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
278+
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_QUEUE_SIZE)).isEqualTo(44);
279+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
280+
.getDuration(DefaultDriverOption.CONTROL_CONNECTION_TIMEOUT)).isEqualTo(Duration.ofMillis(5555));
281+
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
282+
.getString(DefaultDriverOption.PROTOCOL_COMPRESSION)).isEqualTo("SNAPPY");
283+
284+
softly.assertAll();
285+
});
286+
}
287+
247288
@Test
248289
void driverConfigLoaderWithConfigCreateProfiles() {
249290
String configLocation = "org/springframework/boot/autoconfigure/cassandra/profiles.conf";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
datastax-java-driver {
2+
basic {
3+
session-name = advanced session
4+
load-balancing-policy {
5+
local-datacenter = datacenter1
6+
}
7+
request.page-size = 11
8+
contact-points = [ "1.2.3.4:5678" ]
9+
}
10+
advanced {
11+
throttler {
12+
max-concurrent-requests = 22
13+
max-requests-per-second = 33
14+
max-queue-size = 44
15+
}
16+
control-connection.timeout = 5555
17+
protocol.compression = SNAPPY
18+
resolve-contact-points = false
19+
}
20+
}

0 commit comments

Comments
 (0)