A guide to @Value in Spring Boot
The @Value annotation is the quickest way to access the application.properties values in Spring Boot. It comes with some powerful features which we will explore in this tutorial.
@Value Annotation in Spring Boot
The @value annotation is the easiest way to inject values into primitive fields. To demo this, let’s set up an application with some sample property values.
greeting.message=Hello
thirdparty.endpoint=http://api.example.com/v3
thirdparty.retry.count=3
thirdparty.retry.delay=10000
Code language: JavaScript (javascript)
We can access all of these properties values in our spring boot application as shown below.
@Service
public class SampleService {
@Value("${greeting.message}")
private String message;
@Value("${thirdparty.endpoint}")
private String apiEndpoint;
@Value("${thirdparty.retry}")
private Integer numberOfRetries;
@Value("${thirdparty.retry.delay}")
private Long retryDelay;
// use the values in your methods
}
Code language: PHP (php)
As you can see, we can create as many fields as we go. Even though field injection is usually not recommended, This approach is an easy fix.
Advanced usages of @Value annotation
Even though the above approach would be sufficient, you can also use @Value annotation in the following use cases.
Property values as arrays
If you have defined a comma-separated list of values, you can @Value them into an array.
app.menu.categories=sides,beverages,dessert
@Value("${app.menu.categories}")
private String[] categories;
Code language: CSS (css)
The same works for collections as well. For example, you can assign the values from the properties file into a List or Set. Spring Boot @Value annotation will take care of the injection for you.
@Value("${app.menu.categories}")
private List<String> categoriesList;
@Value("${app.menu.categories}")
private Set<String> categoriesSet;
@Value("${app.menu.categories}")
private Set<String> categoriesCollection;
Code language: CSS (css)
Note that the Set and Collection behave the same way (remove duplicates in the list of values).
Property values with time units and durations
You could also read values directly into Duration. For instance, take a look at this property entry.
thirdparty.retry.delay=10S
If you define the @Value annotation for a Duration field, Spring will inject an appropriate value.
@Value("${thirdparty.retry.delay}")
private Duration retryDelay;
Code language: CSS (css)
Reading properties values as ENUM
If the value matches the ENUM.name(), then you can directly assign the values into appropriate fields.
For example, if you have an enum like below, then you could directly read values as ENUMs.
public enum Menu {
DESSERT,
SIDES,
BEVERAGES
}
Code language: PHP (php)
app.menu.discounted= DESSERT
With the above property value, you can access the results as shown here.
@Value("${app.menu.discounted}")
private Menu discounted;
Code language: CSS (css)
This approach is useful when you expect only a certain set of values for that field. Also, This approach works with the arrays of enums as well.
Spring Boot @Value with Default values
With all the above implementations, if you fail to provide an entry in the application.properties file, then you would get a “Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder ‘XXX’ in value “${XXX}”“.
To avoid this, you should always provide a default value when possible. To do that, you need to write the annotation in a slightly different way.
For example, if you expect a default greeting message, then you can do as shown here.
@Value("${greeting.message:Hello World}")
private String message;
Code language: CSS (css)
In this case, if the “greeting.message” is not available in the application.properties or any other properties source, then Spring will use the fallback value “Hello World” instead.
Advanced use cases with @Value and SpEL
So far every example used a ${…} pattern in the @Value annotations. These are called SpEL(Spring Expression Language) expressions. Now we are going to look at some advanced usages in conjunction with SpEL.
Injecting maps
With the help of Key-value parsing from SpEL, You can define a Map in one of the properties keys and use inject them like this.
some.data={key1:'value1',key2:'value2'}
Code language: JavaScript (javascript)
And you can read these values in to map using @Value annotation like this.
@Value("#{${some.data}}")
private Map<String,String> valueMap;
Code language: JavaScript (javascript)
Note that the expression here is at two levels. The inner level gets a string value from the property. That is then parsed by the # operator into a map.
Accessing Beans
You could call bean methods within the @Value expression through SpEL.
@Value("#{someService.someMethod()}")
private String valueFromAnotherBean;
Code language: CSS (css)
This way, You could call other beans or bean.fields to populate values. For this to work, The other bean must be initialized.
@Value with Constructor injection in Spring boot
Spring boot allows @Value annotation in their constructor injection as well. For example, if you need to use values from the application.properties into a constructor, then you can use @Value annotation against the constructor parameter.
@Service
public class SampleService
private String greeting;
public SampleService(@Value("${greeting.message:Greetings People!}") String greeting){
this.greeting = greeting;
}
Code language: JavaScript (javascript)
This approach allows the value to be set through a constructor. Also, you don’t need to use @Autowired with Spring 5.
We learned how to use @Value annotation in various ways. If you liked this tutorial You might also find the below topics relevant.
You could also find various examples at https://github.com/springhow.