Spring boot condition with autowired requires a default constructor

Viewed 30

As the question states, my following code uses some properties to startup some camel routes with spring boot. But this has to happen conditionally on the camel routes class by the use of an env variable.


@Configuration
public class SomeCondition implements Condition {


    private final Properties properties;

    public SomeCondition(Properties properties) {
        this.properties = properties;
    }

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return properties.isEnableData();
    }
}

But when trying to start or run some tests, I get the error:

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [xxx.in.annotation.SomeCondition]: No default constructor found; nested exception is java.lang.NoSuchMethodException: xxx.in.annotation.SomeCondition.<init>()
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:154)
    at org.springframework.context.annotation.ConditionEvaluator.getCondition(ConditionEvaluator.java:125)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:96)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:88)
    at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:71)
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isConditionMatch(ClassPathScanningCandidateComponentProvider.java:513)
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.isCandidateComponent(ClassPathScanningCandidateComponentProvider.java:496)
    at org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider.scanCandidateComponents(ClassPathScanningCandidateComponentProvider.java:430)
    ... 88 more
Caused by: java.lang.NoSuchMethodException: 
xxxx.in.annotation.SomeCondition.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3349)
    at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:147)
    ... 95 more

Is there any way to autowire or to inject something in a condition?

1 Answers

The ConditionalContext instance has a getter method getEnvironment(), which again has methods to check properties. So you can just call that in your matches method without having to inject a bean.

That's the same way as Spring Boot does it in its OnPropertyCondition class, which basically provides the same functionality as you probably would need: https://github.com/spring-projects/spring-boot/blob/main/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnPropertyCondition.java

Additional suggestion: If the property/environment variable is the only condition, that's necessary, you can actually just use the annotation @ConditionalOnProperty which is provided by Spring Boot.

Related