Version:5.1.13.RELEASE There are two resolvers, one resolve value from Apollo, another resolver resolve value from file of my project. A Bean with a @Value field, the field value is existed in file of my project and not in Apollo.
I get a java.lang.IllegalArgumentException when I run my project.
java.lang.IllegalArgumentException: Could not resolve placeholder 'verifyCode.bVariableFont' in value "${verifyCode.bVariableFont}"
A bean:
@Service
public class VerifyCodeConfig {
@Value(value = "${verifyCode.bVariableFont}")
private String bVariableFont;
public String getbVariableFont() {
return bVariableFont;
}
}
A resolver resolve value from file of my project:
@Configuration
public class PropertiesConfiguration {
@Bean
@Order(0)
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer =
new PropertySourcesPlaceholderConfigurer();
List<Resource> resources = new ArrayList<>();
resources.add(new ClassPathResource("META-INF/res/application-verify-code.properties"));
propertySourcesPlaceholderConfigurer.setLocations(resources.toArray(new Resource[] {}));
propertySourcesPlaceholderConfigurer.setIgnoreResourceNotFound(true);
return propertySourcesPlaceholderConfigurer;
}
}
Extract from AbstractBeanFactory:
@Override
@Nullable
public String resolveEmbeddedValue(@Nullable String value) {
if (value == null) {
return null;
}
String result = value;
for (StringValueResolver resolver : this.embeddedValueResolvers) {
result = resolver.resolveStringValue(result);
if (result == null) {
return null;
}
}
return result;
}
I think a solution should be to continue the resolving chain, if an embeddedValueResolver resolves the value to null, and all embeddedValueResolver resolves the value to null,then return null;
Possible Solution:
Extract from AbstractBeanFactory:
@Override
@Nullable
public String resolveEmbeddedValue(@Nullable String value) {
if (value == null) {
return null;
}
String result = null;
for (StringValueResolver resolver : this.embeddedValueResolvers) {
result = resolver.resolveStringValue(value);
if (result != null) {
return result;
}
}
return result;
}
Comment From: snicoll
I think a solution should be to continue the resolving chain, if an embeddedValueResolver resolves the value to null, and all embeddedValueResolver resolves the value to null,then return null;
Unfortunately, that's not the issue here. The reason why the code is designed this way is to allow resolver to be chained if necessary, resolving specific placeholders. If a given resolver cannot resolve a value, it should return the original String as-is. If it returns null
, it means it was able to resolve the value - with the result being null
and therefore not subject for further resolution steps
The problem seems rather that the same placeholder syntax is used for both resolvers there. To ignore an unresolvable name within a known placeholder syntax, PropertySourcesPlaceholderConfigurer
needs a setIgnoreUnresolvablePlaceholders(true)
setting.