In Spring Boot project I have a Map<String, AbstractMap.SimpleEntry<String, String>>
, and use it like:
testData.put("key1", new AbstractMap.SimpleEntry<>("myKey1", "myValue1");
testData.put("key2", new AbstractMap.SimpleEntry<>("myKey2", "myValue2");
...
I want to put the data into a Java properties file, to be more flexible to change it without changing the code, but how to construct the data in the properties file, to map it onto the Map?
I would have a class like:
@Component
@PropertySource("classpath:testdata.properties")
@ConfigurationProperties(prefix = "test.data")
public class TestDataProperties {
private Map<String, AbstractMap.SimpleEntry<String, String>> testData;
// Getter/Setter
}
When constructing in testData.properties
, like:
test.data.testData.key1=myKey1,myValue1
and using it where needed with:
@Autowired
TestDataProperties testDataProperties;
I get Exceptions:
org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'test.data.testdata.key1' to java.util.AbstractMap$SimpleEntry<java.lang.String, java.lang.String>
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [java.util.AbstractMap$SimpleEntry<java.lang.String, java.lang.String>]
Obviously a converter is needed, but how does one look like and how to wire it to the Map?
There are a couple of issue here -
TestDataProperties
, for the first key key1
it will try to find a field with key1 name.Right now the program load the testData.properties and while parsing the properties file it is trying to look for the name key1 but there no key1, instead there is testData property thus testData is always nut in your code.
Since spring does not allow for camel casing properties you can update testData.properties
like so (the convention is to use hyphen every time you want to used more that two words for a property name)-
test.data.test-data.key1=myKey1,myValue1
Then You can change you code in the following way -
TestDataProperties.java
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Component;
import java.util.AbstractMap;
@Component
@PropertySource(value = "classpath:testData.properties")
@ConfigurationProperties(prefix = "test.data.test-data")
public class TestDataProperties {
private AbstractMap.SimpleEntry<String, String> key1;
TestDataProperties(){
}
public AbstractMap.SimpleEntry<String, String> getKey1() {
return key1;
}
public void setKey1(AbstractMap.SimpleEntry<String, String> key1) {
this.key1 = key1;
}
}
Secondly create custom converter to handle the data conversion while parsing the properties file -
CustomConverter.java
import org.springframework.boot.context.properties.ConfigurationPropertiesBinding;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.util.AbstractMap;
@Component
@ConfigurationPropertiesBinding
public class CustomConverter implements Converter<String, AbstractMap.SimpleEntry<String, String>> {
@Override
public AbstractMap.SimpleEntry<String, String> convert(String data) {
if(data != null && !data.isEmpty()){
String[] values = data.trim().split(",");
if(values.length == 2){
return new AbstractMap.SimpleEntry<>(values[0], values[1]);
}
}
return null;
}
}
Finally you can autowire your TestDataProperties
class as
@Autowired
private TestDataProperties testDataProperties;
Then you can access the properties like this -
testDataProperties.getKey1().getKey();
testDataProperties.getKey1().getValue();
Hope this helps!
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.