8

In Spring 4, using the @Value annotation, what is the right way to specify a system property as a default if a specified property does not exists?

Whereas this works for the no-default case:

@Value("${myapp.temp}")
private String tempDirectory;

This doesn't work when I need a default:

@Value("#{myapp.temp ?: systemProperties.java.io.tmpdir}")
private String tempDirectory;

Nor does this:

@Value("#{myapp.temp ?: systemProperties(java.io.tmpdir)}")
private String tempDirectory;

Both of these give me an exception at the time Spring is trying to create the bean:

org.springframework.beans.factory.BeanCreationException: Error creating bean  
     with name 'configurationService': Invocation of init method failed;
     nested exception is java.lang.NullPointerException

Can this be done?

David H
  • 1,215
  • 1
  • 14
  • 31

3 Answers3

11

I tried the following and it worked for me:

@Value("${myapp.temp:#{systemProperties['java.io.tmpdir']}}")
private String tempDirectory;

The missing parts for you I believe was not using ?: and needing the #{}. According to this answer:

${...} is the property placeholder syntax. It can only be used to dereference properties.

#{...} is SpEL syntax, which is far more capable and complex. It can also handle property placeholders, and a lot more besides.

So basically what is happening is we are telling Spring to first interpret myapp.temp as property placeholder syntax by using the ${} syntax. We then use : instead of ?: (which is called the Elvis operator) since the elvis operator only applies to Spring Expression Language expressions, not property placeholder syntax. The third part of our statement is #{systemProperties['java.io.tmpdir']} which is telling Spring to interpret the next expression as a Spring Expression and allows us to get system properties.

Community
  • 1
  • 1
Ian Dallas
  • 11,281
  • 18
  • 55
  • 80
1

Try systemProperties['java.io.tmpdir'].

It's a map, so if the key has a dot in the name, you should use [..]

Bozho
  • 554,002
  • 136
  • 1,025
  • 1,121
0

For me it only works with different property-names (being property.name.a a key with a value in my application.properties and property.name.b a Environment-Variable) like:

@Value("${property.name.a:${property.name.b}}")

The same names didn´t work for me like expected (loading the default, when the first property isn´t present), e.g.:

@Value("${property.name.a:${property.name.a}}")
jonashackt
  • 4,663
  • 1
  • 36
  • 58