Immutable @ConfigurationProperties

RJo picture RJo · Oct 1, 2014 · Viewed 18.9k times · Source

Is it possible to have immutable (final) fields with Spring Boot's @ConfigurationProperties annotation? Example below

@ConfigurationProperties(prefix = "example")
public final class MyProps {

  private final String neededProperty;

  public MyProps(String neededProperty) {
    this.neededProperty = neededProperty;
  }

  public String getNeededProperty() { .. }
}

Approaches I've tried so far:

  1. Creating a @Bean of the MyProps class with two constructors
    • Providing two constructors: empty and with neededProperty argument
    • The bean is created with new MyProps()
    • Results in the field being null
  2. Using @ComponentScan and @Component to provide the MyProps bean.
    • Results in BeanInstantiationException -> NoSuchMethodException: MyProps.<init>()

The only way I have got it working is by providing getter/setter for each non-final field.

Answer

davidxxx picture davidxxx · Jul 24, 2019

From Spring Boot 2.2, it is at last possible to define an immutable class decorated with @ConfigurationProperties.
The documentation shows an example.
You just need to declare a constructor with the fields to bind (instead of the setter way) and to add the @ConstructorBinding annotation at the class level to indicate that constructor binding should be used.
So your actual code without any setter is now fine :

@ConstructorBinding
@ConfigurationProperties(prefix = "example")
public final class MyProps {

  private final String neededProperty;

  public MyProps(String neededProperty) {
    this.neededProperty = neededProperty;
  }

  public String getNeededProperty() { .. }
}