This is my project structure
- src
- main
- java
- mypackage
- resources
- config
application.yml
and i have this in application.yml
document:
templates:
filetypes:
- elem1
- elem2
- elem3
- elem4
hello:
test: "hello"
in my Endpoint i have the following
@Value("${document.templates.filetypes}")
List<String> templatesFileTypes;
@Value("${document.hello.test}")
String hello;
in any function i can access something like System.out.println(hello)
and its perfectly working
but for the fileTypes its not even compiling and i receive this error :
Error creating bean with name 'configurationEndPoint': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'document.templates.filetypes' in value "${document.templates.filetypes}"
Searched alot and every solution i could find was that pointing to the write application.yml/application.xml file, which is invalid in my case since i can read the other test String but not the array;
i tried String[]
i tried ArrayList<String>
but i can't get it to work
One way is to pass the elements as delimited list. Typically we have used comma and it works out of the box for String arrays. To use a List, then you will need to set the delimiter using Spring SPEL format... see example below.
document:
templates:
filetypes:elem1,elem2,elem3
-
@Value("${document.templates.filetypes:}")
private String[] array;
@Value("#{'${document.templates.filetypes}'.split(',')}")
private List<String> list;
@PostConstruct
void testList(){
list.stream().forEach(System.out::println);
for (String a : array) {
System.out.println(a);
}
}
The other solution provided by @Jose Martinez would work but not really as clear as needed, because its reading document.templates.filetypes
as a String and then splitting it into array of Strings; thus i am adding my solution to this,
1- Create new class FileTypesProperties
@Configuration
@ConfigurationProperties(prefix = "document.templates")
public class FileTypesConfig {
private List<String> fileTypes;
public List<String> getFileTypes() {
return fileTypes;
}
public void setFileTypes(List<String> fileTypes) {
this.fileTypes = fileTypes;
}
}
2- Create service and inject the previous class
@Service
public class FileTypeService {
private final List<String> fileTypes;
@Autowired
public FileTypeService(FileTypesConfig fileTypesConfig){
this.fileTypes = fileTypesConfig.getFileTypes();
}
public List<String> getFileTypes(){
return this.fileTypes;
}
}
3- In your end point simply autowire and call the previous service
@RestController
public class ConfigurationEndPoint {
@Autowired
FileTypeService fileTypeService;
@GetMapping("/api/filetypes")
@ResponseBody
public ResponseEntity<List<String>> getDocumentTemplatesFileTypes(){
return ResponseEntity.ok(fileTypeService.getFileTypes());
}
}
And then your yaml file can be a real array
document:
templates:
file-types:
- elem1
- elem2
- elem3
- elem4
I believe this is cleaner than splitting a String into smaller strings into an array, hope this will help out someone.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With