Skip to content

Commit d9f441d

Browse files
nosanwilkinsona
authored andcommitted
Update SpringBootJoranConfigurator to use proper GraalVM format
Before this commit, the generated name for the inner class had the wrong format <package>.<parent>.<child> (canonical name). GraalVM expects $ to separate the parent from the inner class. This commit updates SpringBootJoranConfigurator to generate an appropriate format for a class name. Specifically, an inner class should be separated by a dollar sign, not a dot. See gh-44021 Signed-off-by: Dmytro Nosan <dimanosan@gmail.com>
1 parent 7f9b4c6 commit d9f441d

File tree

2 files changed

+69
-29
lines changed

2 files changed

+69
-29
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/SpringBootJoranConfigurator.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2024 the original author or authors.
2+
* Copyright 2012-2025 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.
@@ -222,12 +222,12 @@ private Set<Class<? extends Serializable>> serializationTypes(Model model) {
222222
return modelClasses;
223223
}
224224

225-
private Set<String> reflectionTypes(Model model) {
225+
private Set<Class<?>> reflectionTypes(Model model) {
226226
return reflectionTypes(model, () -> null);
227227
}
228228

229-
private Set<String> reflectionTypes(Model model, Supplier<Object> parent) {
230-
Set<String> reflectionTypes = new HashSet<>();
229+
private Set<Class<?>> reflectionTypes(Model model, Supplier<Object> parent) {
230+
Set<Class<?>> reflectionTypes = new HashSet<>();
231231
Class<?> componentType = determineType(model, parent);
232232
if (componentType != null) {
233233
processComponent(componentType, reflectionTypes);
@@ -297,23 +297,22 @@ private Object instantiate(Class<?> type) {
297297
}
298298
}
299299

300-
private void processComponent(Class<?> componentType, Set<String> reflectionTypes) {
300+
private void processComponent(Class<?> componentType, Set<Class<?>> reflectionTypes) {
301301
BeanDescription beanDescription = this.modelInterpretationContext.getBeanDescriptionCache()
302302
.getBeanDescription(componentType);
303303
reflectionTypes.addAll(parameterTypesNames(beanDescription.getPropertyNameToAdder().values()));
304304
reflectionTypes.addAll(parameterTypesNames(beanDescription.getPropertyNameToSetter().values()));
305-
reflectionTypes.add(componentType.getCanonicalName());
305+
reflectionTypes.add(componentType);
306306
}
307307

308-
private Collection<String> parameterTypesNames(Collection<Method> methods) {
308+
private Collection<Class<?>> parameterTypesNames(Collection<Method> methods) {
309309
return methods.stream()
310310
.filter((method) -> !method.getDeclaringClass().equals(ContextAware.class)
311311
&& !method.getDeclaringClass().equals(ContextAwareBase.class))
312312
.map(Method::getParameterTypes)
313313
.flatMap(Stream::of)
314314
.filter((type) -> !type.isPrimitive() && !type.equals(String.class))
315315
.map((type) -> type.isArray() ? type.getComponentType() : type)
316-
.map(Class::getName)
317316
.toList();
318317
}
319318

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackConfigurationAotContributionTests.java

+62-21
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-2025 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.
@@ -53,6 +53,7 @@
5353
import org.springframework.aot.hint.MemberCategory;
5454
import org.springframework.aot.hint.RuntimeHints;
5555
import org.springframework.aot.hint.SerializationHints;
56+
import org.springframework.aot.hint.TypeHint;
5657
import org.springframework.aot.hint.TypeReference;
5758
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
5859
import org.springframework.aot.test.generate.TestGenerationContext;
@@ -115,15 +116,18 @@ void componentModelClassAndSetterParametersAreRegisteredForReflection() {
115116
Model model = new Model();
116117
model.getSubModels().add(component);
117118
TestGenerationContext generationContext = applyContribution(model);
119+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
118120
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(SizeAndTimeBasedRollingPolicy.class))
119-
.accepts(generationContext.getRuntimeHints());
121+
.accepts(runtimeHints);
120122
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(FileAppender.class))
121-
.accepts(generationContext.getRuntimeHints());
122-
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(FileSize.class))
123-
.accepts(generationContext.getRuntimeHints());
123+
.accepts(runtimeHints);
124+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(FileSize.class)).accepts(runtimeHints);
124125
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(
125126
TimeBasedFileNamingAndTriggeringPolicy.class))
126-
.accepts(generationContext.getRuntimeHints());
127+
.accepts(runtimeHints);
128+
assertThat(runtimeHints).satisfies(hasValidTypeName(SizeAndTimeBasedRollingPolicy.class));
129+
assertThat(runtimeHints).satisfies(hasValidTypeName(FileSize.class));
130+
assertThat(runtimeHints).satisfies(hasValidTypeName(FileAppender.class));
127131
}
128132

129133
@Test
@@ -133,12 +137,14 @@ void implicitModelClassAndSetterParametersAreRegisteredForReflection() {
133137
Model model = new Model();
134138
model.getSubModels().add(implicit);
135139
TestGenerationContext generationContext = applyContribution(model);
140+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
136141
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(PatternLayoutEncoder.class))
137-
.accepts(generationContext.getRuntimeHints());
138-
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Layout.class))
139-
.accepts(generationContext.getRuntimeHints());
140-
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Charset.class))
141-
.accepts(generationContext.getRuntimeHints());
142+
.accepts(runtimeHints);
143+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Layout.class)).accepts(runtimeHints);
144+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Charset.class)).accepts(runtimeHints);
145+
assertThat(runtimeHints).satisfies(hasValidTypeName(PatternLayoutEncoder.class));
146+
assertThat(runtimeHints).satisfies(hasValidTypeName(Layout.class));
147+
assertThat(runtimeHints).satisfies(hasValidTypeName(Charset.class));
142148
}
143149

