1

I'm using @ConstructorBinding with @ConfigurationProperties like this

    @ConstructorBinding
    @ConditionalOnProperty(name = "nexus.orchestration.cloud.model", havingValue = "true", matchIfMissing = false)
    @ConfigurationProperties(value = "nexus.orchestration.model.cloud-bucket", ignoreUnknownFields = false)
    @ToString
    public static class ModelCloudBucket {
        private final CloudBucket cloudBucket;

        public ModelCloudBucket(final CloudProviderEnum provider, final String bucket, final String folder) {
            this.cloudBucket = new CloudBucket(provider, bucket, folder);
        }
    }

I have @EnableConfigurationProperties(FlowCache.ModelCloudBucket.class) on my main application class

However, the @ConditionalOnProperty is not working. If my property is false and I comment out the CloudBucket object in the yaml file, it fails on startup because it can't bind the cloud bucket property. If the property is false, than that object should not be required and then bean should just be null. How can I make this work?

Peter Kronenberg
  • 878
  • 10
  • 32

1 Answers1

1

From my understanding, Spring @ConditionalOnProperty and @ConfigurationProperties are used in two different areas:

  1. @ConditionalOnProperty is used to conditional inject beans and configurations.
  2. @ConfigurationProperties is for external configurations, which is from your configuration files like application.properties

From the code, I assume that ModelCloudBucket is a bean you want to inject if nexus.orchestration.cloud.model == true, which takes provider, bucket and folder as its properties.

So I would suggest to the following code:

A property class:

@Configuration
@ConfigurationProperties(prefix = "nexus.orchestration.model.cloud-bucket")
@Data
public class ModelCloudBucketProps {
    private CloudProviderEnum  testProp;
    private String bucket;
    private String folder;
}

And the original bean which will be injected with properties:

@Component
@ConditionalOnProperty(name = "nexus.orchestration.cloud.model", havingValue = "true")
public class ModelCloudBucket {
    ...
    public ModelCloudBucket(ModelCloudBucketProps config) {
         this.cloudBucket = new CloudBucket(config.getProvider(), ...);
    }
}

@EnableConfigurationProperties(FlowCache.ModelCloudBucket.class) can be removed since will be injected through @Configuration.

In this way, you can control the bean injection with condition and decouple it with the external config initialization.

Greg
  • 1,363
  • 13
  • 15
  • But won't I have the same problem when ModelCloudBucketProps tries to inject properties that aren't in the yaml file? – Peter Kronenberg Apr 03 '22 at 20:58
  • 1
    `ModelCloudBucketProps` will still be injected with null values if properties are not presented in the yaml file, yet `ModelCloudBucket` will not be injected anymore. – Greg Apr 04 '22 at 01:52