Skip to content

Commit ba916cb

Browse files
committed
Allow KafkaProperties to build properties with empty bundle name
Update `KafkaProperties` so that properties can still be built when the bundle name has no text. Fixes gh-43561
1 parent a5c2f0f commit ba916cb

File tree

4 files changed

+77
-42
lines changed

4 files changed

+77
-42
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/KafkaProperties.java

+45-37
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.springframework.kafka.listener.ContainerProperties.AckMode;
4444
import org.springframework.kafka.security.jaas.KafkaJaasLoginModuleInitializer;
4545
import org.springframework.util.CollectionUtils;
46+
import org.springframework.util.StringUtils;
4647
import org.springframework.util.unit.DataSize;
4748

4849
/**
@@ -1427,60 +1428,67 @@ public Map<String, Object> buildProperties() {
14271428

14281429
public Map<String, Object> buildProperties(SslBundles sslBundles) {
14291430
validate();
1430-
Properties properties = new Properties();
1431-
if (getBundle() != null) {
1432-
properties.in(SslConfigs.SSL_ENGINE_FACTORY_CLASS_CONFIG)
1433-
.accept(SslBundleSslEngineFactory.class.getName());
1434-
properties.in(SslBundle.class.getName()).accept(sslBundles.getBundle(getBundle()));
1435-
}
1436-
else {
1437-
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
1438-
map.from(this::getKeyPassword).to(properties.in(SslConfigs.SSL_KEY_PASSWORD_CONFIG));
1439-
map.from(this::getKeyStoreCertificateChain)
1440-
.to(properties.in(SslConfigs.SSL_KEYSTORE_CERTIFICATE_CHAIN_CONFIG));
1441-
map.from(this::getKeyStoreKey).to(properties.in(SslConfigs.SSL_KEYSTORE_KEY_CONFIG));
1442-
map.from(this::getKeyStoreLocation)
1443-
.as(this::resourceToPath)
1444-
.to(properties.in(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG));
1445-
map.from(this::getKeyStorePassword).to(properties.in(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG));
1446-
map.from(this::getKeyStoreType).to(properties.in(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG));
1447-
map.from(this::getTrustStoreCertificates)
1448-
.to(properties.in(SslConfigs.SSL_TRUSTSTORE_CERTIFICATES_CONFIG));
1449-
map.from(this::getTrustStoreLocation)
1450-
.as(this::resourceToPath)
1451-
.to(properties.in(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG));
1452-
map.from(this::getTrustStorePassword).to(properties.in(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG));
1453-
map.from(this::getTrustStoreType).to(properties.in(SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG));
1454-
map.from(this::getProtocol).to(properties.in(SslConfigs.SSL_PROTOCOL_CONFIG));
1431+
String bundleName = getBundle();
1432+
if (StringUtils.hasText(bundleName)) {
1433+
return buildPropertiesForSslBundle(sslBundles, bundleName);
14551434
}
1435+
Properties properties = new Properties();
1436+
PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
1437+
map.from(this::getKeyPassword).to(properties.in(SslConfigs.SSL_KEY_PASSWORD_CONFIG));
1438+
map.from(this::getKeyStoreCertificateChain)
1439+
.to(properties.in(SslConfigs.SSL_KEYSTORE_CERTIFICATE_CHAIN_CONFIG));
1440+
map.from(this::getKeyStoreKey).to(properties.in(SslConfigs.SSL_KEYSTORE_KEY_CONFIG));
1441+
map.from(this::getKeyStoreLocation)
1442+
.as(this::resourceToPath)
1443+
.to(properties.in(SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG));
1444+
map.from(this::getKeyStorePassword).to(properties.in(SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG));
1445+
map.from(this::getKeyStoreType).to(properties.in(SslConfigs.SSL_KEYSTORE_TYPE_CONFIG));
1446+
map.from(this::getTrustStoreCertificates).to(properties.in(SslConfigs.SSL_TRUSTSTORE_CERTIFICATES_CONFIG));
1447+
map.from(this::getTrustStoreLocation)
1448+
.as(this::resourceToPath)
1449+
.to(properties.in(SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG));
1450+
map.from(this::getTrustStorePassword).to(properties.in(SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG));
1451+
map.from(this::getTrustStoreType).to(properties.in(SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG));
1452+
map.from(this::getProtocol).to(properties.in(SslConfigs.SSL_PROTOCOL_CONFIG));
1453+
return properties;
1454+
}
1455+
1456+
private Map<String, Object> buildPropertiesForSslBundle(SslBundles sslBundles, String name) {
1457+
Properties properties = new Properties();
1458+
properties.in(SslConfigs.SSL_ENGINE_FACTORY_CLASS_CONFIG).accept(SslBundleSslEngineFactory.class.getName());
1459+
properties.in(SslBundle.class.getName()).accept(sslBundles.getBundle(name));
14561460
return properties;
14571461
}
14581462

14591463
private void validate() {
1460-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1464+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14611465
entries.put("spring.kafka.ssl.key-store-key", getKeyStoreKey());
14621466
entries.put("spring.kafka.ssl.key-store-location", getKeyStoreLocation());
1463-
});
1464-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1467+
}, this::hasValue);
1468+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14651469
entries.put("spring.kafka.ssl.trust-store-certificates", getTrustStoreCertificates());
14661470
entries.put("spring.kafka.ssl.trust-store-location", getTrustStoreLocation());
1467-
});
1468-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1471+
}, this::hasValue);
1472+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14691473
entries.put("spring.kafka.ssl.bundle", getBundle());
14701474
entries.put("spring.kafka.ssl.key-store-key", getKeyStoreKey());
1471-
});
1472-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1475+
}, this::hasValue);
1476+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14731477
entries.put("spring.kafka.ssl.bundle", getBundle());
14741478
entries.put("spring.kafka.ssl.key-store-location", getKeyStoreLocation());
1475-
});
1476-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1479+
}, this::hasValue);
1480+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14771481
entries.put("spring.kafka.ssl.bundle", getBundle());
14781482
entries.put("spring.kafka.ssl.trust-store-certificates", getTrustStoreCertificates());
1479-
});
1480-
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleNonNullValuesIn((entries) -> {
1483+
}, this::hasValue);
1484+
MutuallyExclusiveConfigurationPropertiesException.throwIfMultipleMatchingValuesIn((entries) -> {
14811485
entries.put("spring.kafka.ssl.bundle", getBundle());
14821486
entries.put("spring.kafka.ssl.trust-store-location", getTrustStoreLocation());
1483-
});
1487+
}, this::hasValue);
1488+
}
1489+
1490+
private boolean hasValue(Object value) {
1491+
return (value instanceof String string) ? StringUtils.hasText(string) : value != null;
14841492
}
14851493

14861494
private String resourceToPath(Resource resource) {

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/oauth2/client/ClientsConfiguredCondition.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 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.
@@ -36,7 +36,6 @@
3636
* @author Madhura Bhave
3737
* @since 2.1.0
3838
*/
39-
4039
public class ClientsConfiguredCondition extends SpringBootCondition {
4140

4241
private static final Bindable<Map<String, OAuth2ClientProperties.Registration>> STRING_REGISTRATION_MAP = Bindable

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/kafka/KafkaPropertiesTests.java

+14
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,20 @@ void sslPemConfiguration() {
8787
"-----BEGINchain");
8888
}
8989

