Skip to content

Commit

Permalink
DATACMNS-1273 - Consider merged annotations when populating for annot…
Browse files Browse the repository at this point in the history
…ation cache.

We now consider property annotations as merged annotations when initially scanning for annotations in a property declaration. Composed annotations such as declared outside our code are captured correctly because they use an own type that is not queried by users of PersistentProperty. Own, revised annotations, using @AliasFor providing an alias for annotation values require merged annotation processing.

Previously, annotations were cached as-is without resolving @AliasFor. This caused a later lookup via findAnnotation(…) to return the cached annotation without aliasing. Because the annotation was cached, no further lookup via AnnotatedElementUtils.findMergedAnnotation(…) was attempted.

@retention(RetentionPolicy.RUNTIME)
@target(value = { FIELD, METHOD })
public @interface RevisedAnnnotationWithAliasFor {

	@AliasFor("value")
	String name() default "";

	@AliasFor("name")
	String value() default "";
}

public class Person {
	@RevisedAnnnotationWithAliasFor(value = "spring")
	String firstname;
}

PersistentProperty firstname = …

property.findAnnotation(…) returned previously @RevisedAnnnotationWithAliasFor(value = "spring", name = "")

now we return @RevisedAnnnotationWithAliasFor(value = "spring", name = "spring")

Original ticket: DATACMNS-981.
Java 6 compatible backport of 2da5acc.
  • Loading branch information
mp911de committed Mar 5, 2018
1 parent aadeebb commit ada4498
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2011-2016 the original author or authors.
* Copyright 2011-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -43,6 +43,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
public abstract class AnnotationBasedPersistentProperty<P extends PersistentProperty<P>>
extends AbstractPersistentProperty<P> {
Expand Down Expand Up @@ -99,7 +100,7 @@ private final void populateAnnotationCache(Field field) {
+ "multiple times on accessor methods of property %s in class %s!",
annotationType.getSimpleName(), getName(), getOwner().getType().getSimpleName());

cacheAndReturn(annotationType, annotation);
cacheAndReturn(annotationType, AnnotatedElementUtils.findMergedAnnotation(method, annotationType));
}
}

Expand All @@ -115,7 +116,7 @@ private final void populateAnnotationCache(Field field) {
"Ambiguous mapping! Annotation %s configured " + "on field %s and one of its accessor methods in class %s!",
annotationType.getSimpleName(), field.getName(), getOwner().getType().getSimpleName());

cacheAndReturn(annotationType, annotation);
cacheAndReturn(annotationType, AnnotatedElementUtils.findMergedAnnotation(field, annotationType));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2013-2017 the original author or authors.
* Copyright 2013-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,6 +29,7 @@

import org.junit.Before;
import org.junit.Test;

import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.data.annotation.AccessType;
Expand All @@ -46,6 +47,7 @@
*
* @author Oliver Gierke
* @author Christoph Strobl
* @author Mark Paluch
*/
public class AnnotationBasedPersistentPropertyUnitTests<P extends AnnotationBasedPersistentProperty<P>> {

Expand Down Expand Up @@ -197,6 +199,16 @@ public void composedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() {
assertThat(AnnotationUtils.getValue(annotation), is((Object) "spring"));
}

@Test // DATACMNS-867, DATACMNS-981, DATACMNS-1273
public void revisedAnnotationWithAliasShouldHaveSynthesizedAttributeValues() {

SamplePersistentProperty setter = entity.getPersistentProperty("setter");
RevisedAnnnotationWithAliasFor annotation = setter.findAnnotation(RevisedAnnnotationWithAliasFor.class);

assertThat(annotation.name(), is(equalTo("my-value")));
assertThat(annotation.value(), is(equalTo("my-value")));
}

@SuppressWarnings("unchecked")
private Map<Class<? extends Annotation>, Annotation> getAnnotationCache(SamplePersistentProperty property) {
return (Map<Class<? extends Annotation>, Annotation>) ReflectionTestUtils.getField(property, "annotationCache");
Expand All @@ -220,7 +232,7 @@ static class Sample {

@MyAnnotation String field;
String getter;
String setter;
@RevisedAnnnotationWithAliasFor(value = "my-value") String setter;
String doubleMapping;

@MyAnnotationAsMeta String meta;
Expand Down Expand Up @@ -282,30 +294,41 @@ public String getProperty() {

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
public static @interface MyAnnotation {
public @interface MyAnnotation {
String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
@MyAnnotation
public static @interface MyAnnotationAsMeta {
public @interface MyAnnotationAsMeta {

}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
@MyAnnotation
public static @interface MyComposedAnnotationUsingAliasFor {
public @interface MyComposedAnnotationUsingAliasFor {

@AliasFor(annotation = MyAnnotation.class, attribute = "value")
String name() default "spring";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD })
@interface RevisedAnnnotationWithAliasFor {

@AliasFor("value")
String name() default "";

@AliasFor("name")
String value() default "";
}

@Retention(RetentionPolicy.RUNTIME)
@Target(value = { FIELD, METHOD, ANNOTATION_TYPE })
@Id
public static @interface MyId {
public @interface MyId {
}

static class FieldAccess {
Expand Down Expand Up @@ -352,7 +375,7 @@ public String getField() {
@ReadOnlyProperty
@Retention(RetentionPolicy.RUNTIME)
@Target(FIELD)
static @interface CustomReadOnly {
@interface CustomReadOnly {

}
}

0 comments on commit ada4498

Please # to comment.