Skip to content

Commit f145ca0

Browse files
committed
Fix reflection hint generation for properties nested in superclass
Fixes gh-36406
1 parent 9d91dbc commit f145ca0

File tree

2 files changed

+60
-1
lines changed

2 files changed

+60
-1
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrar.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,8 @@ private boolean isMap(ResolvableType type) {
317317
* @return whether the specified {@code propertyType} is a nested type
318318
*/
319319
private boolean isNestedType(String propertyName, Class<?> propertyType) {
320-
if (this.type.equals(propertyType.getDeclaringClass())) {
320+
Class<?> declaringClass = propertyType.getDeclaringClass();
321+
if (declaringClass != null && declaringClass.isAssignableFrom(this.type)) {
321322
return true;
322323
}
323324
Field field = ReflectionUtils.findField(this.type, propertyName);

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/context/properties/bind/BindableRuntimeHintsRegistrarTests.java

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.springframework.boot.context.properties.BoundConfigurationProperties;
3535
import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
3636
import org.springframework.boot.context.properties.NestedConfigurationProperty;
37+
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.BaseProperties.InheritedNested;
3738
import org.springframework.context.ApplicationContext;
3839
import org.springframework.context.ApplicationContextAware;
3940
import org.springframework.context.EnvironmentAware;
@@ -243,6 +244,21 @@ void registerHintsWhenHasPackagePrivateGettersAndSetters() {
243244
"setBravo"));
244245
}
245246

247+
@Test
248+
void registerHintsWhenHasInheritedNestedProperties() {
249+
RuntimeHints runtimeHints = registerHints(ExtendingProperties.class);
250+
assertThat(runtimeHints.reflection().typeHints()).hasSize(3);
251+
assertThat(runtimeHints.reflection().getTypeHint(BaseProperties.class)).satisfies((entry) -> {
252+
assertThat(entry.getMemberCategories()).isEmpty();
253+
assertThat(entry.methods()).extracting(ExecutableHint::getName)
254+
.containsExactlyInAnyOrder("getInheritedNested", "setInheritedNested");
255+
});
256+
assertThat(runtimeHints.reflection().getTypeHint(ExtendingProperties.class))
257+
.satisfies(javaBeanBinding(ExtendingProperties.class, "getBravo", "setBravo"));
258+
assertThat(runtimeHints.reflection().getTypeHint(InheritedNested.class))
259+
.satisfies(javaBeanBinding(InheritedNested.class, "getAlpha", "setAlpha"));
260+
}
261+
246262
private Consumer<TypeHint> javaBeanBinding(Class<?> type, String... expectedMethods) {
247263
return javaBeanBinding(type, type.getDeclaredConstructors()[0], expectedMethods);
248264
}
@@ -665,4 +681,46 @@ public void setField(String field) {
665681

666682
}
667683

684+
public abstract static class BaseProperties {
685+
686+
private InheritedNested inheritedNested;
687+
688+
public InheritedNested getInheritedNested() {
689+
return this.inheritedNested;
690+
}
691+
692+
public void setInheritedNested(InheritedNested inheritedNested) {
693+
this.inheritedNested = inheritedNested;
694+
}
695+
696+
public static class InheritedNested {
697+
698+
private String alpha;
699+
700+
public String getAlpha() {
701+
return this.alpha;
702+
}
703+
704+
public void setAlpha(String alpha) {
705+
this.alpha = alpha;
706+
}
707+
708+
}
709+
710+
}
711+
712+
public static class ExtendingProperties extends BaseProperties {
713+
714+
private String bravo;
715+
716+
public String getBravo() {
717+
return this.bravo;
718+
}
719+
720+
public void setBravo(String bravo) {
721+
this.bravo = bravo;
722+
}
723+
724+
}
725+
668726
}

0 commit comments

Comments
 (0)