62

Initially, I have the following spec:

@Value("#{props.isFPL}")
private boolean isFPL=false;

This works fine correctly getting the value from the property file:

isFPL = true

However, the following expression with default results in the error:

@Value("#{props.isFPL:false}")
private boolean isFPL=false;

Expression parsing failed; nested exception is org.springframework.expression.spel.SpelParseException: EL1041E:(pos 28): After parsing a valid expression, there is still more data in the expression: 'colon(:)'

I also tried to use $ instead of #.

@Value("${props.isFPL:true}")
private boolean isFPL=false;

Then the default value in annotation works fine but I did not get the correct value from the Properties file:

Alex
  • 7,007
  • 18
  • 69
  • 114
  • 5
    With `#{}` it is an expression, with `${}` it is a placeholder for a value. The first expression you use will call a method/attribute on a bean called props, the one with the placeholder will try to locate a property named `props.isFPL` in the `Environment`. You should use the latter and you are probably loading your properties in the wrong way. – M. Deinum Nov 13 '14 at 19:18
  • Thank you. If I load properties in the wrong way why #{} picks up the correct value? – Alex Nov 13 '14 at 19:22
  • Because that is an expression not a placeholder. They are both evaluated in completely different ways. – M. Deinum Nov 13 '14 at 19:36

8 Answers8

62

Try with $ as follows:

@Value("${props.isFPL:true}")
private boolean isFPL=false;

Also make sure you set the ignore-resource-no-found to true so that if the property file is missing, the default value will be taken.

Place the following in the context file if using XML based configuration:

<context:property-placeholder ignore-resource-not-found="true"/>

If using Java configurations:

 @Bean
 public static PropertySourcesPlaceholderConfigurer   propertySourcesPlaceholderConfigurer() {
     PropertySourcesPlaceholderConfigurer p =  new PropertySourcesPlaceholderConfigurer();
     p.setIgnoreResourceNotFound(true);

    return p;
 }
informatik01
  • 16,038
  • 10
  • 74
  • 104
shi9
  • 638
  • 6
  • 5
19

For int type variable:

@Value("${my.int.config: #{100}}")
int myIntConfig;

Note: there is no space before the colon, but an extra space after the colon.

Kevin Liu
  • 667
  • 5
  • 14
6

The exact answer of your question depends on the type of the parameter.

for 'String' parameters, your sample code works fine:

@Value("#{props.string.fpl:test}")
private String fpl = "test";

for other types (like boolean in your question) it should be written in this way:

@Value("${props.boolean.isFPL:#{false}}")
private boolean isFPL = false;

or for 'Integers':

@Value("${props.integer.fpl:#{20}}")
Dharman
  • 30,962
  • 25
  • 85
  • 135
Majid Roustaei
  • 1,556
  • 1
  • 20
  • 39
3

Does your Spring application context file contains more than one propertyPlaceholder beans like below:

<context:property-placeholder ignore-resource-not-found="true" ignore-unresolvable="true" location="classpath*:/*.local.properties" />
<context:property-placeholder location="classpath:/config.properties" />

If so, then property lookup for: props.isFPL will only take place for the first property file (.local.properties), if property not found, the default value (true) will take effect and the second property file (config.properties) is effectively ignored for this property.

Kevin
  • 41
  • 3
  • This is a known issue since 2012, but not fixed, apparently due to both lack of interest and no clean way of fixing it. See https://github.com/spring-projects/spring-framework/issues/14623 for discussion and some ways to work around it. It's explained in an understandable way by http://www.michelschudel.nl/wp/2017/01/25/beware-of-multiple-spring-propertyplaceholderconfigurers-and-default-values/ – Stefan L Sep 23 '20 at 09:26
3

For a String you can default to null like so:

public UrlTester(@Value("${testUrl:}") String url) {
    this.url = url;
}
Dave Richardson
  • 4,880
  • 7
  • 32
  • 47
2

Depends on how you're loading your properties, if you use something like

<context:property-placeholder location="classpath*:META-INF/spring/*.properties" />

Then @Value should look like

@Value("${isFPL:true}")
Mike Summers
  • 2,139
  • 3
  • 27
  • 57
0

If the default is a string specify like this:

@Value("${my.string.config: #{'Default config value'}}")
String myIntConfig;
Marinos An
  • 9,481
  • 6
  • 63
  • 96
-4

This way of defining defaults works only if we write "value=..." in the @Value annotation. e.g.

Does not work : @Value("${testUrl:some-url}" // This will always set "some-url" no matter what you do in the config file.

Works : @Value(value = "${testUrl:some-url}" // This will set "some-url" only if testUrl property is missing in the config file.

Kislay Verma
  • 59
  • 1
  • 10