3

My property file has a content as follows

config.entry[0]=X-FRAME-OPTIONS,SAMEORIGIN

config.entry[1]=Content-Security-Policy,Frame-Ancestors 'self'

I want this to be loaded to a config class where i can have the comma seperated values loaded as Key,Value pairs in a collection. How can this be achieved using @ConfigurationProperties in Spring 3 ?

Entries = config.getEntry() should give me a collection so that I can iterate and get the list of name value pairs defined in the property file

for(Entry<String,String> index : config.getEntry().entryset()) {
          index.getKey(); // Should Give - X-FRAME-OPTIONS
          index.getValue(); // Should Give - SAMEORIGIN
}

How should i define my Config class that will be autowired with the values from the properties file in this way ?

the following implementation, throws Spring exception "Cannot convert value of type [java.lang.String] to required type [java.util.Map]" for property 'entry[0]': no matching editors or conversion strategy found]

@Component
@ConfigurationProperties("config")
public class MyConfiguration {

  private Map<String,Map<String,String>> entry = new LinkedHashMap<String,Map<String,String>>();

  //getter for entry

  //setter for entry
}
2
  • Can there be multiple value against one key? Commented Apr 28, 2015 at 14:10
  • nope, there can be only 1 value per key. I've updated the question with my current approach and the exact error now. Commented Apr 28, 2015 at 14:11

2 Answers 2

2

You can try with @PostConstruct annotation that will be called after bean in constructed. Here you can load the configuration file and update the map as per your need.

For example:

@Component
public class Config {
    private Map<String, String> entry = new LinkedHashMap<String, String>();

    @PostConstruct
    private void init() throws IOException {
        try (InputStream input = ClassUtils.getDefaultClassLoader().getResourceAsStream("config.properties")) {
            for (String line : IOUtils.readLines(input)) {
                // change the logic as per your need
                String[] keyValue = line.split("=")[1].split(",");
                entry.put(keyValue[0], keyValue[1]);
            }
        }
    }
}
Sign up to request clarification or add additional context in comments.

8 Comments

doesn't @ConfigurationProperties allow straight forward method for loading this kind of Name-Value pair values ? .. this will be final option
I don't think so because it's your own custom file that doesn't fit as per the global requirement.
Is there any issue with this approach? Can you tell me why is it final option?
Spring is taking the entire text as 1 string and creating a Map of that string with 0, 1 as Key. Instead how to force spring to use first part of the text as Key and 2nd part of the text as value.. instead of using the index as Key ?
why can't you use simple property file with key-value pair? Make it simple.
|
1

You can potentially do this in two parts, first a simple @ConfigurationProperties this way:

@ConfigurationProperties(prefix = "config")
@Component
public class SampleConfigProperties {

    private List<String> entry;

    public List<String> getEntry() {
        return entry;
    }

    public void setEntry(List<String> entry) {
        this.entry = entry;
    }
}

This should cleanly load your properties into the entry field of your SampleConfigProperties natively. What you want to do next is not native to Spring - you want the first field in the comma delimited list to be a key in a map, this is a custom logic, you can handle this logic using a @PostConstruct logic this way, see how I am still using Spring's conversionService to transform the comma delimited String to a List<String>:

import javax.annotation.PostConstruct;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ConfigurationProperties(prefix = "config")
@Component
public class SampleConfigProperties {

    @Autowired
    private ConversionService conversionService;
    private List<String> entry;

    private Map<String, String> entriesMap;


    public List<String> getEntry() {
        return entry;
    }

    public void setEntry(List<String> entry) {
        this.entry = entry;
    }

    public Map<String, String> getEntriesMap() {
        return entriesMap;
    }

    public void setEntriesMap(Map<String, String> entriesMap) {
        this.entriesMap = entriesMap;
    }

    @PostConstruct
    public void postConstruct() {
        Map<String, String> entriesMap = new HashMap<>();
        for (String anEntry: entry) {
            List<String> l = conversionService.convert(anEntry, List.class);
            entriesMap.put(l.get(0), l.get(1));
        }
        this.entriesMap = entriesMap;
    }

}

1 Comment

Need an additional help.The >> List<String> l << is creating a list of string when the string is seperated with coma (,). Is there anyway to force using another seperator character ? like pipe or double pipe...etc ?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.