Overview
This came up in the context of Spring Native, when the exception below was thrown.
TypeAccess
is an enum used in the org.springframework.nativex.hint.TypeHint
annotation.
@TypeHint
is declared in the user code but is not present on the classpath at runtime.
java.lang.IllegalArgumentException: Could not find class [org.springframework.nativex.hint.TypeAccess]
at org.springframework.util.ClassUtils.resolveClassName(ClassUtils.java:334)
at org.springframework.core.type.classreading.MergedAnnotationReadingVisitor.visitEnum(MergedAnnotationReadingVisitor.java:103)
at org.springframework.core.type.classreading.MergedAnnotationReadingVisitor$ArrayVisitor.visitEnum(MergedAnnotationReadingVisitor.java:169)
at org.springframework.asm.ClassReader.readElementValue(ClassReader.java:3081)
at org.springframework.asm.ClassReader.readElementValues(ClassReader.java:3006)
at org.springframework.asm.ClassReader.readElementValue(ClassReader.java:3180)
at org.springframework.asm.ClassReader.readElementValues(ClassReader.java:3000)
at org.springframework.asm.ClassReader.accept(ClassReader.java:610)
at org.springframework.asm.ClassReader.accept(ClassReader.java:426)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
at org.springframework.core.type.classreading.CachingMetadataReaderFactory.getMetadataReader(CachingMetadataReaderFactory.java:132)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.addCandidateComponentsFromIndex(ClassPathScanningCandidateComponentProvider.java:387)
at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:313)
at org.springframework.boot.test.context.AnnotatedClassFinder.scanPackage(AnnotatedClassFinder.java:90)
at org.springframework.boot.test.context.AnnotatedClassFinder.findFromPackage(AnnotatedClassFinder.java:82)
at org.springframework.boot.test.context.AnnotatedClassFinder.findFromClass(AnnotatedClassFinder.java:68)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.getOrFindConfigurationClasses(SpringBootTestContextBootstrapper.java:235)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.processMergedContextConfiguration(SpringBootTestContextBootstrapper.java:152)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:392)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildDefaultMergedContextConfiguration(AbstractTestContextBootstrapper.java:309)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildMergedContextConfiguration(AbstractTestContextBootstrapper.java:262)
at org.springframework.test.context.support.AbstractTestContextBootstrapper.buildTestContext(AbstractTestContextBootstrapper.java:107)
at org.springframework.boot.test.context.SpringBootTestContextBootstrapper.buildTestContext(SpringBootTestContextBootstrapper.java:102)
at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:137)
at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:122)
Proposal
Introduce try-catch blocks in MergedAnnotationReadingVisitor
's visitEnum(String, String, Consumer<E>)
and visitAnnotation(String, Consumer<MergedAnnotation<T>>)
methods, and ignore types that cannot be loaded via ClassUtils.resolveClassName(...)
.
Comment From: sbrannen
This is potentially a regression introduced when MergedAnnotation
support was introduced.
Comment From: viktorardelean
@sbrannen I would like to work on this issue.
Besides catching java.lang.IllegalArgumentException in visitEnum(String, String, Consumer
Should I add some specific logging in the catch block?
Comment From: sbrannen
Hi @viktorardelean,
Thanks for offering to help. Much appreciated!
However, I actually meant to assign this one to myself (which I've now done), since I will work on the fix and determine if it's a regression that needs to be backported.
Comment From: sbrannen
Prior to the introduction of the MergedAnnotation
API in Spring Framework 5.2, the ASM-based metadata readers caught exceptions while attempting to load a visited annotation type or visited enum type (or enum value).
https://github.com/spring-projects/spring-framework/blob/5.1.x/spring-core/src/main/java/org/springframework/core/type/classreading/AnnotationAttributesReadingVisitor.java
https://github.com/spring-projects/spring-framework/blob/dafd904b14edb1a450e69411074b335e1e5cb47a/spring-core/src/main/java/org/springframework/core/type/classreading/AbstractRecursiveAnnotationVisitor.java#L83-L100
In light of that, I am labeling this as a regression for backporting to 5.2.x.
Comment From: sbrannen
Update: the status quo for Spring Framework 5.1.x has been tested in https://github.com/spring-projects/spring-framework/commit/8de2a9b74dbcdc98f00074d1a0e4456b32e5bc63.
Comment From: sbrannen
Since this issue has not surfaced again since it was first encountered in a Spring Native sample application, we are closing this issue.
If necessary, this issue can be reassessed at a later date.