I am new to String Boot and I am trying to parse property from application.properties into HashMap.
This is how I store Map in application.properties for good readability:
my.map.property.key0=value01,value02
my.map.property.key1=value11,value12
In my properties class I define a Bean with #ConfigurationProperties annotation:
#Bean
#ConfigurationProperties(prefix="my.map.property")
public Map<String, Set<String>> myMap() {
return new HashMap<>();
}
This works fine and to get that HashMap I can just Autowire that bean
#Autowired
Map<String, Set<String>> myMap
The problem is that it's very easy to mess up with correct Map keys in properties file and I want to validate keys to check if they match some Enum values.
Custom Enum validator is not working in this case, so I am thinking maybe I need to use Listeners or something else to do validation. Does anybody have any ideas on the best way to validate HashMap keys once myMap is initialized?
Related
I was able to use java Spring annotation to inject key values pair into the hashmap as follows
validationError.properties file
errorcode.map={\
"default.labOrder.oneservice": "AAAAAA", \
"default.labOrder.patient.firstName": "BBBBB", \
}
I able to use the following code to inject the values into my hashmap as follows
#Value("#{${errorcode.map}}")
private Map<String, String> errorNumberMap;
However if I have a property file with the following values
errorcode.map={\
"LAB": "AAAAAA, BBBB, CCCC", \
"ECP": "AAAAAA, BBBB, CCCC", \
}
and a map Hashmap<AccessType, List> preserveMap = new HashMap() where AccessType is an enum. Does spring has any annotation that will populate my preserveMap value?
Thanks!
Mapping properties directly into bean fields only support simple basic mappings between properties and field values.
Using a configuration object gives more options and can do this kind of tricks and is also more readable.
https://www.baeldung.com/configuration-properties-in-spring-boot
I am trying to follow this guide here:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-Configuration-Binding
but I am struggling to get it to work.
I want to initialize a HashMap from a map defined in application.yml.
This is my last try at the yml-map definition:
symbols:
symbolPairs.CombinationsAlpha="CombinationsAlpha"
symbolPairs.[CombinationsAlpha]=aaabbb, bbbaaa, ccceee, dddggg
symbolPairs.Combinations="CombinationsInteger"
symbolPairs.[CombinationsAlpha]=000111, 222666, 999000, 151515
And this is my java class:
#Data
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "symbols")
public class SymbolsConfig {
private Map<String, List<String>> symbolPairs = new HashMap<>();
}
I want to have "CombinationsAplha" and "CombinationsInteger"injected as keys and the values as a List of Strings.
I am struggling to define the yml correctly.
The #Data annotation from projectlombok generates getters and setters.
Your yml structure isn't correct. Change your yml like this
symbols:
symbolPairs.[CombinationsAlpha]: aaabbb, bbbaaa, ccceee, dddggg
symbolPairs.[CombinationsInteger]: 000111, 222666, 999000, 151515
Here is the output
I am trying to create a
Map<String,Map<Map<String,String>,String>> properties2
as a configurable property with Spring Boot properties file.
I have been previously been able to get a :
Map<String, Map<String,String>> properties
populated with
properties.[A].B=C
where A is the first key and B the second key with a value of C.
I have already tried
properties2.[A].[B=C]=D
which doesn't allow the later components to start although it doesn't throw errors
Does anyone know how I can populate the properties2 map correctly?
you can nest properties as following
private final Map<String, Map<String, Map<String, String>>> namespace = new HashMap<>();
namespace.[foo].[bar].a=alpha
May be you have error here Map,String>> properties2
as you you're using Map<String,String> as as key try this instead Map<String, Map<String, Map<String, String>>>
I have a "details.yml" file, considering all the setting for getting all values from "yml.file" is done. But I am unable to store Map values into
"Map"
Here is my "details.yml" file below
details:
company:XYZ
values:
name: Manish
last: Raut
And in my class file i am able to get the values of "company" from yml file using #Value("${company}")
#Component
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "details")
public class abcd() {
#Value("${company}")
String company;
#Value("${values}")
Map<String, String> values =new HashMap<String, String>();
...............................
}
i am not able to get those values in Mao which i created in this class, but i am getting values for "Company".
Help me with this?
Im the past, I added getter/setter for MAP type and it was work.
Did you try it? (getter/setter for 'values')
I'm not really sure what marshalling framework Spring uses behind the scenes and how it configures it (you could probably find out with some debugging and maybe make it work for your case), but you could always add an extra layer to your application and configure your own.
For instance you could use Jackson with yaml dataformat - https://dzone.com/articles/read-yaml-in-java-with-jackson.
Scenario:
Using Jackson 2.4.5 I have a dynamic bean to be serialised into JSON which can store some of its state in 'optional' properties in an internal map and uses #JsonAnyGetter on an accessor method that returns this map, e.g:
public class DynamicJsonView {
private final Map<String, Object> optionalProperties = new HashMap<>();
private final String rqdProperty = "blah";
public String getRqdProperty() {
return rqdProperty;
}
public DynamicJsonView() {
optionalProperties.put("PROP_1", "value 1");
optionalProperties.put("PROP_2", "value 2");
optionalProperties.put("PROP_3", "value 3");
// etc - in reality populated from another map
}
#JsonAnyGetter
public Map<String, Object> any() {
return Collections.unmodifiableMap(optionalProperties);
}
}
Note the map keys are UPPER_CASE. When we setup our ObjectMapper we set the following naming strategy to convert properties to lower case (and replace camelCase with snake_case), e.g:
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
Problem:
This works exactly as expected with normal java properties, i.e. rqdProperty in the example above converts to rqd_property in the JSON serialized form, but the naming strategy is seemingly ignored for the map 'properties', with the upper case keys appearing unmodified. Having debugged the jackson LowerCaseWithUnderscoresStrategy#translate method and watched the input parameter values passed in as the object is serialised, it seems the keys are never passed through the naming strategy.
The obvious workaround is to pre-process the map keys and convert them all to lower case, but I wondered if there's something I'm missing with regards to the property naming strategy, or if this is simply a limitation of the library?
This is as designed since NamingStrategy is only applied to actual concrete properties, and not for Map keys, or "any" properties.
But if ability to include name mangling for any properties sounds like a good idea, you could request a new feature to do that: it could be enabled (for example) by a flag of #JsonAnySetter:
https://github.com/FasterXML/jackson-databind/issues/