Merge branch '3.0.x' into 3.1.x

Closes gh-37022
3.1.x
Stephane Nicoll 1 year ago
commit 958f92495d

@ -318,13 +318,20 @@ public class BindableRuntimeHintsRegistrar implements RuntimeHintsRegistrar {
*/ */
private boolean isNestedType(String propertyName, Class<?> propertyType) { private boolean isNestedType(String propertyName, Class<?> propertyType) {
Class<?> declaringClass = propertyType.getDeclaringClass(); Class<?> declaringClass = propertyType.getDeclaringClass();
if (declaringClass != null && declaringClass.isAssignableFrom(this.type)) { if (declaringClass != null && isNested(declaringClass, this.type)) {
return true; return true;
} }
Field field = ReflectionUtils.findField(this.type, propertyName); Field field = ReflectionUtils.findField(this.type, propertyName);
return (field != null) && MergedAnnotations.from(field).isPresent(Nested.class); return (field != null) && MergedAnnotations.from(field).isPresent(Nested.class);
} }
private static boolean isNested(Class<?> type, Class<?> candidate) {
if (type.isAssignableFrom(candidate)) {
return true;
}
return (candidate.getDeclaringClass() != null && isNested(type, candidate.getDeclaringClass()));
}
private boolean isJavaType(Class<?> candidate) { private boolean isJavaType(Class<?> candidate) {
return candidate.getPackageName().startsWith("java."); return candidate.getPackageName().startsWith("java.");
} }

@ -35,6 +35,9 @@ import org.springframework.boot.context.properties.BoundConfigurationProperties;
import org.springframework.boot.context.properties.ConfigurationPropertiesBean; import org.springframework.boot.context.properties.ConfigurationPropertiesBean;
import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.BaseProperties.InheritedNested; import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.BaseProperties.InheritedNested;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.ComplexNestedProperties.ListenerRetry;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.ComplexNestedProperties.Retry;
import org.springframework.boot.context.properties.bind.BindableRuntimeHintsRegistrarTests.ComplexNestedProperties.Simple;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationContextAware;
import org.springframework.context.EnvironmentAware; import org.springframework.context.EnvironmentAware;
@ -259,6 +262,23 @@ class BindableRuntimeHintsRegistrarTests {
.satisfies(javaBeanBinding(InheritedNested.class, "getAlpha", "setAlpha")); .satisfies(javaBeanBinding(InheritedNested.class, "getAlpha", "setAlpha"));
} }
@Test
void registerHintsWhenHasComplexNestedProperties() {
RuntimeHints runtimeHints = registerHints(ComplexNestedProperties.class);
assertThat(runtimeHints.reflection().typeHints()).hasSize(4);
assertThat(runtimeHints.reflection().getTypeHint(Retry.class)).satisfies((entry) -> {
assertThat(entry.getMemberCategories()).isEmpty();
assertThat(entry.methods()).extracting(ExecutableHint::getName)
.containsExactlyInAnyOrder("getCount", "setCount");
});
assertThat(runtimeHints.reflection().getTypeHint(ListenerRetry.class))
.satisfies(javaBeanBinding(ListenerRetry.class, "isStateless", "setStateless"));
assertThat(runtimeHints.reflection().getTypeHint(Simple.class))
.satisfies(javaBeanBinding(Simple.class, "getRetry"));
assertThat(runtimeHints.reflection().getTypeHint(ComplexNestedProperties.class))
.satisfies(javaBeanBinding(ComplexNestedProperties.class, "getSimple"));
}
private Consumer<TypeHint> javaBeanBinding(Class<?> type, String... expectedMethods) { private Consumer<TypeHint> javaBeanBinding(Class<?> type, String... expectedMethods) {
return javaBeanBinding(type, type.getDeclaredConstructors()[0], expectedMethods); return javaBeanBinding(type, type.getDeclaredConstructors()[0], expectedMethods);
} }
@ -723,4 +743,52 @@ class BindableRuntimeHintsRegistrarTests {
} }
public static class ComplexNestedProperties {
private final Simple simple = new Simple();
public Simple getSimple() {
return this.simple;
}
public static class Simple {
private final ListenerRetry retry = new ListenerRetry();
public ListenerRetry getRetry() {
return this.retry;
}
}
public abstract static class Retry {
private int count = 5;
public int getCount() {
return this.count;
}
public void setCount(int count) {
this.count = count;
}
}
public static class ListenerRetry extends Retry {
private boolean stateless;
public boolean isStateless() {
return this.stateless;
}
public void setStateless(boolean stateless) {
this.stateless = stateless;
}
}
}
} }

Loading…
Cancel
Save