Home > Back-end >  @ConditionalOnProperty on YAML objects
@ConditionalOnProperty on YAML objects

Time:01-28

I have an YAML that looks like this:

client:
  auth:
    foo:
      something: 123
      whatever: 321
    bar:
      idk: 999
      anything: bleh

I'm trying to create beans whether they're specified on that YAML, example:

@Bean
@ConditionalOnProperty(prefix = "client.auth", name = "foo")
public Foo foo() {
    return new Foo();
}

@Bean
@ConditionalOnProperty(prefix = "client.auth", name = "bar")
public Bar bar() {
    return new Bar();
}

Such YAML should create only the Bar bean (no client.auth.foo specified):

client:
  auth:
    bar:
      idk: 999
      anything: bleh

However, this does not work (beans aren't created). I've also tried the following (foo's - bar's omitted for brevity):

@Bean
@ConditionalOnProperty(prefix = "client.auth", value = "foo")
public Foo foo() {
    return new Foo();
}

@Bean
@ConditionalOnProperty(prefix = "client", name = "auth", havingValue = "foo")
public Foo foo() {
    return new Foo();
}

Is it possible to achieve what I'm looking for? How?

CodePudding user response:

Approach #1:

ConditionalOnProperty work on the complete property name. For your usecase, something that could work is if you can add an additional boolean parameter like client.auth.foo.enabled. Like shown below:

@Bean
@ConditionalOnProperty(value = "client.auth.foo.enabled", havingValue = "true")
public Foo foo() {
    return new Foo();
}

Corresponding yaml file

client:
  auth:
    foo:
      enabled: true
      something: 123
      whatever: 321

Approach #2:

You can implement your own Condition to check whether the property prefix exist.

@Bean
@Conditional(MyCondition.class)
public Foo foo() {
    return new Foo();
}

static class MyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        final String prefix = "client.auth.foo";
        if (context.getEnvironment() instanceof ConfigurableEnvironment env) {
            for (PropertySource<?> propertySource : env.getPropertySources()) {
                if (propertySource instanceof EnumerablePropertySource enumerablePropertySource) {
                    for (String key : enumerablePropertySource.getPropertyNames()) {
                        if (key.startsWith(prefix)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}

Based on https://stackoverflow.com/a/47873601 modified for your usecase

  •  Tags:  
  • Related