Skip to content

Commit b50b0e8

Browse files
committed
Remove detection of missing parameter information
There are some cases where false positives of the detection prevent compiling an application to native which otherwise would run perfectly fine in a native image. Closes gh-40051
1 parent 3e5d6c9 commit b50b0e8

File tree

3 files changed

+20
-80
lines changed

3 files changed

+20
-80
lines changed

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

+6-37
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,7 @@
3939
import org.springframework.boot.context.properties.bind.JavaBeanBinder.BeanProperties;
4040
import org.springframework.boot.context.properties.bind.JavaBeanBinder.BeanProperty;
4141
import org.springframework.core.KotlinDetector;
42-
import org.springframework.core.KotlinReflectionParameterNameDiscoverer;
43-
import org.springframework.core.ParameterNameDiscoverer;
44-
import org.springframework.core.PrioritizedParameterNameDiscoverer;
4542
import org.springframework.core.ResolvableType;
46-
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
4743
import org.springframework.core.annotation.MergedAnnotations;
4844
import org.springframework.util.Assert;
4945
import org.springframework.util.ReflectionUtils;
@@ -92,12 +88,8 @@ public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
9288
* @param hints the hints contributed so far for the deployment unit
9389
*/
9490
public void registerHints(RuntimeHints hints) {
95-
Set<Class<?>> compiledWithoutParameters = new HashSet<>();
9691
for (Bindable<?> bindable : this.bindables) {
97-
new Processor(bindable, compiledWithoutParameters).process(hints.reflection());
98-
}
99-
if (!compiledWithoutParameters.isEmpty()) {
100-
throw new MissingParametersCompilerArgumentException(compiledWithoutParameters);
92+
new Processor(bindable).process(hints.reflection());
10193
}
10294
}
10395

@@ -144,18 +136,7 @@ public static BindableRuntimeHintsRegistrar forBindables(Bindable<?>... bindable
144136
/**
145137
* Processor used to register the hints.
146138
*/
147-
private final class Processor {
148-
149-
private static final ParameterNameDiscoverer parameterNameDiscoverer;
150-
151-
static {
152-
PrioritizedParameterNameDiscoverer discoverer = new PrioritizedParameterNameDiscoverer();
153-
if (KotlinDetector.isKotlinReflectPresent()) {
154-
discoverer.addDiscoverer(new KotlinReflectionParameterNameDiscoverer());
155-
}
156-
discoverer.addDiscoverer(new StandardReflectionParameterNameDiscoverer());
157-
parameterNameDiscoverer = discoverer;
158-
}
139+
private static final class Processor {
159140

160141
private final Class<?> type;
161142

@@ -165,21 +146,17 @@ private final class Processor {
165146

166147
private final Set<Class<?>> seen;
167148

168-
private final Set<Class<?>> compiledWithoutParameters;
169-
170-
Processor(Bindable<?> bindable, Set<Class<?>> compiledWithoutParameters) {
171-
this(bindable, false, new HashSet<>(), compiledWithoutParameters);
149+
Processor(Bindable<?> bindable) {
150+
this(bindable, false, new HashSet<>());
172151
}
173152

174-
private Processor(Bindable<?> bindable, boolean nestedType, Set<Class<?>> seen,
175-
Set<Class<?>> compiledWithoutParameters) {
153+
private Processor(Bindable<?> bindable, boolean nestedType, Set<Class<?>> seen) {
176154
this.type = bindable.getType().getRawClass();
177155
this.bindConstructor = (bindable.getBindMethod() != BindMethod.JAVA_BEAN)
178156
? BindConstructorProvider.DEFAULT.getBindConstructor(bindable.getType().resolve(), nestedType)
179157
: null;
180158
this.bean = JavaBeanBinder.BeanProperties.of(bindable);
181159
this.seen = seen;
182-
this.compiledWithoutParameters = compiledWithoutParameters;
183160
}
184161

185162
void process(ReflectionHints hints) {
@@ -198,7 +175,6 @@ else if (this.bean != null && !this.bean.getProperties().isEmpty()) {
198175

199176
private void handleConstructor(ReflectionHints hints) {
200177
if (this.bindConstructor != null) {
201-
verifyParameterNamesAreAvailable();
202178
if (KotlinDetector.isKotlinType(this.bindConstructor.getDeclaringClass())) {
203179
KotlinDelegate.handleConstructor(hints, this.bindConstructor);
204180
}
@@ -213,13 +189,6 @@ private void handleConstructor(ReflectionHints hints) {
213189
.ifPresent((constructor) -> hints.registerConstructor(constructor, ExecutableMode.INVOKE));
214190
}
215191

216-
private void verifyParameterNamesAreAvailable() {
217-
String[] parameterNames = parameterNameDiscoverer.getParameterNames(this.bindConstructor);
218-
if (parameterNames == null) {
219-
this.compiledWithoutParameters.add(this.bindConstructor.getDeclaringClass());
220-
}
221-
}
222-
223192
private boolean hasNoParameters(Constructor<?> candidate) {
224193
return candidate.getParameterCount() == 0;
225194
}
@@ -268,7 +237,7 @@ else if (isNestedType(propertyName, propertyClass)) {
268237
}
269238

270239
private void processNested(Class<?> type, ReflectionHints hints) {
271-
new Processor(Bindable.of(type), true, this.seen, this.compiledWithoutParameters).process(hints);
240+
new Processor(Bindable.of(type), true, this.seen).process(hints);
272241
}
273242

274243
private Class<?> getComponentClass(ResolvableType type) {

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

-42
This file was deleted.

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

+14-1
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.
@@ -24,6 +24,7 @@
2424
import java.util.Map;
2525
import java.util.function.Consumer;
2626

27+
import org.apache.tomcat.jdbc.pool.PoolProperties;
2728
import org.junit.jupiter.api.Test;
2829

2930
import org.springframework.aot.hint.ExecutableHint;
@@ -41,9 +42,11 @@
4142
import org.springframework.context.ApplicationContext;
4243
import org.springframework.context.ApplicationContextAware;
4344
import org.springframework.context.EnvironmentAware;
45+
import org.springframework.core.StandardReflectionParameterNameDiscoverer;
4446
import org.springframework.core.env.Environment;
4547

4648
import static org.assertj.core.api.Assertions.assertThat;
49+
import static org.assertj.core.api.Assertions.assertThatNoException;
4750

4851
/**
4952
* Tests for {@link BindableRuntimeHintsRegistrar}.
@@ -279,6 +282,16 @@ void registerHintsWhenHasComplexNestedProperties() {
279282
.satisfies(javaBeanBinding(ComplexNestedProperties.class, "getSimple"));
280283
}
281284

285+
@Test
286+
void registerHintsDoesNotThrowWhenParameterInformationForConstructorBindingIsNotAvailable()
287+
throws NoSuchMethodException, SecurityException {
288+
Constructor<?> constructor = PoolProperties.InterceptorProperty.class.getConstructor(String.class,
289+
String.class);
290+
String[] parameterNames = new StandardReflectionParameterNameDiscoverer().getParameterNames(constructor);
291+
assertThat(parameterNames).isNull();
292+
assertThatNoException().isThrownBy(() -> registerHints(PoolProperties.class));
293+
}
294+
282295
private Consumer<TypeHint> javaBeanBinding(Class<?> type, String... expectedMethods) {
283296
return javaBeanBinding(type, type.getDeclaredConstructors()[0], expectedMethods);
284297
}

0 commit comments

Comments
 (0)