I have an application that needs to run for multiple tenants. There is some validation logic, but not all tenants have the same checks.
I would like to have a list of strings in my application.yml and conditional beans implementing the same interface that check if a certain string is contained:
application.yml
my-app:
checks:
check-one,
check-two
Bean
@Component
@ConditionalOnProperty(value = "my-app.checks", havingValue = "check-one")
public class CheckOne implements Check {}
But this doesn't seem to work.
Do I really have to use something like this (which works):
my-app:
checks:
check-one: true
check-two: true
And then @ConditionalOnProperty(value = "my-app.checks.check-one", havingValue = "true")
Based on @pebble units comment I made a custom annotation:
Annotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
@Documented
@Conditional({OnPropertyContains.class})
public @interface ConditionalOnPropertyContains {
String containsValue();
String name();
}
Implementation
public class OnPropertyContains extends SpringBootCondition {
OnPropertyContains() {}
@Override
public ConditionOutcome getMatchOutcome(
final ConditionContext context, final AnnotatedTypeMetadata metadata) {
final String name =
(String)
metadata
.getAnnotationAttributes(ConditionalOnPropertyContains.class.getName())
.get("name");
final String value =
(String)
metadata
.getAnnotationAttributes(ConditionalOnPropertyContains.class.getName())
.get("containsValue");
final Environment env = context.getEnvironment();
final String[] values = env.getProperty(name, String[].class, new String[0]);
if (Arrays.asList(values).contains(value)) {
return ConditionOutcome.match();
}
return ConditionOutcome.noMatch("Property '" + name + "' does not contain '" + value + "'");
}
}
Usage
@ConditionalOnPropertyContains(name= "my-app.checks", containsValue = "check-one")