1

Is it expected that configuration properties classes should be usable within @Configuration classes.

Environment

  • Spring Boot 2.0.2
  • java version "10.0.1" 2018-04-17 Java(TM) SE Runtime Environment 18.3 (build 10.0.1+10), Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.1+10, mixed mode)
  • OSX 10.13.4

My Code

application-local.properties:

s3.bucketName=test-bucket

Configuration Properties

@Validated
@ConfigurationProperties(prefix = "s3")
public class S3ConfigurationProperties {

    @NotBlank
    private String bucketName;

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(final String bucketName) {
        this.bucketName = bucketName;
    }
}

Configuration Class

@Configuration
@Profile("local")
@EnableConfigurationProperties(S3ConfigurationProperties.class)
public class LocalS3Configuration {

    @Autowired
    private S3ConfigurationProperties properties;

    @Value("${s3.bucketName}")
    private String bucket;

    @Bean(destroyMethod = "shutdown")
    public AmazonS3 amazonS3(@Value("${local.s3.endpoint}") final String s3Endpoint, @Value("${s3.bucketName}") final String bucketName) {
        // use properties...
        final String bucketInjectedToMethod = bucketName; // works
        final String bucketInjectedViaProperties = properties.getBucketName(); // null
        final String bucketInjectedInClass = bucket; // null

    }

}

Observed Behaviour

If I inject the S3ConfigurationProperties as a field to the configuration class or an argument to the amazonS3 method the instance is non-null, but the bucketName property within it is null.

Injecting the string to the class via @Value is also null.

The only way I can get it to work is to use the method argument annotated as @Value with a string.

Is this expected behaviour or possibly a bug?

David
  • 7,652
  • 21
  • 60
  • 98

1 Answers1

3

In your case it is not necessary to use @EnableConfigurationProperties. You can put @Configuration in S3ConfigurationProperties:

@Configuration
@ConfigurationProperties(prefix = "s3")
public class S3ConfigurationProperties {

    private String bucketName;

    //getter and setter
}

So, now you can inject it in LocalS3Configuration:

@Profile("local")
@Configuration
public class LocalS3Configuration {

    @Autowired
    private S3ConfigurationProperties properties;

    @Value(("${s3.bucketName}"))
    private String bucketName;

    @Bean(destroyMethod = "shutdown")
    public AmazonS3 amazonS3() {

        final String bucketInjectedToMethod = bucketName;
        final String bucketInjectedViaProperties = properties.getBucketName();
        ...
    }
}

The annotation @Configuration registers the class as a bean and allows you to inject it in another bean.

vallim
  • 308
  • 2
  • 12
  • thansk for trying, but this causes a NPE ` java.lang.NullPointerException: null` on the line that tries to use `properties`. – David May 29 '18 at 23:15
  • Hey man, I updated the code. For me it's working fine. Did you remove the parameters in amazonS3() method? – vallim May 29 '18 at 23:41
  • Hi, I just double checked and yes I have removed the params from the method args. Both values are `null` (bucketName and properties) using this approach :( Are you also using boot 2.0.2, I feel like this used to work in 1.X but I could be wrong. – David May 29 '18 at 23:58
  • 1
    Please, take a look in this sample: https://bitbucket.org/vallim/spring-boot-configuration – vallim May 30 '18 at 00:45
  • I've upvoted your answer due to the effort you've put in. You're sample does work - however my code still doesn't. I suspect now that it's got something to do with adding spring cloud to the class path. Once I add spring-cloud-aws-context, spring-cloud-aws-autoconfigure and spring-cloud-dependencies for Finchley.RC1 + spring cloud 1.2.1.RELEASE it no longer works. Maybe they do some fancy stuff with context reloading. The message I see in the log before it goes bang is `o.s.cloud.context.scope.GenericScope : BeanFactory id` using `org.springframework.cloud.context.scope.GenericScope` – David May 30 '18 at 01:54
  • FYI, I have raised this potential bug here: https://github.com/spring-cloud/spring-cloud-commons/issues/373 – David May 30 '18 at 01:59
  • Sure David. Let me know if you can solve your problem. – vallim May 30 '18 at 02:27
  • 1
    FYI: a version of your code which highlights the issue: https://github.com/davidgoate/spring-cloud-configuration-issue – David May 30 '18 at 08:03