Restore previous source in Context.withSource calls
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Build and Deploy Snapshot / Build and Deploy Snapshot (push) Waiting to run
Details
Build and Deploy Snapshot / Trigger Docs Build (push) Blocked by required conditions
Details
Build and Deploy Snapshot / Verify (push) Blocked by required conditions
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:17], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:false version:21], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:${{ vars.UBUNTU_MEDIUM || 'ubuntu-latest' }} name:Linux]) (push) Waiting to run
Details
CI / ${{ matrix.os.name}} | Java ${{ matrix.java.version}} (map[toolchain:true version:24], map[id:windows-latest name:Windows]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:false version:17]) (push) Waiting to run
Details
Run System Tests / Java ${{ matrix.java.version}} (map[toolchain:true version:21]) (push) Waiting to run
Details
Fix `Context.withSource` is the `Binder` to ensure that the previous source is restored once the callback has completed. This update is especially important in Spring Boot 3.5+ since indexed binding calls `withSource` multiple times. Fixes gh-46039
This commit is contained in:
parent
05906cc047
commit
cb9cf45b7f
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -567,6 +567,7 @@ public class Binder {
|
|||
if (source == null) {
|
||||
return supplier.get();
|
||||
}
|
||||
ConfigurationPropertySource previous = this.source.get(0);
|
||||
this.source.set(0, source);
|
||||
this.sourcePushCount++;
|
||||
try {
|
||||
|
@ -574,6 +575,7 @@ public class Binder {
|
|||
}
|
||||
finally {
|
||||
this.sourcePushCount--;
|
||||
this.source.set(0, previous);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -123,6 +123,41 @@ class CollectionBinderTests {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToCollectionWhenNonKnownIndexedChildNotBoundThrowsException() {
|
||||
// gh-45994
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("foo[0].first", "Spring");
|
||||
source.put("foo[0].last", "Boot");
|
||||
source.put("foo[1].missing", "bad");
|
||||
this.sources.add(source);
|
||||
assertThatExceptionOfType(BindException.class)
|
||||
.isThrownBy(() -> this.binder.bind("foo", Bindable.listOf(Name.class)))
|
||||
.satisfies((ex) -> {
|
||||
Set<ConfigurationProperty> unbound = ((UnboundConfigurationPropertiesException) ex.getCause())
|
||||
.getUnboundProperties();
|
||||
assertThat(unbound).hasSize(1);
|
||||
ConfigurationProperty property = unbound.iterator().next();
|
||||
assertThat(property.getName()).hasToString("foo[1].missing");
|
||||
assertThat(property.getValue()).isEqualTo("bad");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToNestedCollectionWhenNonKnownIndexed() {
|
||||
// gh-46039
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
source.put("foo[0].items[0]", "a");
|
||||
source.put("foo[0].items[1]", "b");
|
||||
source.put("foo[0].string", "test");
|
||||
this.sources.add(source);
|
||||
List<ExampleCollectionBean> list = this.binder.bind("foo", Bindable.listOf(ExampleCollectionBean.class)).get();
|
||||
assertThat(list).hasSize(1);
|
||||
ExampleCollectionBean bean = list.get(0);
|
||||
assertThat(bean.getItems()).containsExactly("a", "b", "d");
|
||||
assertThat(bean.getString()).isEqualTo("test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void bindToNonScalarCollectionWhenNonSequentialShouldThrowException() {
|
||||
MockConfigurationPropertySource source = new MockConfigurationPropertySource();
|
||||
|
@ -436,6 +471,8 @@ class CollectionBinderTests {
|
|||
|
||||
private Set<String> itemsSet = new LinkedHashSet<>();
|
||||
|
||||
private String string;
|
||||
|
||||
List<String> getItems() {
|
||||
return this.items;
|
||||
}
|
||||
|
@ -452,6 +489,14 @@ class CollectionBinderTests {
|
|||
this.itemsSet = itemsSet;
|
||||
}
|
||||
|
||||
String getString() {
|
||||
return this.string;
|
||||
}
|
||||
|
||||
void setString(String string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ExampleCustomNoDefaultConstructorBean {
|
||||
|
@ -562,4 +607,8 @@ class CollectionBinderTests {
|
|||
|
||||
}
|
||||
|
||||
record Name(String first, String last) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue