How do I go about representing Map<String, List<String>>
in a Spring .properties
file?
To give an example scenario of the problem, I'd like to be able to add the following to a @Component
:
@Autowired
private Map<String, List<String>> animalHabitats;
...and inject into it the following animal habitat info from a .properties
file:
Spring does this out of the box, but arranging it is not all that intuitive.
.properties
file:In this example we'll create a habitats.properties
in /src/main/resources
:
my-habitats={ \
home: {'dog', 'cat', 'goldfish'}, \
farm: {'sheep', 'goat'}, \
zoo: {'lion', 'giraffe'} \
}
@Configuration
class:@Configuration
@PropertySource("classpath:/habitats.properties")
public class HabitatConfiguration {
@Bean
public Map<String, List<String>> getHabitatConfig(@Value("#{${my-habitats}}") Map<String, List<String>> habitats) {
return habitats;
}
}
@Component
class:@Component
public class HabitatValidator {
private final Map<String, List<String>> habitats;
@Autowired
public HabitatValidator(Map<String, List<String>> habitats) {
this.habitats = habitats;
}
public void validateInput(String habitat, String animal) throws InvalidAnimalHabitatCombinationException {
if (!habitats.get(habitat).contains(animal)) {
throw new InvalidAnimalHabitatCombinationException("You won't find a " + animal + " in a " + habitat);
}
}
}
That's it :)
For a little more type safety you could replace the Strings with enums. Just make sure that the values in the properties file line up with the enum entries. E.g.
Without changing the contents of the habitats.properties
file, add the following two enums:
public enum Habitat {
home, farm, zoo
}
public enum Animal {
dog, cat, goldfish, sheep, goat, lion, giraffe
}
Then change the bean method in the configuration class to:
@Bean
public Map<Habitat, List<Animal>> getHabitatConfig(@Value("#{${my-habitats}}") Map<Habitat, List<Animal>> habitats) {
return habitats;
}
And inject it into the component like this:
private final Map<Habitat, List<Animal>> habitats;
@Autowired
public HabitatValidator(Map<Habitat, List<Animal>> habitats) {
this.habitats = habitats;
}