3

How does one populate a map of values using the @Values annotation, without defining anything in applicationContext.xml or any other XML file.

I am using spring boot, which doesn't have any XML files, and nor do I want any XML files, so please don't tell me to declare any property reader beans in XML etc.

Also, this is a properties injection question - please don't suggest using a database to store the data - that's not an answer, and not possible for my situation anyway.

Also, I can't use YAML either (due to deployment/operational requirements).

I have tried declaring this injection:

@Value("${myprop}")
Map<Integer, String> map;

And this one

@Value("${myprop.*}")
Map<Integer, String> map;

with these entries application.properties:

myprop.1=One
myprop.2=Two
myprop.3=Three

and then tried

myprop[1]=One
myprop[2]=Two
myprop[3]=Three

But no good - just explodes with

Could not autowire field: ... Could not resolve placeholder 'myprop'

I have found a work-around with an injected String[] specified as key1:value1,key2:value2,... that I then parse in code, but I'd prefer to not do that because a) it's more code, and b) the list is going to be quite long, and all pairs on one line is going to be hard to read and maintain.

Is there a way to automatically build a map from several properties?

I don't care what the property names are, what the field type or the annotation is; I'm just trying to inject one key/value pair per property.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • As far as I know, there isn't a built-in configuration for this. It seems like a very specific use case. Does the key of the `Map` match everything matched by the `*`? – Sotirios Delimanolis Aug 11 '14 at 06:19
  • http://stackoverflow.com/questions/9259819/how-to-read-values-from-properties-file – StanislavL Aug 11 '14 at 06:26
  • @SotiriosDelimanolis that was my intention. Although I don't care what format the properties are in; as long as it's one key/value pair per line, it can be any format, any field type, any annotation. I should add that it is not possible for me to yse YAML either. – Bohemian Aug 11 '14 at 07:13
  • @stan Thanks, but that linked answer uses XML to declare a custom property loader, which as per the bold print in the first line of my question is not a useful answer – Bohemian Aug 11 '14 at 07:20
  • Did you resolve this ? – yathirigan Jun 07 '15 at 09:10
  • @yathirigan no. the closest I got was to use YAML, which the latest spring boot version supports. – Bohemian Jun 07 '15 at 17:52
  • Here is a similar problem am facing ..http://stackoverflow.com/questions/30691949/how-to-inject-a-map-using-the-value-spring-annotation/30693052?noredirect=1#comment49451560_30693052 – yathirigan Jun 07 '15 at 17:58

3 Answers3

1

Not sure if this applies to your scenario entirely (you have there a Map<Integer, String> but in the end you say you just need a key-value pair in a Map), but maybe it could give you some more ideas:

  • assuming a @Configuration class where the .properties file is loaded as a java.util.Properties object:
@Configuration
public class Config {

    @Bean(name = "mapper")
    public PropertiesFactoryBean mapper() {
        PropertiesFactoryBean bean = new PropertiesFactoryBean();
        bean.setLocation(new ClassPathResource("META-INF/spring/application.properties"));
        return bean;
    }

    @Bean
    public MyBean myBean() {
        return new MyBean();
    }
}
  • the MyBean class where those Properties are being used, injected using SPeL:
public class MyBean {

    @Value("#{mapper}")
    private Map props;

    public Map getProps() {
        return props;
    }
}

So, in the end you don't use xml (of course), you need to use a PropertiesFactoryBean to load the .properties file and, using @Value, Spring will inject the Properties into a Map. The extra code (compared to, probably, @PropertySource) is the PropertiesFactoryBean and you don't need to parse the values in your code manually (compared to your workaround that injects a String[]).

Hope this helps.

Andrei Stefan
  • 51,654
  • 6
  • 98
  • 89
0

How about defining a bean in your Java config for this?

@Bean
public Map<Integer, String> myProps(Properties properties) {
  Map<Integer, String> map = new HashMap<>();

  // implement logic to populate map from properties

  return map;
}

And in your class:

@Autowirded
Map<Integer, String> map;
micha
  • 47,774
  • 16
  • 73
  • 80
0

Hello for people serach a simply solution to this problem.

put the sequent line to your application.properties:

myprop = "{1:'One',2:'Two',3:'Three'}"

then in your Spring application put the line:

@Value("#{${myprop}}")
Map<Integer, String> map;
Davide Castronovo
  • 1,366
  • 8
  • 21