Can't bind map to complex key from spring boot yaml using @ConfigurationProperties
I am trying to unmount a map using a complex key from spring yaml config file in java.util.Map using spring boot and @ConfigurationProperties . There are many examples about cards with simple keys like
map:
key: value
or even cards with a simple key and complex value, like
map:
key: {firstPartOfComplexValue: alpha, secondPartOfComplexValue: beta}
I've tested both of the above examples - works well.
Now I need a complex key on the map:
map:
? {firstPartOfAKey: someValue1, secondPartOfAKey: someValue2}: value
And the result of this unmarshalling is an empty map. Could you tell me what I am doing wrong? thanks in advance
There is my code:
application.yml
custom:
users:
? {firstPartOfAKey: hello, secondPartOfAKey: world} : tom
bean for route cancellation
@Component
@ConfigurationProperties("custom")
public class MyBean {
private Map<Key, String> users = new HashMap<>();
public Map<Key, String> getUsers() {
return users;
}
public void setUsers(Map<Key, String> users) {
this.users = users;
}
@Override
public String toString() {
return users.toString();
}
public static class Key {
private String firstPartOfAKey;
private String secondPartOfAKey;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Key key = (Key) o;
return Objects.equals(firstPartOfAKey, key.firstPartOfAKey) &&
Objects.equals(secondPartOfAKey, key.secondPartOfAKey);
}
@Override
public int hashCode() {
return Objects.hash(firstPartOfAKey, secondPartOfAKey);
}
public String getFirstPartOfAKey() {
return firstPartOfAKey;
}
public void setFirstPartOfAKey(String firstPartOfAKey) {
this.firstPartOfAKey = firstPartOfAKey;
}
public String getSecondPartOfAKey() {
return secondPartOfAKey;
}
public void setSecondPartOfAKey(String secondPartOfAKey) {
this.secondPartOfAKey = secondPartOfAKey;
}
@Override
public String toString() {
return String.format("firsPartOfKey: '%s', secondPartOfKey: '%s'", firstPartOfAKey, secondPartOfAKey);
}
}
}
java config (it's empty)
@Configuration
@ComponentScan(basePackages = {"com"})
@EnableAutoConfiguration
@EnableConfigurationProperties
public class Config {
}
unit test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Config.class})
public class TestProps {
@Autowired
private MyBean myBean;
@Test
public void testYamlPropsLoad() {
System.out.println(myBean);
}
}
Testing prints '{}' for a map with a complex key. Other cards (with simple keys) work well.
source to share
It seems that the binding of yours MyBean
is not handled at all, if your test is executed without any exceptions, there should usually be an exception, e.g .:
Target {} binding error:
Property: custom.null Value: {{firstPartOfAKey = hello, secondPartOfAKey = world} = tom} Cause: Could not convert property value of type 'java.lang.String' to required type 'com.example.MyBean $ Key' for property " null "; nested exception java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'com.example.MyBean $ Key': no โโcomparable editors or conversion strategy
Obviously, the parser cannot handle complex keys and interprets key null
and value {firstPartOfAKey=hello, secondPartOfAKey=world}=tom
.
Perhaps you can find another way to handle your config by doing a custom editor / converter .
source to share