90+
@Test
91+
void sslPemConfigurationWithEmptyBundle() {
92+
KafkaProperties properties = new KafkaProperties();
93+
properties.getSsl().setKeyStoreKey("-----BEGINkey");
94+
properties.getSsl().setTrustStoreCertificates("-----BEGINtrust");
95+
properties.getSsl().setKeyStoreCertificateChain("-----BEGINchain");
96+
properties.getSsl().setBundle("");
97+
Map<String, Object> consumerProperties = properties.buildConsumerProperties();
98+
assertThat(consumerProperties).containsEntry(SslConfigs.SSL_KEYSTORE_KEY_CONFIG, "-----BEGINkey");
99+
assertThat(consumerProperties).containsEntry(SslConfigs.SSL_TRUSTSTORE_CERTIFICATES_CONFIG, "-----BEGINtrust");
100+
assertThat(consumerProperties).containsEntry(SslConfigs.SSL_KEYSTORE_CERTIFICATE_CHAIN_CONFIG,
101+
"-----BEGINchain");
102+
}
103+
90104
@Test
91105
void sslBundleConfiguration() {
92106
KafkaProperties properties = new KafkaProperties();

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/source/MutuallyExclusiveConfigurationPropertiesException.java

+17-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 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.
@@ -20,8 +20,10 @@
2020
import java.util.LinkedHashMap;
2121
import java.util.LinkedHashSet;
2222
import java.util.Map;
23+
import java.util.Objects;
2324
import java.util.Set;
2425
import java.util.function.Consumer;
26+
import java.util.function.Predicate;
2527
import java.util.stream.Collectors;
2628

2729
import org.springframework.util.Assert;
@@ -96,11 +98,23 @@ private static String buildMessage(Set<String> mutuallyExclusiveNames, Set<Strin
9698
* @param entries a consumer used to populate the entries to check
9799
*/
98100
public static void throwIfMultipleNonNullValuesIn(Consumer<Map<String, Object>> entries) {
99-
Map<String, Object> map = new LinkedHashMap<>();
101+
throwIfMultipleMatchingValuesIn(entries, Objects::nonNull);
102+
}
103+
104+
/**
105+
* Throw a new {@link MutuallyExclusiveConfigurationPropertiesException} if multiple
106+
* values are defined in a set of entries that match the given predicate.
107+
* @param <V> the value type
108+
* @param entries a consumer used to populate the entries to check
109+
* @param predicate the predicate used to check for matching values
110+
* @since 3.3.7
111+
*/
112+
public static <V> void throwIfMultipleMatchingValuesIn(Consumer<Map<String, V>> entries, Predicate<V> predicate) {
113+
Map<String, V> map = new LinkedHashMap<>();
100114
entries.accept(map);
101115
Set<String> configuredNames = map.entrySet()
102116
.stream()
103-
.filter((entry) -> entry.getValue() != null)
117+
.filter((entry) -> predicate.test(entry.getValue()))
104118
.map(Map.Entry::getKey)
105119
.collect(Collectors.toCollection(LinkedHashSet::new));
106120
if (configuredNames.size() > 1) {

0 commit comments

Comments
 (0)