183

I have the following in a Spring bean:

@Value("${myValue}")
private String value;

The value is correctly injected. However, the variable needs to be optional, it is passed in as a command line parameter (which is then added to the Spring context using a SimpleCommandLinePropertySource), and this argument will not always exist.

I have tried both the following in order to provide a default value:

@Value("${myValue:}")
@Value("${myValue:DEFAULT}")

but in each case, the default argument after the colon is injected even when there is an actual value - this appears override what Spring should inject.

What is the correct way to specify that @Value is not required?

Thanks

user1052610
  • 4,440
  • 13
  • 50
  • 101

4 Answers4

253

What is the correct way to specify that @Value is not required?

Working on the assumption that by 'not required' you mean null then...

You have correctly noted that you can supply a default value to the right of a : character. Your example was @Value("${myValue:DEFAULT}").

You are not limited to plain strings as default values. You can use SPEL expressions, and a simple SPEL expression to return null is:

@Value("${myValue:#{null}}")
Andy Brown
  • 11,766
  • 2
  • 42
  • 61
  • 1
    I have the same problem as the original poster when using Spring 5.0.12. Using the construction with `:#{null}` doesn't help, it makes it ignore the actual property value assigned in the same way. – Stefan L Sep 22 '20 at 11:50
  • Update: A small hello-world type spring non-boot application based on annotations has working `:default` handling, Properties are then also programatically accessible from the Environment if injected. Must be some extra configuration/customization causing this. – Stefan L Sep 23 '20 at 07:42
  • confusing, what is the `myValue` relates to in this case why this word? is it the same as the variable name or what, should have a complete example. – Mobigital Jun 23 '21 at 20:24
86

If you are using Java 8, you can take advantage of its java.util.Optional class. You just have to declare the variable following this way:

@Value("${myValue:#{null}}")
private Optional<String> value;

Then, you can check whether the value is defined or not in a nicer way:

if (value.isPresent()) {
    // do something cool
}

Hope it helps!

haggisandchips
  • 523
  • 2
  • 11
alonso_50
  • 1,442
  • 13
  • 16
  • 8
    According to intelliJ idea. It's not a best practice to use `Optional` types in class fields. – Fırat Küçük Aug 30 '18 at 12:31
  • 4
    You do this and it throws a NPE. `value` is null. – aatk Dec 07 '18 at 14:51
  • 1
    @aatk It seems that the issue you describe has been fixed at least since 4.3.13. I get no trouble using the described declaration. Though it's better to just use a nullable value: https://blog.joda.org/2015/08/java-se-8-optional-pragmatic-approach.html – Torben Apr 02 '19 at 11:22
  • 2
    "According to intelliJ idea. It's not a best practice to use Optional types in class fields." what is wrong about using Optional as instance variable? only that is relatively long lived compared to when used in getters... and such field should be marked Transient for serialization? – Andrey M. Stepanov May 16 '19 at 14:59
6

If you want to make the configuration property optional just pass an empty string like this:

@Value("${app.optional.value:}")
Pritam Banerjee
  • 17,953
  • 10
  • 93
  • 108
3

I guess you are you using multiple context:property-placeholder/ declarations?

If so, 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
  • 1,529
  • 13
  • 20