Reputation: 2019
This is in my application.yml
translations:
en:
title: 'english'
description: 'english text'
fr:
title: 'french'
description: 'french text'
de:
title: 'german'
description: 'french text'
codes:
GB:
# I am assuming that en here will have an object with both title and description properties
en: ${translations.en}
CA:
en: ${translations.en}
fr: ${translations.fr}
DE:
en: ${translations.en}
fr: ${translations.fr}
de: ${translations.de}
Now consider this piece of code(removed unnecessary getters etc and also using project lombok for brevity)
@SpringBootApplication
public class DemoApplication implements CommandLineRunner {
// Inner classes, but these can be outside as well
@ConfigurationProperties
@Getter
@Component
class Config {
Map<String, Map<String, LanguageDTO>> codes;
}
@Data
@AllArgsConstructor
class LanguageDTO {
String title;
String description;
}
@Autowired
Config config;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
// Getting error on this line below
Map<String, Map<String, LanguageDTO>> codes = config.getCodes();
}
}
Now when I start the app, I am getting an error like this:
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'codes.gb.en' to com.example.demo.DemoApplication$LanguageDTO:
Property: codes.gb.en
Value: ${translations.en}
Origin: class path resource [application.yml]:24:9
Reason: No converter found capable of converting from type [java.lang.String] to type [com.example.demo.DemoApplication$LanguageDTO]
Action:
Update your application's configuration
What I want?
I want to be able to read codes as a Map<String, Map<String, LanguageDTO>
. That is, I should be able to do config.getCodes().get("GB").get("en")
--> which should in turn have a data type of LanguageDTO
.
Upvotes: 2
Views: 732
Reputation: 10681
I don't think it's doable: Spring supports only simple property placeholders inside the application.yaml file (as far as I know). What you could do though, is leveraging YAML format built-in functionality, anchors and aliases:
translations:
en: &en
title: 'english'
description: 'english text'
fr: &fr
title: 'french'
description: 'french text'
de: &de
title: 'german'
description: 'french text'
codes:
GB:
en: *en
CA:
en: *en
fr: *fr
DE:
en: *en
fr: *fr
de: *de
For it to work, the
LanguageDTO
class needs to have setters and a default constructor. @AllArgsConstructor won't work. Alternatively you might try to get it work in conjunction with constructor binding, although I'm not sure if it's possible.
Upvotes: 1