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.

+3


source to share


1 answer


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 .

+1


source







All Articles