Skip to content

Commit 8753789

Browse files
committed
Skip AOT processing for validation constraint with missing dependency
1 parent 5e08a88 commit 8753789

File tree

2 files changed

+43
-6
lines changed

2 files changed

+43
-6
lines changed

spring-context/src/main/java/org/springframework/validation/beanvalidation/BeanValidationBeanRegistrationAotProcessor.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-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.
@@ -124,18 +124,19 @@ private static void processAheadOfTime(Class<?> clazz, Collection<Class<?>> vali
124124
try {
125125
descriptor = validator.getConstraintsForClass(clazz);
126126
}
127-
catch (RuntimeException ex) {
127+
catch (RuntimeException | LinkageError ex) {
128+
String className = clazz.getName();
128129
if (KotlinDetector.isKotlinType(clazz) && ex instanceof ArrayIndexOutOfBoundsException) {
129130
// See https://hibernate.atlassian.net/browse/HV-1796 and https://youtrack.jetbrains.com/issue/KT-40857
130-
logger.warn("Skipping validation constraint hint inference for class " + clazz +
131+
logger.warn("Skipping validation constraint hint inference for class " + className +
131132
" due to an ArrayIndexOutOfBoundsException at validator level");
132133
}
133134
else if (ex instanceof TypeNotPresentException) {
134135
logger.debug("Skipping validation constraint hint inference for class " +
135-
clazz + " due to a TypeNotPresentException at validator level: " + ex.getMessage());
136+
className + " due to a TypeNotPresentException at validator level: " + ex.getMessage());
136137
}
137138
else {
138-
logger.warn("Skipping validation constraint hint inference for class " + clazz, ex);
139+
logger.warn("Skipping validation constraint hint inference for class " + className, ex);
139140
}
140141
return;
141142
}

spring-context/src/test/java/org/springframework/validation/beanvalidation/BeanValidationBeanRegistrationAotProcessorTests.java

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2023 the original author or authors.
2+
* Copyright 2002-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.
@@ -40,6 +40,7 @@
4040
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
4141
import org.springframework.beans.factory.support.RegisteredBean;
4242
import org.springframework.beans.factory.support.RootBeanDefinition;
43+
import org.springframework.core.OverridingClassLoader;
4344
import org.springframework.lang.Nullable;
4445

4546
import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
@@ -121,6 +122,14 @@ void shouldProcessTransitiveGenericTypeLevelConstraint() {
121122
.withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS)).accepts(this.generationContext.getRuntimeHints());
122123
}
123124

125+
@Test // gh-33940
126+
void shouldSkipConstraintWithMissingDependency() throws Exception {
127+
FilteringClassLoader classLoader = new FilteringClassLoader(getClass().getClassLoader());
128+
Class<?> beanClass = classLoader.loadClass(ConstraintWithMissingDependency.class.getName());
129+
process(beanClass);
130+
assertThat(this.generationContext.getRuntimeHints().reflection().typeHints()).isEmpty();
131+
}
132+
124133
private void process(Class<?> beanClass) {
125134
BeanRegistrationAotContribution contribution = createContribution(beanClass);
126135
if (contribution != null) {
@@ -244,4 +253,31 @@ public void setExclude(List<Exclude> exclude) {
244253
}
245254
}
246255

256+
static class ConstraintWithMissingDependency {
257+
258+
private final Filtered filtered = new Filtered();
259+
}
260+
261+
static class Filtered {}
262+
263+
static class FilteringClassLoader extends OverridingClassLoader {
264+
265+
FilteringClassLoader(ClassLoader parent) {
266+
super(parent);
267+
}
268+
269+
@Override
270+
protected boolean isEligibleForOverriding(String className) {
271+
return className.startsWith(BeanValidationBeanRegistrationAotProcessorTests.class.getName());
272+
}
273+
274+
@Override
275+
protected Class<?> loadClassForOverriding(String name) throws ClassNotFoundException {
276+
if (name.contains("Filtered")) {
277+
throw new NoClassDefFoundError(name);
278+
}
279+
return super.loadClassForOverriding(name);
280+
}
281+
}
282+
247283
}

0 commit comments

Comments
 (0)