Spring Inject Values with @ConfigurationProperties and @Value

How to inject values from yaml and set default values if a property is not defined in the yaml props file? Is using both ConfigurationProperties and Value like below a good use? If not how else can we achieve it?

Properties file

app:
    prop1: test
    prop2: true
    map:
       key1: value1
       key2: value2

Java class:

@Data
@Validated
@ConfigurationProperties("app")
public class properties {
   private String prop1;

  @Value("${app.prop2:default}")
  private Boolean prop2;

  @NestedConfigurationProperty
  @NotNull
  private Map<String,String> prop3;
}

Solution 1:

Is using both ConfigurationProperties and Value like below a good use

No. @ConfigurationProperties indicates to spring that it should bind the java fields based on their name to some matching properties. However to achieve that spring requires that the class that has this annotation must be a spring bean (proxy class). So you have to use it together with either @Configuraiton or @Component or some other annotation that creates a spring bean for this class.

There is also some other functionality available where you can use another annotation @EnableConfigurationProperties(properties.class) on some other spring bean (not the current class that has the @ConfigurationProperties annotation)

Most common is that you use the @Configuration and then spring will be able to create a spring bean (proxy of this class) and then bind the values that you expect on the fields that you have.

Since you already have the @ConfigurationProperties("app"), then the property with the name prop2 will be bound with the application property app.prop2

@Data
@Validated
@Configuration <---------------
@ConfigurationProperties("app")
public class properties {
   private String prop1;

   private Boolean prop2;

  @NestedConfigurationProperty
  @NotNull
  private Map<String,String> prop3;
}

If your problem is the default values in case the properties do not exist at all in application.properties then you can just initialize those java fields with some values.

@Data
@Validated
@Configuration <---------------
@ConfigurationProperties("app")
public class properties {
   private String prop1 = "default";

   private Boolean prop2 = false;

  @NestedConfigurationProperty
  @NotNull
  private Map<String,String> prop3;
}