Spring .properties file: get element as an Array
Asked Answered
P

5

116

I'm loading properties attributes from a .properties file using Spring as follows:

file: elements.properties
base.module.elementToSearch=1
base.module.elementToSearch=2
base.module.elementToSearch=3
base.module.elementToSearch=4
base.module.elementToSearch=5
base.module.elementToSearch=6

The spring xml file

file: myapplication.xml
<bean id="some"
      class="com.some.Class">
      <property name="property" value="#{base.module.elementToSearch}" />
</bean>

And my Class.java

file: Class.java
public void setProperty(final List<Integer> elements){
    this.elements = elements;
}

But when debugging, the parameter elements only get the last element into the list, so, there is a list of one element with value "6", instead of a list with 6 elements.

I tried other approaches, like adding in value only #{base.module} but then it finds no parameter in the properties file.

A workaround is to have in elements.properties file a list separated by commas, like:

base.module.elementToSearch=1,2,3,4,5,6

and use it as a String and parse it, but is there a better solution?

Pamulapan answered 2/6, 2011 at 9:50 Comment(5)
possible duplicate of How do I specify values in a properties file so they can be retrieved using ResourceBundle#getStringArray?Ouzel
so I need to pass it as a comma separated string and parse in method.Pamulapan
Exactly, although there is some libs already doing that for you (apache commons) - commons.apache.org/configuration/howto_properties.htmlOuzel
Here's an answer that at least gives you a Set<String> result. Not quite a List<String>, but probably sufficient in many cases! #5274862Perishable
@Value("${key:one,two,three}") String[] arrayWithDefaults;Anaphylaxis
C
226

If you define your array in properties file like:

base.module.elementToSearch=1,2,3,4,5,6

You can load such array in your Java class like this:

  @Value("${base.module.elementToSearch}")
  private String[] elementToSearch;
Charette answered 20/6, 2011 at 13:50 Comment(7)
My elements contain comma. How do I escape separator? '\,' even '\\,' do not work.Upside
You can try to get them as list of integer and then converts them @Value( "${base.module.elementToSearch}") private List<Integer> elementToSearch;Donato
+1, just what I needed. Unfortunately reading comma-separated values into a List<String> in the same fashion doesn't seem to work (the list will have just one element).Proclamation
I am failing to read them in to an array (String[]). Is this supposed to work?Foreshow
I can confirm that using String[] as type works, where using List<String> does not work.Clovah
Under the hood this uses org.springframework.util.StringUtils.commaDelimitedListToStringArray(String) to split the string, and this util method does not support any escapes, so if your values contain commas, you are out of luck and need to write your own converter.Fusibility
If you want this to work with List<String> instead of String[], you need to add at least a <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean"> to your applicationContext.xml. Otherwise the conversion service is not used but the default property editors, which do not support converting Strings to collections, only arrays: docs.spring.io/spring/docs/current/spring-framework-reference/…Fusibility
H
47

And incase you a different delimiter other than comma, you can use that as well.

@Value("#{'${my.config.values}'.split(',')}")
private String[] myValues;   // could also be a List<String>

and

in your application properties you could have

my.config.values=value1, value2, value3
Hurds answered 19/8, 2016 at 13:4 Comment(1)
this usage also works with other annotations, I used like @KafkaListener{topics= "#{'${ArrayProperty}'.split(',')}"} for spring kafka listenerSkiest
I
35

Here is an example of how you can do it in Spring 4.0+

application.properties content:

some.key=yes,no,cancel

Java Code:

@Autowire
private Environment env;

...

String[] springRocks = env.getProperty("some.key", String[].class);
Innuendo answered 26/11, 2015 at 17:20 Comment(1)
this is what I want, but in env vars... I should be able to use SOME_KEY_0_=yes SOME_KEY_1=no, etc in env vars, but my getProperty is coming back nullEduard
L
12

With a Spring Boot one can do the following:

application.properties

values[0]=abc
values[1]=def

Configuration class

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component
@ConfigurationProperties
public class Configuration {

    List<String> values = new ArrayList<>();

    public List<String> getValues() {
        return values;
    }

}

This is needed, without this class or without the values in class it is not working.

Spring Boot Application class

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

import java.util.List;

@SpringBootApplication
public class SpringBootConsoleApplication implements CommandLineRunner {

    private static Logger LOG = LoggerFactory.getLogger(SpringBootConsoleApplication.class);

    // notice #{} is used instead of ${}
    @Value("#{configuration.values}")
    List<String> values;

    public static void main(String[] args) {
        SpringApplication.run(SpringBootConsoleApplication.class, args);
    }

    @Override
    public void run(String... args) {
        LOG.info("values: {}", values);
    }

}
Leclair answered 11/1, 2020 at 19:51 Comment(1)
why @Value("#{configuration.values}") and not @Value("#{values}"), neither works for me btw...Jasminjasmina
P
-2

If you need to pass the asterisk symbol, you have to wrap it with quotes.

In my case, I need to configure cors for websockets. So, I decided to put cors urls into application.yml. For prod env I'll use specific urls, but for dev it's ok to use just *.

In yml file I have:

websocket:
  cors: "*"

In Config class I have:

@Value("${websocket.cors}")
private String[] cors;
Puerperal answered 28/2, 2020 at 9:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.