144150
@Test
@@ -152,6 +158,8 @@ void componentModelReferencingImportedClassNameIsRegisteredForReflection() {
152158
TestGenerationContext generationContext = applyContribution(model);
153159
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(SizeAndTimeBasedRollingPolicy.class))
154160
.accepts(generationContext.getRuntimeHints());
161+
assertThat(generationContext.getRuntimeHints())
162+
.satisfies(hasValidTypeName(SizeAndTimeBasedRollingPolicy.class));
155163
}
156164

157165
@Test
@@ -162,10 +170,12 @@ void typeFromParentsSetterIsRegisteredForReflection() {
162170
component.setClassName(Outer.class.getName());
163171
component.getSubModels().add(implementation);
164172
TestGenerationContext generationContext = applyContribution(component);
165-
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Outer.class))
166-
.accepts(generationContext.getRuntimeHints());
173+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
174+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Outer.class)).accepts(runtimeHints);
167175
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Implementation.class))
168-
.accepts(generationContext.getRuntimeHints());
176+
.accepts(runtimeHints);
177+
assertThat(runtimeHints).satisfies(hasValidTypeName(Outer.class));
178+
assertThat(runtimeHints).satisfies(hasValidTypeName(Implementation.class));
169179
}
170180

171181
@Test
@@ -176,19 +186,28 @@ void typeFromParentsDefaultClassAnnotatedSetterIsRegisteredForReflection() {
176186
component.setClassName(OuterWithDefaultClass.class.getName());
177187
component.getSubModels().add(contract);
178188
TestGenerationContext generationContext = applyContribution(component);
189+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
179190
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(OuterWithDefaultClass.class))
180-
.accepts(generationContext.getRuntimeHints());
191+
.accepts(runtimeHints);
181192
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Implementation.class))
182-
.accepts(generationContext.getRuntimeHints());
193+
.accepts(runtimeHints);
194+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(BaseImplementation.Details.class))
195+
.accepts(runtimeHints);
196+
assertThat(runtimeHints).satisfies(hasValidTypeName(OuterWithDefaultClass.class));
197+
assertThat(runtimeHints).satisfies(hasValidTypeName(Implementation.class));
198+
assertThat(runtimeHints).satisfies(hasValidTypeName(BaseImplementation.Details.class));
183199
}
184200

185201
@Test
186202
void componentTypesOfArraysAreRegisteredForReflection() {
187203
ComponentModel component = new ComponentModel();
188204
component.setClassName(ArrayParameters.class.getName());
189205
TestGenerationContext generationContext = applyContribution(component);
206+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
190207
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(InetSocketAddress.class))
191-
.accepts(generationContext.getRuntimeHints());
208+
.accepts(runtimeHints);
209+
assertThat(runtimeHints).satisfies(hasValidTypeName(InetSocketAddress.class));
210+
assertThat(runtimeHints).satisfies(hasValidTypeName(ArrayParameters.class));
192211
}
193212

194213
@Test
@@ -197,10 +216,12 @@ void placeholdersInComponentClassAttributeAreReplaced() {
197216
component.setClassName("${VARIABLE_CLASS_NAME}");
198217
TestGenerationContext generationContext = applyContribution(component,
199218
(context) -> context.putProperty("VARIABLE_CLASS_NAME", Outer.class.getName()));
200-
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Outer.class))
201-
.accepts(generationContext.getRuntimeHints());
219+
RuntimeHints runtimeHints = generationContext.getRuntimeHints();
220+
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Outer.class)).accepts(runtimeHints);
202221
assertThat(invokePublicConstructorsAndInspectAndInvokePublicMethodsOf(Implementation.class))
203-
.accepts(generationContext.getRuntimeHints());
222+
.accepts(runtimeHints);
223+
assertThat(runtimeHints).satisfies(hasValidTypeName(Outer.class));
224+
assertThat(runtimeHints).satisfies(hasValidTypeName(Implementation.class));
204225
}
205226

206227
private Predicate<RuntimeHints> invokePublicConstructorsOf(String name) {
@@ -216,6 +237,12 @@ private Predicate<RuntimeHints> invokePublicConstructorsAndInspectAndInvokePubli
216237
MemberCategory.INVOKE_PUBLIC_METHODS);
217238
}
218239

240+
private Consumer<RuntimeHints> hasValidTypeName(Class<?> type) {
241+
return (runtimeHints) -> assertThat(runtimeHints.reflection().getTypeHint(type)).extracting(TypeHint::getType)
242+
.extracting(TypeReference::getName)
243+
.isEqualTo(type.getName());
244+
}
245+
219246
private Properties load(InputStreamSource source) {
220247
try (InputStream inputStream = source.getInputStream()) {
221248
Properties properties = new Properties();
@@ -279,7 +306,21 @@ public void setContract(Contract contract) {
279306

280307
}
281308

282-
public static class Implementation implements Contract {
309+
public static class BaseImplementation implements Contract {
310+
311+
private Details details;
312+
313+
public void setDetails(Details details) {
314+
this.details = details;
315+
}
316+
317+
public static final class Details {
318+
319+
}
320+
321+
}
322+
323+
public static class Implementation extends BaseImplementation {
283324

284325
}
285326

0 commit comments

Comments
 (0)