Monday, November 4, 2019

Spring Boot: @ConfigurationProperties vs. @Value

You must have used @Value in your spring project for reading the values from property file and you have seen people started using @ConfigurationProperties to do the same.

You are wondering what exactly is the difference ?

I will try to explain.

1. You must have seen cases where the expected value type is Integer, however we supplied String expecting it will take care of conversion and bang it failed during runtime. so basically what I wanted to convey @Value is not type safe.

2. For below example, how will you load property file in you application:

    spring:
          datasource:
                   url:
                   uname:
                   pwd:
          security:
                   uname:
                   pwd:
                   role:

you must be doing

@Value("{spring.datasource.uname}")
private String dbUsername;

@Value("{spring.security.uname}")
private String securityUname;

isn't it too verbose and confusing. What I wanted to say here is @Value is too verbose and can create confusion as you have to use fully qualified name to read the property.

3. Let's suppose you have used a particular file in 30 different places in the project and suddenly need arose to change the name :), hell lot of work and not guaranteed that all changed. imagine if the property is used in hundreds of places ? What I wanted to convey @Value doesn't give any centralized mechanism to control.
4. I am not sure everyone faced this issue or not, but I am very bad at giving names. Giving name like deviceIdNumber, bulkProcessorName etc. are good if anyone is reading but not soothing to eyes. if we write like, device-id-number or bulk_processor_name, its both soothing to eyes as well as readable. What I wanted to convey @Value is not relaxing enough to allow writing property names like it. 

That's all about shortcomings in @Value, which are supported by @ConfigurationProperties apart from many other advantages.

1. @ConfigurationProperties kind of centralized all property configuration in a single class with Type binding with Setter's where you can control type conversion instead of throwing exception and log the details:

for the above example we can have 2 location to read properties, one for Datasource and one for Security:

@ConfigurationProperties(prefix="spring.datasource")
public class DatasourceConfig {
            private String uname;
            private String pwd;
            private String url;

           //setters and getters
}

@ConfigurationProperties(prefix="spring.security")
public class SecurityConfig {
            private String uname;
            private String pwd;
            private String role

           //setters and getters
}

Wherever we wanted to use those just inject the required config bean and you are done, want to change name, change it at this one place and compiler will ensure it is getting changed at all places where it is used using getter.

2. We can validate config properties using @Validate annotation in conjunction with @ConfigurationProperties annotation. we can use JSR-303 annotation directly over the fields to do the validation.

@ConfigurationProperties(prefix="spring.datasource") @Validated public class DataSourceConfig { @NotNull private String uname; // ... getters and setters }


Feature@ConfigurationProperties@Value
Yes
No
Yes
No
SpEL evaluation
No
Yes


No comments: