Monday, 11 December 2017

Understanding @value annotation in Spring

Background

Spring framework is based on the concept of dependency injection -
And while doing so you may need to set the values of some variables in your Spring application based on the environment or abstract it out to a properties file. For eg.  base URL of your application or username/password and other database connection details etc. Basically properties that may vary in each environment.

@value annotation is used for same reason. To set value of a variable from a properties file or environment variables. We will see the usage of this annotation next.


Setup

Before you start using @value annotation you need to setup the properties file from which your configured values can be read. To set of properties file you can use @PropertySource annotation in your configuration class. Example -

package com.osfg.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

/**
 * 
 * @author athakur
 * Root applciation context
 * Services and data sources should go here - common to all web application contexts
 */
@Configuration
@ComponentScan({ "com.osfg" })
@PropertySource(value = { "classpath:com/osfg/resources/spring-props.properties" })
public class RootApplicationConfig {

}



Source : https://github.com/aniket91/SpringFeaturesDemo/blob/master/src/com/osfg/config/RootApplicationConfig.java

You do not need entirely need the properties file. You can also set values from environment variables. We will see this part next.



Your properties file will have simple key=value content. Eg.
  • adminName=athakur
See https://github.com/aniket91/SpringFeaturesDemo/blob/master/src/com/osfg/resources/spring-props.properties


Usage

You can use this as follows -

package com.osfg.models;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import lombok.Data;

@Component
@Data
public class Properties {
    
    @Value("${adminName}")
    String adminName;
}



Above usage will automatically inject values from your property file into your Java model class as you see above. Now you are free to inject  Properties class anywhere in your Spring project and access the variable.




@Controller
public class TestController {
    
    @Autowired
    Properties properties;
    
    
    Logger logger = LoggerFactory.getLogger(TestController.class);

    @RequestMapping(value="/test/{data}",method=RequestMethod.GET)
    public String test(@PathVariable String data, ModelMap model,
            HttpServletRequest request, HttpServletResponse response) {
        logger.debug("Received request for test controller with data : {}", data);
        model.put("adminName", properties.getAdminName());
        model.put("dara", data);
        return "test";
        
    }    
    
}

That's the basic usage.

NOTE : If same property is present in System property (environment variables) and also in property file then the System property takes preference.


You can also directly give the value of the variable. Eg.

    @Value("athakur")
    String adminName;
}



You can also give default value in the @value annotation.


@Data
public class Properties {
    @Value("${adminName:athakur}")
    String adminName;
}


So if  adminName is not defined in system properties or in properties file default value specified after ":" is picked up and used.

 Advanced usage

You can also use advanced usage of this annotation as follows-

private String adminName;

@Value("#{config['adminName'] ?: 'athakur'}")
private String adminName;

@Value("#{someBean.adminName ?: 'athakur'}")
private String adminName;

Using above you can choose to lookup system properties or config file or value in some predefined bean. This use Elvis operator in Spring Expression Language (SpEL).


You can see a sample demo in my github repo mentioned in Related Links section below -

Related Links



t> UA-39527780-1 back to top