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
This commit is contained in:
committed by
Phillip Webb
parent
7017e103f6
commit
1c7d99890e
@@ -126,7 +126,8 @@ public class CassandraAutoConfiguration {
|
||||
|
||||
private Config applyDefaultFallback(Config config) {
|
||||
ConfigFactory.invalidateCaches();
|
||||
return ConfigFactory.defaultOverrides().withFallback(config).withFallback(ConfigFactory.defaultReference())
|
||||
return ConfigFactory.defaultOverrides().withFallback(config)
|
||||
.withFallback(mapConfig(CassandraProperties.defaults())).withFallback(ConfigFactory.defaultReference())
|
||||
.resolve();
|
||||
}
|
||||
|
||||
@@ -153,9 +154,9 @@ public class CassandraAutoConfiguration {
|
||||
mapPoolingOptions(properties, options);
|
||||
mapRequestOptions(properties, options);
|
||||
mapControlConnectionOptions(properties, options);
|
||||
map.from(mapContactPoints(properties))
|
||||
map.from(mapContactPoints(properties)).whenNonNull()
|
||||
.to((contactPoints) -> options.add(DefaultDriverOption.CONTACT_POINTS, contactPoints));
|
||||
map.from(properties.getLocalDatacenter()).to(
|
||||
map.from(properties.getLocalDatacenter()).whenHasText().to(
|
||||
(localDatacenter) -> options.add(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER, localDatacenter));
|
||||
return options.build();
|
||||
}
|
||||
@@ -210,7 +211,8 @@ public class CassandraAutoConfiguration {
|
||||
}
|
||||
|
||||
private List<String> mapContactPoints(CassandraProperties properties) {
|
||||
return properties.getContactPoints().stream()
|
||||
List<String> contactPoints = properties.getContactPoints();
|
||||
return (contactPoints == null) ? null : contactPoints.stream()
|
||||
.map((candidate) -> formatContactPoint(candidate, properties.getPort())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@ import org.springframework.core.io.Resource;
|
||||
@ConfigurationProperties(prefix = "spring.data.cassandra")
|
||||
public class CassandraProperties {
|
||||
|
||||
static CassandraProperties defaults() {
|
||||
CassandraProperties properties = new CassandraProperties();
|
||||
|
||||
properties.setContactPoints(new ArrayList<>(Collections.singleton("127.0.0.1:9042")));
|
||||
properties.setCompression(Compression.NONE);
|
||||
properties.getControlconnection().setTimeout(Duration.ofSeconds(5));
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Location of the configuration file to use.
|
||||
*/
|
||||
@@ -57,7 +67,7 @@ public class CassandraProperties {
|
||||
* Cluster node addresses in the form 'host:port', or a simple 'host' to use the
|
||||
* configured port.
|
||||
*/
|
||||
private final List<String> contactPoints = new ArrayList<>(Collections.singleton("127.0.0.1:9042"));
|
||||
private List<String> contactPoints;
|
||||
|
||||
/**
|
||||
* Port to use if a contact point does not specify one.
|
||||
@@ -83,7 +93,7 @@ public class CassandraProperties {
|
||||
/**
|
||||
* Compression supported by the Cassandra binary protocol.
|
||||
*/
|
||||
private Compression compression = Compression.NONE;
|
||||
private Compression compression;
|
||||
|
||||
/**
|
||||
* Schema action to take at startup.
|
||||
@@ -143,6 +153,10 @@ public class CassandraProperties {
|
||||
return this.contactPoints;
|
||||
}
|
||||
|
||||
public void setContactPoints(List<String> contactPoints) {
|
||||
this.contactPoints = contactPoints;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
@@ -266,7 +280,7 @@ public class CassandraProperties {
|
||||
/**
|
||||
* How many rows will be retrieved simultaneously in a single network round-trip.
|
||||
*/
|
||||
private int pageSize;
|
||||
private Integer pageSize;
|
||||
|
||||
private final Throttler throttler = new Throttler();
|
||||
|
||||
@@ -294,7 +308,7 @@ public class CassandraProperties {
|
||||
this.serialConsistency = serialConsistency;
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
public Integer getPageSize() {
|
||||
return this.pageSize;
|
||||
}
|
||||
|
||||
@@ -347,7 +361,7 @@ public class CassandraProperties {
|
||||
/**
|
||||
* Timeout to use for control queries.
|
||||
*/
|
||||
private Duration timeout = Duration.ofSeconds(5);
|
||||
private Duration timeout;
|
||||
|
||||
public Duration getTimeout() {
|
||||
return this.timeout;
|
||||
@@ -370,17 +384,17 @@ public class CassandraProperties {
|
||||
* Maximum number of requests that can be enqueued when the throttling threshold
|
||||
* is exceeded.
|
||||
*/
|
||||
private int maxQueueSize;
|
||||
private Integer maxQueueSize;
|
||||
|
||||
/**
|
||||
* Maximum number of requests that are allowed to execute in parallel.
|
||||
*/
|
||||
private int maxConcurrentRequests;
|
||||
private Integer maxConcurrentRequests;
|
||||
|
||||
/**
|
||||
* Maximum allowed request rate.
|
||||
*/
|
||||
private int maxRequestsPerSecond;
|
||||
private Integer maxRequestsPerSecond;
|
||||
|
||||
/**
|
||||
* How often the throttler attempts to dequeue requests. Set this high enough that
|
||||
@@ -397,7 +411,7 @@ public class CassandraProperties {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public int getMaxQueueSize() {
|
||||
public Integer getMaxQueueSize() {
|
||||
return this.maxQueueSize;
|
||||
}
|
||||
|
||||
@@ -405,7 +419,7 @@ public class CassandraProperties {
|
||||
this.maxQueueSize = maxQueueSize;
|
||||
}
|
||||
|
||||
public int getMaxConcurrentRequests() {
|
||||
public Integer getMaxConcurrentRequests() {
|
||||
return this.maxConcurrentRequests;
|
||||
}
|
||||
|
||||
@@ -413,7 +427,7 @@ public class CassandraProperties {
|
||||
this.maxConcurrentRequests = maxConcurrentRequests;
|
||||
}
|
||||
|
||||
public int getMaxRequestsPerSecond() {
|
||||
public Integer getMaxRequestsPerSecond() {
|
||||
return this.maxRequestsPerSecond;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.springframework.boot.autoconfigure.cassandra;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlIdentifier;
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
@@ -28,6 +30,7 @@ import com.datastax.oss.driver.api.core.config.DriverExecutionProfile;
|
||||
import com.datastax.oss.driver.internal.core.session.throttling.ConcurrencyLimitingRequestThrottler;
|
||||
import com.datastax.oss.driver.internal.core.session.throttling.PassThroughRequestThrottler;
|
||||
import com.datastax.oss.driver.internal.core.session.throttling.RateLimitingRequestThrottler;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
@@ -244,6 +247,44 @@ class CassandraAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test // gh-31025
|
||||
void driverConfigLoaderWithConfigOverridesDefaults() {
|
||||
String configLocation = "org/springframework/boot/autoconfigure/cassandra/override-defaults.conf";
|
||||
this.contextRunner.withPropertyValues("spring.data.cassandra.config=" + configLocation).run((context) -> {
|
||||
assertThat(context).hasSingleBean(DriverConfigLoader.class);
|
||||
|
||||
SoftAssertions softly = new SoftAssertions();
|
||||
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getString(DefaultDriverOption.SESSION_NAME)).isEqualTo("advanced session");
|
||||
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getDuration(DefaultDriverOption.REQUEST_TIMEOUT)).isEqualTo(Duration.ofSeconds(2)); // default
|
||||
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getStringList(DefaultDriverOption.CONTACT_POINTS)).isEqualTo(Collections.singletonList("1.2.3.4:5678"));
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getBoolean(DefaultDriverOption.RESOLVE_CONTACT_POINTS)).isFalse();
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getInt(DefaultDriverOption.REQUEST_PAGE_SIZE)).isEqualTo(11);
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getString(DefaultDriverOption.LOAD_BALANCING_LOCAL_DATACENTER)).isEqualTo("datacenter1");
|
||||
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_CONCURRENT_REQUESTS)).isEqualTo(22);
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_REQUESTS_PER_SECOND)).isEqualTo(33);
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getInt(DefaultDriverOption.REQUEST_THROTTLER_MAX_QUEUE_SIZE)).isEqualTo(44);
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getDuration(DefaultDriverOption.CONTROL_CONNECTION_TIMEOUT)).isEqualTo(Duration.ofMillis(5555));
|
||||
softly.assertThat(context.getBean(DriverConfigLoader.class).getInitialConfig().getDefaultProfile()
|
||||
.getString(DefaultDriverOption.PROTOCOL_COMPRESSION)).isEqualTo("SNAPPY");
|
||||
|
||||
softly.assertAll();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void driverConfigLoaderWithConfigCreateProfiles() {
|
||||
String configLocation = "org/springframework/boot/autoconfigure/cassandra/profiles.conf";
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
datastax-java-driver {
|
||||
basic {
|
||||
session-name = advanced session
|
||||
load-balancing-policy {
|
||||
local-datacenter = datacenter1
|
||||
}
|
||||
request.page-size = 11
|
||||
contact-points = [ "1.2.3.4:5678" ]
|
||||
}
|
||||
advanced {
|
||||
throttler {
|
||||
max-concurrent-requests = 22
|
||||
max-requests-per-second = 33
|
||||
max-queue-size = 44
|
||||
}
|
||||
control-connection.timeout = 5555
|
||||
protocol.compression = SNAPPY
|
||||
resolve-contact-points = false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user