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

AnnotationBeanNameGenerator issues warning about explicitly aliased value attribute #34317

Open
odrotbohm opened this issue Jan 24, 2025 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: backported An issue that has been backported to maintenance branches type: bug A general bug
Milestone

Comments

@odrotbohm
Copy link
Member

odrotbohm commented Jan 24, 2025

Assume an annotation that declares a value() attribute explicitly aliasing an attribute other than @Component(value = "…").

@interface MyAnnotation {

  @AliasFor(annotation = Foo.class, attribute = "…")
  String value() default "";
}

If that annotation gets used with a set value (@MyAnnotation("foo")), I now see a warning:

Support for convention-based stereotype names is deprecated and will \
be removed in a future version of the framework. Please annotate the \
'value' attribute in @MyAnnotation with @AliasFor(annotation=Component.class) \
to declare an explicit alias for @Component's 'value' attribute.

This warning should not be issued if the value() attribute is explicitly aliased to some attribute other than @Component's value.

Also, the phrasing of "convention-based stereotype names" in combination with @Component led me to believe it's about the bean name stereotypically being derived from the class name (which made it particularly puzzling as the warning only appears with a value set, which would not trigger that convention). It turns out this term is actually referring to the default aliasing convention of the annotation attributes (the @MyAnnotation.value() conventionally being considered a redeclaration of @Component.value()). I wonder if the message's wording could be adapted to clarify this.

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Jan 24, 2025
@snicoll snicoll changed the title AnnotationBeanNameGenerator issuing warnings about value() declaration explicitly aliasing AnnotationBeanNameGenerator issuing warnings about value() declaration explicitly aliasing Jan 28, 2025
@snicoll snicoll added the in: core Issues in core modules (aop, beans, core, context, expression) label Jan 28, 2025
@jhoeller jhoeller added type: regression A bug that is also a regression and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Jan 28, 2025
@jhoeller jhoeller added this to the 6.2.3 milestone Jan 28, 2025
@jhoeller jhoeller added type: bug A general bug for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x and removed type: regression A bug that is also a regression labels Jan 28, 2025
@github-actions github-actions bot added status: backported An issue that has been backported to maintenance branches and removed for: backport-to-6.1.x Marks an issue as a candidate for backport to 6.1.x labels Jan 28, 2025
@sbrannen sbrannen changed the title AnnotationBeanNameGenerator issuing warnings about value() declaration explicitly aliasing AnnotationBeanNameGenerator issuing warnings about value() declaration explicitly aliasing Jan 28, 2025
@sbrannen sbrannen self-assigned this Jan 28, 2025
@sbrannen sbrannen changed the title AnnotationBeanNameGenerator issuing warnings about value() declaration explicitly aliasing AnnotationBeanNameGenerator issues warning about value() declaration explicitly aliasing Jan 28, 2025
@snicoll snicoll changed the title AnnotationBeanNameGenerator issues warning about value() declaration explicitly aliasing AnnotationBeanNameGenerator issues warning about value() declaration explicitly aliasing Jan 28, 2025
@sbrannen sbrannen changed the title AnnotationBeanNameGenerator issues warning about value() declaration explicitly aliasing AnnotationBeanNameGenerator issues warning about explicitly aliased value attribute Jan 29, 2025
@sbrannen
Copy link
Member

sbrannen commented Jan 30, 2025

This raises some interesting questions, so thanks for bringing this to our attention! 👍

I wonder if the message's wording could be adapted to clarify this.

We can definitely improve the wording, but before we do that we should decide what to do about the status quo in terms of actual behavior.

This warning should not be issued if the value attribute is explicitly aliased to some attribute other than @Component's value.

Yes and no. Let me explain...

With the current behavior, we need such a warning, because that value is actually used as the @Component name (see example below).

But if we were to no longer use such an explicitly aliased value as the @Component name, then the message would not be necessary for that particular use case.


I put together the following to demonstrate the status quo.

@Retention(RetentionPolicy.RUNTIME)
@interface SomeAnnotation {

	String attribute() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Component
@SomeAnnotation
@interface MyComponent {

	@AliasFor(annotation = SomeAnnotation.class, attribute = "attribute")
	String value() default "";
}
@MyComponent("enigma")
class ConcreteComponent {
}
@SpringJUnitConfig
class ComponentNameTests {

	@Test
	void annotationValues() {
		MergedAnnotations mergedAnnotations = MergedAnnotations.from(ConcreteComponent.class);
		SomeAnnotation someAnnotation = mergedAnnotations.get(SomeAnnotation.class).synthesize();
		Component component = mergedAnnotations.get(Component.class).synthesize();

		// @Component(value = "")
		assertThat(component.value()).isBlank();
		// @MyComponent(value = "enigma") -> @SomeAnnotation(attribute = "enigma")
		assertThat(someAnnotation.attribute()).isEqualTo("enigma");
	}

	@Test
	void beanName(ApplicationContext context) {
		// "enigma" comes from @MyComponent("enigma");
		// whereas, AnnotationBeanNameGenerator would generate "concreteComponent".
		assertThat(context.getBeanNamesForType(ConcreteComponent.class))
				.containsExactly("enigma");
	}
	@Configuration
	@ComponentScan(includeFilters =
		@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ConcreteComponent.class))
	static class Config {
	}
}

The above tests pass which means that the @Component name for the component-scanned ConcreteComponent bean comes from the @MyComponent("enigma") declaration even though MyComponent.value is an explicit @AliasFor SomeAnnotation.attribute.

Thus, with the status quo, that log message is intended to warn you that MyComponent.value is interpreted as the @Component name even if that is not your intention.

Historically, a String value() attribute has always been considered the @Component name. Since Spring Framework 6.1 (see #31089), one should ideally make use of @AliasFor. However, the value convention remains in effect. We would like to remove that support at some point in the future, but we have not yet decided when we will do that.


Now that we've clarified the status quo, let's look at our options.

  1. Leave the behavior as-is and update the warning to better explain what's going on.
  2. Stop using a value attribute that is explicitly aliased to something other than @Component.value as the @Component name.
  3. Stop supporting the String value() convention for @Component names.

We can do #1 in 6.2.x and backport that to 6.1.x.

We could consider doing #2 in 6.2.x or 7.0.

We could consider doing #3 in 7.0 or 8.0.

Note, however, that #2 and #3 would technically be breaking changes for certain users.

If anyone would like to share their thoughts on the matter, feel free to do so here. In any case, we will discuss this within the Framework team.

@sbrannen
Copy link
Member

Update

For Spring Framework 6.2.x and 6.1.x, we will use this GitHub issue to improve the log message to clarify the following different scenarios (effectively option #1 above).

  • value is not annotated with @AliasFor and is therefore used as a convention-based override for Component.value.
  • value is annotated with @AliasFor as an override for an attribute other than Component.value and yet is still used as the @Component name.

For Spring Framework 7 (see #34346), we will stop using a value attribute that is explicitly aliased to something other than @Component.value as the @Component name (effectively option #2 above).

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: backported An issue that has been backported to maintenance branches type: bug A general bug
Projects
None yet
Development

No branches or pull requests

5 participants