Spring Boot initialize new instance for nested configuration binding when there are no corresponding nested key/value pairs in application.properties

isuru89 :

I have a configuration class like below. All of fields in the inner class OptionalServiceConfigs has a default value as annotated using @Value as shown in below.

Sometimes in my application.properties file, it does not have a single service prefixed property. In that case, we want to have loaded an OptionalServiceConfigs instance with its default field values.

@Configuration
@ConfigurationProperties(prefix = "myconf")
public class MyConfigs {

   // ... rest of my configs

   @Value("${service:?????}") // what to put here, or can I?
   private OptionalServiceConfigs service;   // this is null

   // In this class all fields have a default value.
   public static class OptionalServiceConfigs {

       @Value("${mode:local}")
       private String mode;

       @Value("${timeout:30000}")
       private long timeout;

       // ... rest of getter and setters
   }

   // ... rest of getter and setters
}

But unfortunately, the service field is null when it is accessed using its getter method. Because spring boot does not initialize an instance of it when there is no property keys found with prefixed myconf.service.* in my application.properties file.

Question:

How can I make service field to initialize to a new instance along with its specified default field values when there are no corresponding prefixed keys in properties file?

I can't imagine a value to put in annotation @Value("${service:?????}") for service field. Nothing works, tried, @Value("${service:}") or @Value("${service:new")

isuru89 :

Based on @M. Deinum's advice, did some changes to configuration class. I am a newbie to Spring and it seems I have misunderstood how Spring works behind-the-scenes.

  1. First I removed all @Value annotation from inner class (i.e. OptionalServiceConfigs), and as well as service field in MyConfigs class.
  2. Then, initialized all inner class fields with their default values inline.
  3. In the constructor of MyConfigs, I initialized a new instance of OptionalServiceConfigs for the field service.

By doing this, whenever there is no service related keys in my application.properties a new instance has already been created with default values.

When there is/are service related key/s, then Spring does override my default values to the specified values in application.properties only the field(s) I've specified.

I believe from Spring perspective that there is no way it can know in advance that a referencing field (i.e. service field) would be related to the configurations, when none of its keys exist in the configuration file. That must be the reason why Spring does not initialize it. Fair enough.

Complete solution:

@Configuration
@ConfigurationProperties(prefix = "myconf")
public class MyConfigs {

   // ... rest of my configs

   private OptionalServiceConfigs service;

   public static class OptionalServiceConfigs {

       private String mode = "local";

       private long timeout = 30000L;

       // ... rest of getter and setters
   }

   public MyConfigs() {
      service = new OptionalServiceConfigs();
   }

   // ... rest of getter and setters
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=106235&siteId=1