Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression: default values for implicit aliases no longer honored in MergedAnnotations #24110

Closed
wants to merge 1 commit into from

Conversation

iiiron
Copy link
Contributor

@iiiron iiiron commented Dec 1, 2019

A single low-level annotation attribute can change a high-level attribute via @AliasFor, but when some low-level attribute is mirrored and is the default value, the high-level attribute will not be changed.

I think this is unreasonable.

… when some low level properties is mirrored and is default value, the high level properties will not changed, i think its unreasonable.
@pivotal-issuemaster
Copy link

@iiiron Please sign the Contributor License Agreement!

Click here to manually synchronize the status of this Pull Request.

See the FAQ for frequently asked questions.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Dec 1, 2019
@pivotal-issuemaster
Copy link

@iiiron Thank you for signing the Contributor License Agreement!

@sbrannen sbrannen added the in: core Issues in core modules (aop, beans, core, context, expression) label Dec 2, 2019
@sbrannen sbrannen changed the title Mirror repair Improve mirror handling for default values in MergedAnnotations Dec 2, 2019
@sbrannen
Copy link
Member

sbrannen commented Dec 2, 2019

@iiiron, thanks for submitting the PR.

Do you have a use case that used to work but now fails with Spring Framework 5.2.x?

@iiiron
Copy link
Contributor Author

iiiron commented Dec 2, 2019 via email

@sbrannen
Copy link
Member

sbrannen commented Dec 2, 2019

No I didn't,I just find it by reading the source code.

Thanks for providing feedback.

Since the proposed change does not address a regression, I would like to wait on input from @philwebb.

In addition, after reviewing the affected code, it appears to me that leaving the result set to -1 in such cases does not lead to any negative side effects.

@sbrannen sbrannen requested a review from philwebb December 2, 2019 15:00
@philwebb
Copy link
Member

philwebb commented Dec 2, 2019

I'm not sure I totally understand the issue. @iiiron can you clarify what you mean by "when some low-level attribute is mirrored and is the default value, the high-level attribute will not be changed"? Perhaps you can provide some sample annotations that show what you mean?

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label Dec 2, 2019
@iiiron
Copy link
Contributor Author

iiiron commented Dec 3, 2019 via email

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Dec 3, 2019
@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

Thanks for providing the example.

In terms of executable tests, the following passes against master.

class TestCase {

	@Test
	void findMergedAnnotation() {
		MyAnnotation myAnnotation = AnnotatedElementUtils.findMergedAnnotation(AnnotatedClass.class,
			MyAnnotation.class);
		assertThat(myAnnotation).isNotNull();
		assertThat(myAnnotation.b1()).isEqualTo("testA");
		assertThat(myAnnotation.b2()).isEqualTo("testA");
	}

	@Test
	void findMergedAnnotationAttributes() {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(AnnotatedClass.class,
			MyAnnotation.class, false, true);

		assertThat(attributes).isNotNull();
		assertThat(attributes).size().isEqualTo(2);
		assertThat(attributes.get("b1")).isEqualTo("testA");
		assertThat(attributes.get("b2")).isEqualTo("testA");
	}
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {

	@AliasFor("b2")
	String b1() default "testB";

	@AliasFor("b1")
	String b2() default "testB";
}
@MyAnnotation
@Retention(RetentionPolicy.RUNTIME)
@interface ComposedAnnotation {

	@AliasFor(attribute = "b1", annotation = MyAnnotation.class)
	String a1() default "testA";

}
@ComposedAnnotation
class AnnotatedClass {
}

@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

In addition, the following JUnit 4 based tests pass against 5.1.x.

public class TestCase {

	@Test
	public void findMergedAnnotation() {
		MyAnnotation myAnnotation = AnnotatedElementUtils.findMergedAnnotation(AnnotatedClass.class,
			MyAnnotation.class);
		assertNotNull(myAnnotation);
		assertEquals("testA", myAnnotation.b1());
		assertEquals("testA", myAnnotation.b2());
	}

	@Test
	public void findMergedAnnotationAttributes() {
		AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(AnnotatedClass.class,
			MyAnnotation.class, false, true);

		assertNotNull(attributes);
		assertEquals(2, attributes.size());
		assertEquals("testA", attributes.get("b1"));
		assertEquals("testA", attributes.get("b2"));
	}
}
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {

	@AliasFor("b2")
	String b1() default "testB";

	@AliasFor("b1")
	String b2() default "testB";
}
@MyAnnotation
@Retention(RetentionPolicy.RUNTIME)
@interface ComposedAnnotation {

