Advertisement
Advertisement


Reading a List from properties file and load with spring annotation @Value


Question

I want to have a list of values in a .properties file, ie:

my.list.of.strings=ABC,CDE,EFG

And to load it in my class directly, ie:

@Value("${my.list.of.strings}")
private List<String> myList;

As I understand, an alternative of doing this is to have it in the spring config file, and load it as a bean reference (correct me if I'm wrong), ie

<bean name="list">
 <list>
  <value>ABC</value>
  <value>CDE</value>
  <value>EFG</value>
 </list>
</bean>

But is there any way of doing this? using a .properties file? ps: I would like to do this with out any custom code if possible.

2019/04/18
1
248
4/18/2019 3:35:46 AM

Accepted Answer

Using Spring EL:

@Value("#{'${my.list.of.strings}'.split(',')}") 
private List<String> myList;

Assuming your properties file is loaded correctly with the following:

my.list.of.strings=ABC,CDE,EFG
2018/03/16
472
3/16/2018 2:19:38 PM

Since Spring 3.0, you can add a line like

<bean id="conversionService" 
    class="org.springframework.context.support.ConversionServiceFactoryBean" />

to your applicationContext.xml (or where you configure things). As Dmitry Chornyi points out in a comment, Java based configuration looks like:

@Bean public ConversionService conversionService() {
    return new DefaultConversionService();
}

This activates the new configuration service which supports converting String to Collection types. If you do not activate this configuration service, Spring falls back on its legacy property editors as configuration services, which do not support this kind of conversion.

Converting to collections of other types works, too:

@Value("${my.list.of.ints}")
private List<Integer> myList

will work with a line like

 my.list.of.ints= 1, 2, 3, 4

No problems with whitespace there, the ConversionServiceFactoryBean takes care of it.

See http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#core-convert-Spring-config

In a Spring application, you typically configure a ConversionService instance per Spring container (or ApplicationContext). That ConversionService will be picked up by Spring and then used whenever a type conversion needs to be performed by the framework. [...] If no ConversionService is registered with Spring, the original PropertyEditor-based system is used.


If you are reading this and you are using Spring Boot, you have 1 more option for this feature

Usually comma separated list are very clumsy for real world use case (And sometime not even feasible, if you want to use commas in your config):

[email protected],[email protected],[email protected],.....

With Spring Boot, you can write it like these (Index start at 0):

email.sendTo[0][email protected]
email.sendTo[1][email protected]
email.sendTo[2][email protected]

And use it like these:

@Component
@ConfigurationProperties("email")
public class EmailProperties {

    private List<String> sendTo;

    public List<String> getSendTo() {
        return sendTo;
    }

    public void setSendTo(List<String> sendTo) {
        this.sendTo = sendTo;
    }

}


@Component
public class EmailModel {

  @Autowired
  private EmailProperties emailProperties;

  //Use the sendTo List by 
  //emailProperties.getSendTo()

}



@Configuration
public class YourConfiguration {
    @Bean
  public EmailProperties emailProperties(){
        return new EmailProperties();
  }

}


#Put this in src/main/resource/META-INF/spring.factories
  org.springframework.boot.autoconfigure.EnableAutoConfiguration=example.compackage.YourConfiguration
2017/12/01

By specifying the the my.list.of.strings=ABC,CDE,EFG in .properties file and using

@Value("${my.list.of.strings}") private String[] myString;

You can get the arrays of strings. And using CollectionUtils.addAll(myList, myString), you can get the list of strings.

2012/09/25

Have you considered @Autowireding the constructor or a setter and String.split()ing in the body?

class MyClass {
    private List<String> myList;

    @Autowired
    public MyClass(@Value("${my.list.of.strings}") final String strs) {
        myList = Arrays.asList(strs.split(","));
    }

    //or

    @Autowired
    public void setMyList(@Value("${my.list.of.strings}") final String strs) {
        myList = Arrays.asList(strs.split(","));
    }
}

I tend to prefer doing my autowiring in one of these ways to enhance the testability of my code.

2012/09/25

If you are using Spring Boot 2, it works as is, without any additional configuration.

my.list.of.strings=ABC,CDE,EFG

@Value("${my.list.of.strings}")
private List<String> myList;
2018/12/05