Issue
I am in the process to upgrade a project to Spring Boot 2.2.6. Following compilation errors are there wrt to binding yaml properties data to list of objects -
** Please note the project is compiling in previous version of spring-boot (2.2.1) I have been using**
java.lang.IllegalStateException: Failed to load ApplicationContext Caused by: org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'webUiApplication.States': Could not bind properties to 'WebUiApplication.States' : prefix=states, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'states.defaults' to java.util.List
application.yml
states:
defaults:
-
postal-code: AL
name: Alabama
-
postal-code: AK
name: Alaska
-
postal-code: AZ
name: Arizona
Configuration
@Data
@Configuration
@ConfigurationProperties("states")
public static class States {
private List<State> defaults;
private List<State> docVerify;
private List<State> registration;
}
POJO
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(onlyExplicitlyIncluded = true)
public class State implements ListOption {
public static final Comparator<State> DISPLAY_COMPARATOR = new ListOption.DisplayComparator<>();
@NonNull private final String postalCode;
@NonNull private final String name;
@Override
@EqualsAndHashCode.Include
public String getValue() {
return this.postalCode;
}
@Override
@ToString.Include
public String getLabel() {
return String.format("%s - %s", postalCode, name);
}
}
Have come across posts where members have received the similar issue but have not been been able to come to a solution. Looking forward to your inputs.
Solution
Refactor your code:
States:
@Data
@Configuration
@ConfigurationProperties("states")
@ToString
@NoArgsConstructor
public class States {
private List<State> defaults;
private List<State> docVerify;
private List<State> registration;
}
State:
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString(onlyExplicitlyIncluded = true)
@NoArgsConstructor
public class State {
@NonNull
private String postalCode;
@NonNull
private String name;
@EqualsAndHashCode.Include
public String getValue() {
return this.postalCode;
}
@ToString.Include
public String getLabel() {
return String.format("%s - %s", postalCode, name);
}
}
application.yaml
states:
defaults:
-
postal-code: AL
name: Alabama
-
postal-code: AK
name: Alaska
-
postal-code: AZ
name: Arizona
We need to have an empty object and then fill it with data. This is why we need no args constructor.
Answered By - Bhushan Uniyal
Answer Checked By - Mary Flores (JavaFixing Volunteer)