diff --git a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java index 19623076032..8e8affbd8b7 100644 --- a/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java +++ b/spring-core/src/main/java/org/springframework/core/annotation/AnnotationUtils.java @@ -1486,6 +1486,7 @@ public abstract class AnnotationUtils { * it will be cast to an {@code AnnotationConfigurationException} and thrown, * allowing it to propagate to the caller. *

Otherwise, this method does nothing. + * @param t the throwable to inspect * @since 4.2 */ static void rethrowAnnotationConfigurationException(Throwable t) { @@ -1621,6 +1622,7 @@ public abstract class AnnotationUtils { return synthesizedAnnotations; } catch (Exception ex) { + rethrowAnnotationConfigurationException(ex); // Unable to read value from repeating annotation container -> ignore it. return Collections.emptyList(); } diff --git a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java index a23c48380e3..b35f57d8ee8 100644 --- a/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/core/annotation/AnnotationUtilsTests.java @@ -504,6 +504,15 @@ public class AnnotationUtilsTests { assertThat(values, equalTo(Arrays.asList("a", "b", "c", "meta"))); } + @Test + public void getRepeatableWithMissingAttributeAliasDeclaration() throws Exception { + exception.expect(AnnotationConfigurationException.class); + exception.expectMessage(containsString("Attribute [value] in")); + exception.expectMessage(containsString(BrokenContextConfig.class.getName())); + exception.expectMessage(containsString("must be declared as an @AliasFor [locations]")); + getRepeatableAnnotation(BrokenConfigHierarchyTestCase.class, BrokenHierarchy.class, BrokenContextConfig.class); + } + @Test public void getRepeatableWithAttributeAliases() throws Exception { Set annotations = getRepeatableAnnotation(ConfigHierarchyTestCase.class, Hierarchy.class, @@ -1261,19 +1270,38 @@ public class AnnotationUtilsTests { String locations() default ""; } + @Retention(RetentionPolicy.RUNTIME) + @interface BrokenContextConfig { + + // Intentionally missing: + // @AliasFor(attribute = "locations") + String value() default ""; + + @AliasFor(attribute = "value") + String locations() default ""; + } + /** * Mock of {@code org.springframework.test.context.ContextHierarchy}. */ @Retention(RetentionPolicy.RUNTIME) @interface Hierarchy { - ContextConfig[] value(); } + @Retention(RetentionPolicy.RUNTIME) + @interface BrokenHierarchy { + BrokenContextConfig[] value(); + } + @Hierarchy({ @ContextConfig("A"), @ContextConfig(locations = "B") }) static class ConfigHierarchyTestCase { } + @BrokenHierarchy(@BrokenContextConfig) + static class BrokenConfigHierarchyTestCase { + } + @ContextConfig("simple.xml") static class SimpleConfigTestCase { }