java – Combine @Component and @ConditionalOnBean into one annotation

I want to combine two Spring annotations into a single one.

More exactly I want to combine @Component and @ConditionalOnBean into one annotation named @SubComponent.

Is this possible?

What I have tried so far:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Configuration
    @ConditionalOnProperty(prefix = "user", name = "property", havingValue = "true")
    @Slf4j
    static class TestableConfiguration {

        public TestableConfiguration() {
            log.info(getClass().getSimpleName() + " 666666 initialized");
        }

        @Component
        @ConditionalOnBean(TestableConfiguration.class)
//      @SubComponent(TestableConfiguration.class)
        static class Insight {
            public Insight() {
                log.info(getClass().getSimpleName() + " 666666 initialized");
            }
        }
    }
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@ConditionalOnBean
@interface SubComponent {

    @AliasFor(attribute = "value", annotation = ConditionalOnBean.class)
    Class<?>[] value() default {};
}

but I am receiving an exception :

org.springframework.beans.factory.BeanDefinitionStoreException: Failed to read candidate component class: file [C:UsersQV29YTworkwork_testing2022_apr_27demotargetclassescomexampledemoSubComponent.class]; nested exception is java.lang.IllegalStateException: Error processing condition on com.example.demo.SubComponent
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:457) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.findCandidateComponents(ClassPathScanningCandidateComponentProvider.java:316) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ClassPathBeanDefinitionScanner.doScan(ClassPathBeanDefinitionScanner.java:276) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ComponentScanAnnotationParser.parse(ComponentScanAnnotationParser.java:128) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:296) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.6.7.jar:2.6.7]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:740) ~[spring-boot-2.6.7.jar:2.6.7]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:415) ~[spring-boot-2.6.7.jar:2.6.7]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:303) ~[spring-boot-2.6.7.jar:2.6.7]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1312) ~[spring-boot-2.6.7.jar:2.6.7]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[spring-boot-2.6.7.jar:2.6.7]
    at com.example.demo.DemoApplication.main(DemoApplication.java:18) ~[classes/:na]
Caused by: java.lang.IllegalStateException: Error processing condition on com.example.demo.SubComponent
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-2.6.7.jar:2.6.7]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:90) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:71) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isConditionMatch(ClassPathScanningCandidateComponentProvider.java:512) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isCandidateComponent(ClassPathScanningCandidateComponentProvider.java:495) ~[spring-context-5.3.19.jar:5.3.19]
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:430) ~[spring-context-5.3.19.jar:5.3.19]
    ... 20 common frames omitted
Caused by: java.lang.IllegalStateException: @ConditionalOnBean did not specify a bean using type, name or annotation
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.validate(OnBeanCondition.java:492) ~[spring-boot-autoconfigure-2.6.7.jar:2.6.7]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.<init>(OnBeanCondition.java:443) ~[spring-boot-autoconfigure-2.6.7.jar:2.6.7]
    at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:118) ~[spring-boot-autoconfigure-2.6.7.jar:2.6.7]
    at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.6.7.jar:2.6.7]
    ... 26 common frames omitted


Process finished with exit code 1

What I want to do is have something as the line commented, to create a bean if a certain condition is meet.

Do you know if this is possible?

Or are there any other ways of handling this?

Leave a Comment