Spring-boot has a very powerful and flexible mechanism to bind configuration properties to Java beans using @ConfigurationProperties. I use this to bind the properties for Jakarta Mail:

@Named
@ConfigurationProperties("mail.mime")
public class MailMimeConfigProperties {
  private final Address address = new Address();
  private final Parameters parameters = new Parameters();
  private final DecodeParameters decodeparameters = new DecodeParameters();
  private final DecodeText decodetext = new DecodeText();

  public static abstract class Node {
    private boolean strict;
    public boolean isStrict() { return this.strict; }
    public void setStrict(boolean strict) { this.strict = strict; }
  }
  public static class Address extends Node {}
  public static class Parameters extends Node {}
  public static class DecodeParameters extends Node {}
  public static class DecodeText extends Node {}
}

And with this I can now bind the following properties to my configuration beans:

mail.mime.decodeparameters.strict=false
mail.mime.parameters.strict=false
mail.mime.address.strict=false
mail.mime.decodetext.strict=false

The actual problem now is that Jakarta Mail also has properties that I mapped as kind of "prefix" in spring boot such as:

mail.mime.decodeparameters=...

This seems impossible to solve with spring-boot @ConfigurationProperties in a structured way as mail.mime.decodeparameters is bound to MailMimeConfigProperties.DecodeParameters so mail.mime.decodeparameters.strict can be bound to MailMimeConfigProperties.DecodeParameters.strict.

What I would love to have would be some annotation that allows me to annotate a property and map it to the top-level prefix of the configuration bean.

@Named
@ConfigurationProperties("mail.mime")
public class MailMimeConfigProperties {
  private final Address address = new Address();
  private final Parameters parameters = new Parameters();
  private final DecodeParameters decodeparameters = new DecodeParameters();
  private final DecodeText decodetext = new DecodeText();

  public static abstract class Node {
    private boolean strict;
    @PrefixValue private String value; // something like this !!!
    public boolean isStrict() { return this.strict; }
    public void setStrict(boolean strict) { this.strict = strict; }
    public String getValue() { return this.value; }
    public void setValue(String value) { this.value = value; }
  }
  public static class Address extends Node {}
  public static class Parameters extends Node {}
  public static class DecodeParameters extends Node {}
  public static class DecodeText extends Node {}
}

NOTE: This is just a suggestion. Instead of @PrefixValue it may also make sense to add @PropertyName("") that allows to override the property name mapping taken by default from the code and allowing the empty String to use the name of the prefix (then without a dot appended) but could also be used for other usecases.

Then I would expect being able to set mailMimeConfigProperties.decodeparameters.value as

mail.mime.decodeparameters=...

instead of

mail.mime.decodeparameters.value=...

I have faced this problem many times before but there I was the "owner" defining the custom configuration properties and could simply change my design. But in a case like with Jakarta Mail where the property names are defined by a standard, I have to follow the standard and cannot redefine the property names. I searched really deeply for an existing solution in spring-boot to this problem but IMHO this cannot be solved (except for losing the entire typing and IDE support by mapping all properties as a single Map<String, String>).

Comment From: philwebb

Thanks for the suggestion, but this level of complexity isn't something we'd want to support in the binder. We've actually had problems in the past where we have property overlaps and they have been quite problematic. This feature would also break configuration properties metadata and IDE support.

Thanks anyway for the suggestion.

Comment From: hohwille

Thanks for the feedback. Will then fall back to plain Map.