	@AliasFor(attribute = "b1", annotation = MyAnnotation.class)
	String a1() default "testA";

}
@ComposedAnnotation
class AnnotatedClass {
}

Thus, there is not a regression in 5.2.x for this behavior.

@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

The low-level annotation attributes should have priority over high-level annotation attributes, like subclass can overwrite the methods in super-class.

That is exactly the behavior that is supported.

In the tests I provided, @ComposedAnnotation is like a subclass of @MyAnnotation, and the default value for a1 overrides the default values for b1 and b2.

In light of that, I am closing this PR as "works as designed".

For further information on Spring's support for composed annotations and @AliasFor, consult the Spring Annotation Programming Model wiki page.

@sbrannen sbrannen closed this Dec 3, 2019
@sbrannen sbrannen removed the request for review from philwebb December 3, 2019 13:27
@sbrannen sbrannen self-assigned this Dec 3, 2019
@sbrannen sbrannen added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Dec 3, 2019
@iiiron
Copy link
Contributor Author

iiiron commented Dec 3, 2019 via email

@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

The tests still pass against 5.1.x with only the following changes.

@ComposedAnnotation2
class AnnotatedClass {
}

@MyAnnotation
@Retention(RetentionPolicy.RUNTIME)
@interface ComposedAnnotation2 {

	@AliasFor(attribute = "b1", annotation = MyAnnotation.class)
	String a1() default "testA";

	@AliasFor(attribute = "b2", annotation = MyAnnotation.class)
	String a2() default "testA";
}

However, the tests in fact fail against master with the same changes.

Thus I am reopening this issue since it is in fact a regression.

@iiiron, thank you very much bringing this to our attention!

@sbrannen sbrannen reopened this Dec 3, 2019
@sbrannen sbrannen added type: regression A bug that is also a regression and removed status: invalid An issue that we don't feel is valid labels Dec 3, 2019
@sbrannen sbrannen added this to the 5.2.3 milestone Dec 3, 2019
@sbrannen sbrannen removed their assignment Dec 3, 2019
@sbrannen sbrannen changed the title Improve mirror handling for default values in MergedAnnotations Regression: default values for implicit aliases no longer honored in MergedAnnotations Dec 3, 2019
@iiiron
Copy link
Contributor Author

iiiron commented Dec 3, 2019 via email

@sbrannen sbrannen self-assigned this Dec 3, 2019
@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

The proposed code change in the PR appears to fix the regression.

So I've scheduled this for 5.2.3.

@sbrannen sbrannen closed this in 6f15f32 Dec 3, 2019
sbrannen added a commit that referenced this pull request Dec 3, 2019
@sbrannen
Copy link
Member

sbrannen commented Dec 3, 2019

This has been merged into master in 6f15f32 with an additional integration test in fb13f6f.

Thanks again for the PR! 👏

@philwebb
Copy link
Member

philwebb commented Dec 3, 2019

Thanks @iiiron and @sbrannen !

sbrannen added a commit that referenced this pull request Dec 3, 2019
gnehcgnaw pushed a commit to gnehcgnaw/spring-framework that referenced this pull request Dec 4, 2019
…mework into 5.1.x

* '5.1.x' of https://github.com/spring-projects/spring-framework: (26 commits)
  Add integration test for spring-projectsgh-24110
  Next Development Version
  Provide default codecs config callback to custom codecs
  Allow ExchangeStrategies customizations in WebClient
  Upgrade to AspectJ 1.9.5 and Checkstyle 8.27
  Revert "Allow ExchangeStrategies customizations in WebClient"
  Polishing
  Polishing
  Backport of recent ExtendedBeanInfo refinements from master
  Allow ExchangeStrategies customizations in WebClient
  Test status quo for @inherited annotations in AnnotationMetadata
  Test status quo for AnnotatedTypeMetadata.getAnnotationAttributes()
  Upgrade to Reactor Californium-SR14
  Remove println
  Fix NullPointerException in Jackson2SmileDecoder
  Upgrade to Tomcat 9.0.29, Jetty 9.4.24, RxJava 2.2.15
  Add missing verify() in Jackson2TokenizerTests
  Extra isReady-onWritePossible after last write
  Restore short-circuiting in equals implementation
  Upgrade to Jetty 9.4.23 and Woodstox 5.3
  ...
Kvicii pushed a commit to Kvicii/spring-framework that referenced this pull request Dec 7, 2019
…amework into read_yuyang

* 'master' of https://github.com/spring-projects/spring-framework: (32 commits)
  Polishing
  Add missing backtick in WebSocket documentation
  Hoist Class.getName() from String concatenation to dodge an issue related to profile pollution
  Support variable resolution of wildcard types
  Test status quo for @inherited annotation support in AnnotationMetadata
  Polishing
  Add @SInCE tags to firstElement methods
  Add firstElement to CollectionUtils
  Fix status code in webflux.adoc
  Consistently use releaseBody in DefaultWebClient
  Replace ReadCancellationException with takeWhile
  Add UriUtils.encodeQueryParams
  Remove mismatched marker in core-beans.adoc
  Add integration test for spring-projectsgh-24110
  Honor default values for implicit aliases in composed annotations
  Next Development Version
  Polish
  Provide default codecs config callback to custom codecs
  [*.*] is displayed as [bold .] and needs to be escaped
  Polishing (follow-up on acfeb7)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: feedback-provided Feedback has been provided type: regression A bug that is also a regression
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants