You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Regression: custom composed @Profile annotation without runtime retention no longer supported with component scanning #23901
Hi, I get a similar problem with my composed annotation contains @Component and @javax.enterprise.inject.Stereotype. But Spring cannot scan it anymore. I just saw it was mentioned in the upgrading document as a side effect but is my problem on purpose?
Please note, however, that @Retention(RetentionPolicy.RUNTIME) is required for any annotation in Java if the annotation needs to be found at runtime. Spring always evaluates annotations at runtime. Thus it has always been required for use with Spring.
In light of that, it is not possible that it worked before Spring Framework 5.2 without @Retention(RetentionPolicy.RUNTIME).
I am sorry but you are not right with "In light of that, it is not possible that it worked before Spring Framework 5.2 without @Retention(RetentionPolicy.RUNTIME)."
I have created a small app with Spring Boot version 1.5.22.RELEASE and even when @Retention(RetentionPolicy.RUNTIME) is commented then DevComponent class is not created, when spring.profiles.active=test is set. But in the Spring Boot 2.2.0.RELEASE it loads both DevComponent and TestComponent.
If you run ./gradlew bootRun you will see log message:
with Spring Boot version '1.5.22.RELEASE' (only TestComponent is created):
2019-11-01 13:27:21.945 INFO 44112 --- [ main] c.s.c.CustomProfileAnnotationApplication : The following profiles are active: test
2019-11-01 13:27:22.034 INFO 44112 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1da51a35: startup date [Fri Nov 01 13:27:22 CET 2019]; root of context hierarchy
2019-11-01 13:27:22.570 INFO 44112 --- [ main] c.s.c.test.TestComponent : test component created.
2019-11-01 13:27:22.805 INFO 44112 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2019-11-01 13:27:22.828 INFO 44112 --- [ main] c.s.c.CustomProfileAnnotationApplication : Started CustomProfileAnnotationApplication in 1.362 seconds (JVM running for 2.127)
with Spring Boot version '2.2.0.RELEASE' (TestComponent and DevComponent are created):
2019-11-01 13:28:12.612 INFO 44142 --- [ main] c.s.c.CustomProfileAnnotationApplication : The following profiles are active: test
2019-11-01 13:28:13.056 INFO 44142 --- [ main] c.s.c.dev.DevComponent : dev component created.
2019-11-01 13:28:13.057 INFO 44142 --- [ main] c.s.c.test.TestComponent : test component created.
2019-11-01 13:28:13.118 INFO 44142 --- [ main] c.s.c.CustomProfileAnnotationApplication : Started CustomProfileAnnotationApplication in 0.929 seconds (JVM running for 1.287)
changed the title [-]Regression: custom composed @Profile annotation no longer supported[/-][+]Regression: custom composed @Profile annotation no longer supported with component scanning[/+]on Nov 1, 2019
changed the title [-]Regression: custom composed @Profile annotation no longer supported with component scanning[/-][+]Regression: custom composed @Profile annotation without runtime retention no longer supported with component scanning[/+]on Nov 1, 2019
I am sorry but you are not right with "In light of that, it is not possible that it worked before Spring Framework 5.2 without @Retention(RetentionPolicy.RUNTIME)."
You're correct!
It turns out that my statement was only partially true. So I apologize for that.
My statement was true for any annotations looked up by Spring using reflection. However, as your example project demonstrates, the same was not true for annotations looked up via ASM (i.e., by analyzing the compiled byte code directly).
So, thanks for providing the example project, because that helped me get to the bottom of this mystery! 👍
Speaking of which, I executed javap -v DevComponent.class which revealed the following.
That showed that something must have been reading the "invisible" @DevProfile annotation, even though it should not have been doing so. Some further investigation lead me to the following conclusion...
Prior to Spring Framework 5.2, our ASM-based annotation processing also looked up class retention annotations by accident. This bug was fixed in #22886, and the new MergedAnnotations API internals also implement the same behavior (see #22884).
As of Spring Framework 5.2, all annotations are now required to be annotated with @Retention(RetentionPolicy.RUNTIME) in order for Spring to see them.
In addition, please note that Spring only uses ASM to look up annotations during component scanning (e.g., for annotations on component-scanned classes such as @Component, @Service, @Configuration, @Profile, @Import, etc.), JPA @Entity scanning, and JAXB2 mapped class scanning, as well as for annotation metadata supplied to implementations of ImportSelector and ImportBeanDefinitionRegistrar. Otherwise, Spring uses reflection to look up annotations.
In other words, most user code should not be affected by this change in Spring Framework 5.2. I'll add a note to the Core Container upgrade notes to point this out as well.
I hope this clarifies everything, and thanks again for sticking your ground and providing a failing example project!
Activity
[-]Custom @Profile annotation[/-][+]Regression: custom composed @Profile annotation no longer supported[/+]sbrannen commentedon Oct 31, 2019
@pavelspicak, did you declare your custom annotation with runtime retention as follows?
sbrannen commentedon Oct 31, 2019
Also, how is the component annotated with
@SapConnectorProfileregistered in theApplicationContext?Is that via component scanning,
@Beanmethod registration, or some other means?kingtran2112 commentedon Nov 1, 2019
Hi, I get a similar problem with my composed annotation contains
@Componentand@javax.enterprise.inject.Stereotype. But Spring cannot scan it anymore. I just saw it was mentioned in the upgrading document as a side effect but is my problem on purpose?pavelspicak commentedon Nov 1, 2019
Hello,
you are right @sbrannen. I was missing
@Retention(RetentionPolicy.RUNTIME). It was not necessary in Spring 4.With
@Retention(RetentionPolicy.RUNTIME)it works again.Thank you very much.
kingtran2112 commentedon Nov 1, 2019
It works for me also but I curious why it needs the annotation for version 5.2 since before it wasn't?
sbrannen commentedon Nov 1, 2019
@pavelspicak and @kingtran2112, thanks for the feedback. Glad to hear that it works now for you.
Please note, however, that
@Retention(RetentionPolicy.RUNTIME)is required for any annotation in Java if the annotation needs to be found at runtime. Spring always evaluates annotations at runtime. Thus it has always been required for use with Spring.In light of that, it is not possible that it worked before Spring Framework 5.2 without
@Retention(RetentionPolicy.RUNTIME).pavelspicak commentedon Nov 1, 2019
I am sorry but you are not right with "In light of that, it is not possible that it worked before Spring Framework 5.2 without
@Retention(RetentionPolicy.RUNTIME)."I have created a small app with Spring Boot version
1.5.22.RELEASEand even when@Retention(RetentionPolicy.RUNTIME)is commented thenDevComponentclass is not created, whenspring.profiles.active=testis set. But in the Spring Boot2.2.0.RELEASEit loads bothDevComponentandTestComponent.You can take a look here: https://github.com/pavelspicak/customProfileAnnotation
If you run
./gradlew bootRunyou will see log message:sbrannen commentedon Nov 1, 2019
@pavelspicak, thanks for providing the example project. I'll take a look.
[-]Regression: custom composed @Profile annotation no longer supported[/-][+]Regression: custom composed @Profile annotation no longer supported with component scanning[/+][-]Regression: custom composed @Profile annotation no longer supported with component scanning[/-][+]Regression: custom composed @Profile annotation without runtime retention no longer supported with component scanning[/+]sbrannen commentedon Nov 3, 2019
Hi @pavelspicak,
You're correct!
It turns out that my statement was only partially true. So I apologize for that.
My statement was true for any annotations looked up by Spring using reflection. However, as your example project demonstrates, the same was not true for annotations looked up via ASM (i.e., by analyzing the compiled byte code directly).
So, thanks for providing the example project, because that helped me get to the bottom of this mystery! 👍
Speaking of which, I executed
javap -v DevComponent.classwhich revealed the following.That showed that something must have been reading the "invisible"
@DevProfileannotation, even though it should not have been doing so. Some further investigation lead me to the following conclusion...Prior to Spring Framework 5.2, our ASM-based annotation processing also looked up class retention annotations by accident. This bug was fixed in #22886, and the new
MergedAnnotationsAPI internals also implement the same behavior (see #22884).As of Spring Framework 5.2, all annotations are now required to be annotated with
@Retention(RetentionPolicy.RUNTIME)in order for Spring to see them.In addition, please note that Spring only uses ASM to look up annotations during component scanning (e.g., for annotations on component-scanned classes such as
@Component,@Service,@Configuration,@Profile,@Import, etc.), JPA@Entityscanning, and JAXB2 mapped class scanning, as well as for annotation metadata supplied to implementations ofImportSelectorandImportBeanDefinitionRegistrar. Otherwise, Spring uses reflection to look up annotations.In other words, most user code should not be affected by this change in Spring Framework 5.2. I'll add a note to the Core Container upgrade notes to point this out as well.
I hope this clarifies everything, and thanks again for sticking your ground and providing a failing example project!
Cheers,
Sam
pavelspicak commentedon Nov 4, 2019
Hi @sbrannen,
thank you very much for the clarification.
Best regards,
Pavel.