From 34b691560742f2bbba1cba7066d3892b0a2e4175 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 28 Apr 2016 14:00:42 +0100 Subject: [PATCH] Consider meta-annotations when creating an AnnotationsPropertySource Previously, meta-annotations were not considered when looking for annotations that may have property mappings but were considered when looking for a `@PropertyMapping` annotation. This led to three problems: 1. Properties that should have been included in the property source were not included 2. Properties that were included may have had the wrong name 3. Properties were included when they should not have been `@DataJpaTests` provided a concrete example of all three problems: 1. The `replace` and `connection` attributes from `@AutoConfigureTestDatabase` were not included in the property source 2. The `showSql` attribute from `@DataJpaTest` was mapped as `spring.test.database.spring.jpa.show-sql` 3. The `useDefaultFilters` attribute from `@DataJpaTest` was included in the property source. This commit updates AnnotationsPropertySource to consider meta-annotations when looking for attributes that should be mapped. This addresses the first problem. Furthermore, AnnotationsPropertySource has been updated to no longer consider meta-annotations when looking for a type-level property mapping. This addresses the second and third problems. Closes gh-5794 --- .../properties/AnnotationsPropertySource.java | 9 ++-- .../AnnotationsPropertySourceTests.java | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java index cc9e8ac7a2..86d6c7617e 100644 --- a/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java +++ b/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySource.java @@ -35,6 +35,7 @@ import org.springframework.util.StringUtils; * {@link PropertyMapping @PropertyMapping}. * * @author Phillip Webb + * @author Andy Wilkinson * @since 1.4.0 */ public class AnnotationsPropertySource extends EnumerablePropertySource> { @@ -60,14 +61,16 @@ public class AnnotationsPropertySource extends EnumerablePropertySource private void collectProperties(Class source, Map properties) { if (source != null) { - for (Annotation annotation : source.getDeclaredAnnotations()) { + for (Annotation annotation : AnnotationUtils.getAnnotations(source)) { if (!AnnotationUtils.isInJavaLangAnnotationPackage(annotation)) { - PropertyMapping typeMapping = AnnotationUtils.getAnnotation( - annotation.annotationType(), PropertyMapping.class); + annotation.annotationType().getAnnotation(PropertyMapping.class); + PropertyMapping typeMapping = annotation.annotationType() + .getAnnotation(PropertyMapping.class); for (Method attribute : annotation.annotationType() .getDeclaredMethods()) { collectProperties(annotation, attribute, typeMapping, properties); } + collectProperties(annotation.annotationType(), properties); } } collectProperties(source.getSuperclass(), properties); diff --git a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java index bec497f5c3..3d6cd38137 100644 --- a/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java +++ b/spring-boot-test-autoconfigure/src/test/java/org/springframework/boot/test/autoconfigure/properties/AnnotationsPropertySourceTests.java @@ -29,6 +29,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Tests for {@link AnnotationsPropertySource}. * * @author Phillip Webb + * @author Andy Wilkinson */ public class AnnotationsPropertySourceTests { @@ -133,6 +134,26 @@ public class AnnotationsPropertySourceTests { assertThat(source.getPropertyNames()).contains("camel-case-to-kebab-case"); } + @Test + public void propertiesFromMetaAnnotationsAreMapped() throws Exception { + AnnotationsPropertySource source = new AnnotationsPropertySource( + PropertiesFromSingleMetaAnnotation.class); + assertThat(source.getPropertyNames()).containsExactly("value"); + assertThat(source.getProperty("value")).isEqualTo("foo"); + } + + @Test + public void propertiesFromMultipleMetaAnnotationsAreMappedUsingTheirOwnPropertyMapping() + throws Exception { + AnnotationsPropertySource source = new AnnotationsPropertySource( + PropertiesFromMultipleMetaAnnotations.class); + assertThat(source.getPropertyNames()).containsExactly("value", "test.value", + "test.example"); + assertThat(source.getProperty("value")).isEqualTo("alpha"); + assertThat(source.getProperty("test.value")).isEqualTo("bravo"); + assertThat(source.getProperty("test.example")).isEqualTo("charlie"); + } + static class NoAnnotation { } @@ -262,4 +283,28 @@ public class AnnotationsPropertySourceTests { } + @PropertiesFromSingleMetaAnnotationAnnotation + static class PropertiesFromSingleMetaAnnotation { + + } + + @Retention(RetentionPolicy.RUNTIME) + @TypeLevelAnnotation("foo") + static @interface PropertiesFromSingleMetaAnnotationAnnotation { + + } + + @PropertiesFromMultipleMetaAnnotationsAnnotation + static class PropertiesFromMultipleMetaAnnotations { + + } + + @Retention(RetentionPolicy.RUNTIME) + @TypeLevelAnnotation("alpha") + @TypeLevelWithPrefixAnnotation("bravo") + @TypeAndAttributeLevelWithPrefixAnnotation("charlie") + static @interface PropertiesFromMultipleMetaAnnotationsAnnotation { + + } + }