Skip to content

Commit 9e98f69

Browse files
committed
Merge pull request #31238 from ittays
* pr/31238: Polish 'Allow spring.data.cassandra.config file to override default values' Allow spring.data.cassandra.config file to override default values Closes gh-31238
2 parents 7017e10 + 904feb2 commit 9e98f69

File tree

5 files changed

+97
-33
lines changed

5 files changed

+97
-33
lines changed

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

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,6 +19,7 @@
1919
import java.io.IOException;
2020
import java.security.NoSuchAlgorithmException;
2121
import java.time.Duration;
22+
import java.util.Collections;
2223
import java.util.LinkedHashMap;
2324
import java.util.List;
2425
import java.util.Map;
@@ -63,13 +64,23 @@
6364
* @author Eddú Meléndez
6465
* @author Stephane Nicoll
6566
* @author Steffen F. Qvistgaard
67+
* @author Ittay Stern
6668
* @since 1.3.0
6769
*/
6870
@Configuration(proxyBeanMethods = false)
6971
@ConditionalOnClass({ CqlSession.class })
7072
@EnableConfigurationProperties(CassandraProperties.class)
7173
public class CassandraAutoConfiguration {
7274

75+
private static final Config SPRING_BOOT_DEFAULTS;
76+
static {
77+
CassandraDriverOptions options = new CassandraDriverOptions();
78+
options.add(DefaultDriverOption.CONTACT_POINTS, Collections.singletonList("127.0.0.1:9042"));
79+
options.add(DefaultDriverOption.PROTOCOL_COMPRESSION, "none");
80+
options.add(DefaultDriverOption.CONTROL_CONNECTION_TIMEOUT, (int) Duration.ofSeconds(5).toMillis());
81+
SPRING_BOOT_DEFAULTS = options.build();
82+
}
83+
7384
@Bean
7485
@ConditionalOnMissingBean
7586
@Lazy
@@ -118,44 +129,43 @@ public DriverConfigLoader cassandraDriverConfigLoader(CassandraProperties proper
118129
}
119130

120131
private Config cassandraConfiguration(CassandraProperties properties) {
121-
Config config = mapConfig(properties);
122-
Resource configFile = properties.getConfig();
123-
return (configFile != null) ? applyDefaultFallback(config.withFallback(loadConfig(configFile)))
124-
: applyDefaultFallback(config);
125-
}
126-
127-
private Config applyDefaultFallback(Config config) {
128132
ConfigFactory.invalidateCaches();
129-
return ConfigFactory.defaultOverrides().withFallback(config).withFallback(ConfigFactory.defaultReference())
130-
.resolve();
133+
Config config = ConfigFactory.defaultOverrides();
134+
config = config.withFallback(mapConfig(properties));
135+
if (properties.getConfig() != null) {
136+
config = config.withFallback(loadConfig(properties.getConfig()));
137+
}
138+
config = config.withFallback(SPRING_BOOT_DEFAULTS);
139+
config = config.withFallback(ConfigFactory.defaultReference());
140+
return config.resolve();
131141
}
132142

133-
private Config loadConfig(Resource config) {
143+
private Config loadConfig(Resource resource) {
134144
try {
135-
return ConfigFactory.parseURL(config.getURL());
145+
return ConfigFactory.parseURL(resource.getURL());
136146
}
137147
catch (IOException ex) {
138-
throw new IllegalStateException("Failed to load cassandra configuration from " + config, ex);
148+
throw new IllegalStateException("Failed to load cassandra configuration from " + resource, ex);
139149
}
140150
}
141151

142152
private Config mapConfig(CassandraProperties properties) {
143153
CassandraDriverOptions options = new CassandraDriverOptions();
144-
PropertyMapper map = PropertyMapper.get();
154+
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
145155
map.from(properties.getSessionName()).whenHasText()
146156
.to((sessionName) -> options.add(DefaultDriverOption.SESSION_NAME, sessionName));
147-
map.from(properties::getUsername).whenNonNull()
157+
map.from(properties::getUsername)
148158
.to((username) -> options.add(DefaultDriverOption.AUTH_PROVIDER_USER_NAME, username)
149159
.add(DefaultDriverOption.AUTH_PROVIDER_PASSWORD, properties.getPassword()));
150-
map.from(properties::getCompression).whenNonNull()
160+
map.from(properties::getCompression)
151161
.to((compression) -> options.add(DefaultDriverOption.PROTOCOL_COMPRESSION, compression));
152162
mapConnectionOptions(properties, options);
153163
mapPoolingOptions(properties, options);
154164
mapRequestOptions(properties, options);
155165
mapControlConnectionOptions(properties, options);
156166
map.from(mapContactPoints(properties))
157167
.to((contactPoints) -> options.add(DefaultDriverOption.CONTACT_POINTS, contactPoints));
158-
map.from(properties.getLocalDatacenter()).to(
168+
map.from(properties.getLocalDatacenter()).whenHasText().to(
159169
(localDatacenter) -> options.add(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, localDatacenter));
160170
return options.build();
161171
}
@@ -210,8 +220,12 @@ private void mapControlConnectionOptions(CassandraProperties properties, Cassand
210220
}
211221

212222
private List<String> mapContactPoints(CassandraProperties properties) {
213-
return properties.getContactPoints().stream()
214-
.map((candidate) -> formatContactPoint(candidate, properties.getPort())).collect(Collectors.toList());
223+
if (properties.getContactPoints() != null) {
224+
return properties.getContactPoints().stream()
225+
.map((candidate) -> formatContactPoint(candidate, properties.getPort()))
226+
.collect(Collectors.toList());
227+
}
228+
return null;
215229
}
216230

217231
private String formatContactPoint(String candidate, int port) {

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

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

1919
import java.time.Duration;
20-
import java.util.ArrayList;
21-
import java.util.Collections;
2220
import java.util.List;
2321

2422
import com.datastax.oss.driver.api.core.DefaultConsistencyLevel;
@@ -57,7 +55,7 @@ public class CassandraProperties {
5755
* Cluster node addresses in the form 'host:port', or a simple 'host' to use the
5856
* configured port.
5957
*/
60-
private final List<String> contactPoints = new ArrayList<>(Collections.singleton("127.0.0.1:9042"));
58+
private List<String> contactPoints;
6159

6260
/**
6361
* Port to use if a contact point does not specify one.
@@ -83,7 +81,7 @@ public class CassandraProperties {
8381
/**
8482
* Compression supported by the Cassandra binary protocol.
8583
*/
86-
private Compression compression = Compression.NONE;
84+
private Compression compression;
8785

8886
/**
8987
* Schema action to take at startup.
@@ -143,6 +141,10 @@ public List<String> getContactPoints() {
143141
return this.contactPoints;
144142
}
145143

144+
public void setContactPoints(List<String> contactPoints) {
145+
this.contactPoints = contactPoints;
146+
}
147+
146148
public int getPort() {
147149
return this.port;
148150
}
@@ -266,7 +268,7 @@ public static class Request {
266268
/**
267269
* How many rows will be retrieved simultaneously in a single network round-trip.
268270
*/
269-
private int pageSize;
271+
private Integer pageSize;
270272

271273
private final Throttler throttler = new Throttler();
272274

@@ -294,7 +296,7 @@ public void setSerialConsistency(DefaultConsistencyLevel serialConsistency) {
294296
this.serialConsistency = serialConsistency;
295297
}
296298

297-
public int getPageSize() {
299+
public Integer getPageSize() {
298300
return this.pageSize;
299301
}
300302

@@ -347,7 +349,7 @@ public static class Controlconnection {
347349
/**
348350
* Timeout to use for control queries.
349351
*/
350-
private Duration timeout = Duration.ofSeconds(5);
352+
private Duration timeout;
351353

352354
public Duration getTimeout() {
353355
return this.timeout;
@@ -370,17 +372,17 @@ public static class Throttler {
370372
* Maximum number of requests that can be enqueued when the throttling threshold
371373
* is exceeded.
372374
*/
373-
private int maxQueueSize;
375+
private Integer maxQueueSize;
374376

375377
/**
376378
* Maximum number of requests that are allowed to execute in parallel.
377379
*/
378-
private int maxConcurrentRequests;
380+
private Integer maxConcurrentRequests;
379381

380382
/**
381383
* Maximum allowed request rate.
382384
*/
383-
private int maxRequestsPerSecond;
385+
private Integer maxRequestsPerSecond;
384386

385387
/**
386388
* How often the throttler attempts to dequeue requests. Set this high enough that
@@ -397,23 +399,23 @@ public void setType(ThrottlerType type) {
397399
this.type = type;
398400
}
399401

400-
public int getMaxQueueSize() {
402+
public Integer getMaxQueueSize() {
401403
return this.maxQueueSize;
402404
}
403405

404406
public void setMaxQueueSize(int maxQueueSize) {
405407
this.maxQueueSize = maxQueueSize;
406408
}
407409

408-
public int getMaxConcurrentRequests() {
410+
public Integer getMaxConcurrentRequests() {
409411
return this.maxConcurrentRequests;
410412
}
411413

412414
public void setMaxConcurrentRequests(int maxConcurrentRequests) {
413415
this.maxConcurrentRequests = maxConcurrentRequests;
414416
}
415417

416-
public int getMaxRequestsPerSecond() {
418+
public Integer getMaxRequestsPerSecond() {
417419
return this.maxRequestsPerSecond;
418420
}
419421

spring-boot-project/spring-boot-autoconfigure/src/main/resources/META-INF/additional-spring-configuration-metadata.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -492,6 +492,10 @@
492492
"name": "spring.data.cassandra.connection.init-query-timeout",
493493
"defaultValue": "5s"
494494
},
495+
{
496+
"name": "spring.data.cassandra.controlconnection.timeout",
497+
"defaultValue": "5s"
498+
},
495499
{
496500
"name": "spring.data.cassandra.contact-points",
497501
"defaultValue": [

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

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
1717
package org.springframework.boot.autoconfigure.cassandra;
1818

1919
import java.time.Duration;
20+
import java.util.Collections;
2021

2122
import com.datastax.oss.driver.api.core.CqlIdentifier;
2223
import com.datastax.oss.driver.api.core.CqlSession;
@@ -43,6 +44,7 @@
4344
*
4445
* @author Eddú Meléndez
4546
* @author Stephane Nicoll
47+
* @author Ittay Stern
4648
*/
4749
class CassandraAutoConfigurationTests {
4850

@@ -244,6 +246,28 @@ void driverConfigLoaderWithConfigComplementSettings() {
244246
});
245247
}
246248

249+
@Test // gh-31238
250+
void driverConfigLoaderWithConfigOverridesDefaults() {
251+
String configLocation = "org/springframework/boot/autoconfigure/cassandra/override-defaults.conf";
252+
this.contextRunner.withPropertyValues("spring.data.cassandra.config=" + configLocation).run((context) -> {
253+
DriverExecutionProfile actual = context.getBean(DriverConfigLoader.class).getInitialConfig()
254+
.getDefaultProfile();
255+
assertThat(actual.getString(DefaultDriverOption.SESSION_NAME)).isEqualTo("advanced session");
256+
assertThat(actual.getDuration(DefaultDriverOption.REQUEST_TIMEOUT)).isEqualTo(Duration.ofSeconds(2));
257+
assertThat(actual.getStringList(DefaultDriverOption.CONTACT_POINTS))
258+
.isEqualTo(Collections.singletonList("1.2.3.4:5678"));
259+
assertThat(actual.getBoolean(DefaultDriverOption.RESOLVE_CONTACT_POINTS)).isFalse();
260+
assertThat(actual.getInt(DefaultDriverOption.REQUEST_PAGE_SIZE)).isEqualTo(11);
261+
assertThat(actual.getString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)).isEqualTo("datacenter1");
262+
assertThat(actual.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_CONCURRENT_REQUESTS)).isEqualTo(22);
263+
assertThat(actual.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_REQUESTS_PER_SECOND)).isEqualTo(33);
264+
assertThat(actual.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_QUEUE_SIZE)).isEqualTo(44);
265+
assertThat(actual.getDuration(DefaultDriverOption.CONTROL_CONNECTION_TIMEOUT))
266+
.isEqualTo(Duration.ofMillis(5555));
267+
assertThat(actual.getString(DefaultDriverOption.PROTOCOL_COMPRESSION)).isEqualTo("SNAPPY");
268+
});
269+
}
270+
247271
@Test
248272
void driverConfigLoaderWithConfigCreateProfiles() {
249273
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)