I've seen several "how to write a custom Condition" (org.springframework.context.annotation.Condition)
https://www.baeldung.com/spring-conditional-annotations#defining-custom-conditions
All of these have had "trivial" implementations, or using "globally" available items (like environment variables).
I have searched and tried to find a custom Condition that needs a constructor injected dependency.
I get there is kind of a catch-22 because the @Conditional is during the process of registering the items into the IoC context.
Here is a complete (but "silly") example of what I am trying to do:
public interface IFavoriteColorFinder() {
String findFavoriteColor();
}
..
public class FirstConcreteIFavoriteColorFinder implements IFavoriteColorFinder {
@Override
public String findFavoriteColor() {
return "green";
}
}
..
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
public final class FavoriteColorsAreCoolCondition implements Condition {
private final IFavoriteColorFinder colorFinder;
public FavoriteColorsAreCoolCondition(IFavoriteColorFinder colorFinder) {
if (null == colorFinder) {
throw new IllegalArgumentException("IFavoriteColorFinder is null");
}
this.colorFinder = colorFinder;
}
@Override
public boolean matches(
ConditionContext context,
AnnotatedTypeMetadata metadata) {
String favoriteColorValue = this.colorFinder.findFavoriteColor();
boolean returnValue = favoriteColorValue.equalsIgnoreCase("red");
return returnValue;
}
}
..
and then using java config
I tried "just the Condition annotation" as seen below.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CompositionRootJavaConfig {
@Conditional(FavoriteColorsAreCoolCondition.class)
@Bean
public ArithmeticException addArithmeticExcepiton() {
return new ArithmeticException("This exists to test if FavoriteColorsAreCoolCondition works or not");
}
}
That failed with a
org.springframework.beans.BeanInstantiationException: Failed to instantiate [mypackage.FavoriteColorsAreCoolCondition]: No default constructor found; nested exception is java.lang.NoSuchMethodException: mypackage.FavoriteColorsAreCoolCondition.()
So I made sure those other items were available:
@Bean
public IFavoriteColorFinder getAnIFavoriteColorFinder() {
return new FirstConcreteIFavoriteColorFinder();
}
and even (below) tried to put the custom conditon into the IoC as seen below:
@Bean
public FavoriteColorsAreCoolCondition getAnFavoriteColorsAreCoolCondition(IFavoriteColorFinder colrFinder) {
return new FavoriteColorsAreCoolCondition(colrFinder);
}
But it keeps coming back to "need default constructor" .. (on the custom Condition, aka, FavoriteColorsAreCoolCondition)
Is there anyway to create an "interesting" (non trivial) custom Condition that needs dependencies to figure out its boolean result?
The documentation of
Conditionexplicitly states thatThis is why it requires default no-args constructor to be available and this is why declaring
Conditionwith@Beanwon't help.So you can use neither constructor-based injection, nor
@Autowired. As Andrey mentioned the correct way to get bean inmatches()method is to usecontext: