I am creating @ConfigurationProperties
classes for use in a Spring Boot application. We want to have immutable classes so we have no setters and we are using the @ConstructorBinding
annotation. Within the constructor we are using the @DefaultValue
annotation to set default property values. With simple property types this works fine. However, if the property is a Map I cannot find any way to use this annotation to set the default value. Essentially, I want to know how to put in below:
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
import java.util.Map;
@ConfigurationProperties(prefix = "props")
@ConstructorBinding
@Getter
public class MyProperties {
private final Map<String, String> mapProperty;
public MyProperties(@DefaultValue(<PLACEHOLDER>) Map<String, String> mapProperty) {
this.mapProperty = mapProperty;
}
}
I have tried using syntax similar to what would be required to populate a list, e.g. @DefaultValue(value = {"a=b", "c=d"})
or @DefaultValue(value = {"a:b", "c:d"})
. I have also tried using the Spring Expression Language for inline maps, e.g. @DefaultValue("{a:'b'}")
. None of these approaches seem to work, Spring fails to bind the value to the properties object and the object is not created.
Is it not possible to use this annotation to set the default value for a Map?
I know that I could perform a null check in the constructor and assign a default map. I don't want to use that approach because we are using the generated metadata for documentation.
you need define StringToMapConverter
@Component
@ConfigurationPropertiesBinding
public class StringToMapConverter implements Converter<String, Map<String,String>>{
private final ObjectMapper objectMapper = new ObjectMapper();
@Override
public Map<String, String> convert(String source) {
try {
return objectMapper.readValue(source,new TypeReference<>(){});
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}