Closed spring-projects-issues closed 5 years ago
Adam Berlin commented
This feature would be nice for one of our current projects. We have a little hack to get around this limitation, but we'd love to get rid of it.
Adam Berlin commented
@Adil
, I no longer have access to our client's codebase, so I cannot provide the workaround.
As I remember, we configured the list with a comma-delimited string and tokenized the string into a list. We'd definitely prefer that the standard YAML syntax for creating a list would translate into a List\@Value
.
Adam
Bob Tiernay commented
This would certainly be a welcomed addition to @Value
semantics. Please see this thread for further context:
Tongliang Liu commented
I think at least "one-level" array should be supported.
By "one-level", I mean each item in the array is of a simple type (integer, boolean, or string) and all items are of the same type in the array, for example:
oneLevelIntegerArray:
- 1
- 2
- 3
oneLevelStringArray:
- foo
- bar
Therefore, in the code, one can use the following code to bind the above YAML arrays to a List
:
@Value("${oneLevelIntegerArray}")
List<Integer> intArray;
@Value("${oneLevelStringArray}")
List<String> strArray;
But in order to bind more complex array structures, i.e. items in the array are of compound types (arrays, maps, etc..), one should use @ConfigurationProperties
.
If this is acceptable, I'll create a pull request to make this happen. It is fairly easy to make this happen.
Diego Magalhaes commented
Hey guys,
Just encountered that and got help in the gitter spring-boot channel that led me here.
Sample code:
@Data
@RefreshScope
@ConfigurationProperties(prefix = "api")
@Configuration
public class APIProperties {
private Config config;
@Data
public static class Config {
private Blocked blocked;
@Data
public static class Blocked {
List<String> blockedExtensions = new ArrayList<>();
}
}
}
Looking at :8080/env shows that ConfigurationProperties worked as expected:
applicationConfig: [classpath:/application.yml]: {
api.config.blocked.extensions[0]: ".exe",
api.config.blocked.extensions[1]: ".dll",
api.config.blocked.extensions[2]: ".bin",
api.config.blocked.extensions[3]: ".dat",
api.config.blocked.extensions[4]: ".osx"
}
now the controler:
@RestController
public class SampleServices{
private APIProperties props;
@Autowired
public ShorteningService(@Qualifier("APIProperties") APIProperties apiProperties) {
this.props = apiProperties;
}
@RequestMapping("test")
Callable<String> test() {
return () -> props.getConfig().getBlocked().getBlockedExtensions().toString();
}
}
Calling /test returns "[ ]", an empty list.
So to verify that @Value
won't work as well, let's change it for:
@RestController
public class ShorteningService {
@Value("${api.config.blocked.extensions}")
List<String> blockedExtensions;
@RequestMapping("test")
Callable<String> test() {
return () -> blockedExtensions.toString();
}
}
Error:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'api.config.blocked.extensions' in string value "${api.config.blocked.extensions}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:175)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:807)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:980)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:967)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:543)
Changing the controller code to:
@RestController
public class ShorteningService {
@Value("${api.config.blocked.extensions[0]}")
String blockedExtensions;
@RequestMapping("test")
Callable<String> test() {
return () -> blockedExtensions;
}
}
Works like charm, for the .yaml bellow, the result is ".exe"
api:
config:
blocked:
extensions:
- .exe
- .dll
- .bin
- .dat
- .osx
Stéphane Nicoll commented
Yeah well, your code there reproduces the limitation described in this issue. And this issue is not fixed so what you're experiencing is pretty much the current state yeah.
You are using Spring Boot so please do you a favour and stop using @Value
. @ConfigurationProperties
does a lot more and does support that use case.
Wenjie Zhang commented
I encountered this problem when I was using spring framework to load yaml configuration:
@Bean
public static PropertySourcesPlaceholderConfigurer properties() {
final PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
final YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("application.yml"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
return propertySourcesPlaceholderConfigurer;
}
//The property is
@Value("${platforms}")
private List<String> platforms;
I can see the properties get loaded into the PropertySources object like platforms[0], platforms[1].
However, I still get following exception:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'platforms' in string value "${platforms}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
Wenjie Zhang commented
Do you guys think making the @Value
to support regular expression is a good idea to resolve this bug?
Romero Ricardo commented
Yeah, 2017 and I'm still facing that same issue, the bug is not fixed. Do you guys think you can assign this issue to me so I get it sorted?
Stéphane Nicoll commented
Feel free to give that a try Romero, no need to be assigned for that.
Bulk closing outdated, unresolved issues. Please, reopen if still relevant.
2019 and I need this feature.
@Value
>>>>> @ConfigurationProperties
when there is only one field :
private List<String> someList;
Why I need a Class when I only have one field?
2021 and it's still needed 😉
how hard can it be ... a bit later in 2021 and still stumbling on this ...
Replace this:
foobar:
ignoredUserIds:
- 57016311
- 22588218
with this:
foobar:
ignoredUserIds: 57016311 , 22588218
You need to separate the items with a comma. After that, you can do this:
public class Foobar {
@Value("${foobar.ignoredUserIds}")
List<String> ignoredUserIds;
}
Damn, spend 2 hours to find out, that it's not I am dumb ass, it's just a "feature"!
2022 it's still needed 😀
2023 ;)
2023.11.2 Needed, looking forward to early support
2024😩
+1 for this
This just got me... The current behavior is inconsistent and totally unexpected. Further up it says
Please, reopen if still relevant.
but none of us affected (no even the OP) can reopen it because it was created by bot.
Adam Berlin opened SPR-11759 and commented
Yaml file —
Class —
Error —
Reference URL: https://github.com/spring-projects/spring-boot/issues/501
21 votes, 21 watchers