Spring Boot Map with Map Key - java

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>>>

Related

Validating HashMap keys once Bean method with #ConfigurationProperties initialized

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?

Casting Object to LinkedHashMap

I have parsed a json string using ObjectMapper into Map<String, Object>. Now while I am debugging this map, I see it's effectively a multi-level LinkedHashMap.
So, I would like to convert this Map<String, Object> to Map<String, LinkedHashMap> using ObjectMapper. I have tried the following:
Map<String, LinkedHashMap> tempJsonMap = mapper.readValue((JsonParser) originalJsonMap,
new TypeReference<Map<String, LinkedHashMap>>(){});
Here in this above code, originalJsonMap is of type: Map<String, Object>.
But this code snippet is not working, I am getting error. In this context, I found a few examples to convert LinkedHashMap into a custom object but not the other way round.
Could anyone please help here?

Redis data retrieval

I have a map in redis cache with the following structure :
Cache entry : Map<String, Map<String, String>>
The inner map could have as many as 25000 elements/buckets.
Is there a way in redis to retrieve a specific value from the inner map based on the keys(redis key, outer map's key and inner map's key) without having to fetch the entire redis entry in my Java method that accesses this redis cache?
Currently, if I have to delete a particular key from the inner map, am doing it the following way :
Map<String, Map<String, String>> mapFromRedis = redis.get("myRediscacheKey");
Map<String, String> innerMap = new HashMap<>();
if (!mapFromRedis.isEmpty()) {
innerMap = mapFromRedis.get("key");
}
if (innerMap.containsKey("keyToBeDeleted")) {
innerMap.remove("keyToBeDeleted");
mapFromRedis.put("key", innerMap);
}
redis.set("myRediscacheKey", mapFromRedis);
Your data structure has 3-level mapping: Redis key, outer map key, and inner map key. From your example, we can get the following mapping: myRediscacheKey -> key -> keyToBeDeleted -> value
However, Redis can only has at most 2-level mapping, i.e. HASH. In order to achieve your goal, you have to do compress the 3-level mapping to a 2-level mapping, or even 1-level mapping.
Compress to 2-level mapping
You can combine the Redis key with your outer map key as the key of a HASH, and take the inner map key as the field of the HASH. In that way, we can get the 2-level mapping as follows: myRediscacheKey:key -> keyToBeDeleted -> value.
// set inner map key
hset myRediscacheKey:key keyToBeDeleted value
// remove inner map key
hdel myRediscacheKey:key keyToBeDeleted
Compress to 1-level mapping
You can also combine the 3 keys into one key: myRediscacheKey:key:keyToBeDeleted -> value
// set inner map key
set myRediscacheKey:key:keyToBeDeleted value
// remove inner map key
del myRediscacheKey:key:keyToBeDeleted
You can easily do it with Redisson. It allows to reference Redis object to another Redis object though special reference objects which handled by Redisson. Here is the code sample:
RMap<String, RMap<String, String>> mapFromRedis = redisson.getMap("myRediscacheKey");
// Redisson loads only small reference object
// to another Redis map and NOT entire map
Map<String, String> innerMap = mapFromRedis.get("key");
if (innerMap.remove("keyToBeDeleted") != null) {
// key has been deleted
}
// or with faster approach
if (innerMap.fastRemove("keyToBeDeleted") == 1) {
// key has been deleted
}
That's it! You don't need to execute huge update on each inner map change. Under the hood it works using only 2 operations over Redis: get and hdel
RMap extends standard Java Map and ConcurrentMap interfaces. Thus you don't need to handle with keys/connections/serialization. This all done by Redisson.

JPA Hibernate and having ElementCollection for Map

Can we have an ElementCollection annotation on a field with collection within a collection?
#ElementCollection
private Map<String, List<String>> mappedData = new HashMap<String, List<String>>();
I am getting MappingException at the moment with this so not sure if there are additional annotations or code involved or if I have to make a new class and perhaps use Embeddable and Embedded
You can use UserType or Atribute Converter with JPA attached to your collection I believe. I have never tested it on collection but I believe it is worth the shot:
#ElementCollection
// applies to each element in the collection
#Convert(YourCustomConverter.class)
private Map<String, List<String>> mappedData = new HashMap<String, List<String>>();
When it comes to Hibernate you can try something like this UserCollectionType:
http://www.javalobby.org/java/forums/m91832311.html

How to access List inside Map in Thymeleaf?

Consider the following map,
Map<String, List<String>> map=new HashMap<>();
I would like to put values into this map using thymeleaf. Now, how to insert list items into the map in thymeleaf.
For, Map<String,String> we would write something like map['key']=val;
How to do it for lists?
One way, I thought was keeping the List<String> in a class. For example,
class ListWrapper
{
public List<String> list=new ArrayList<>();
// setter and getter methods
}
and then write the map as
Map<String, ListWrapper> map=new HashMap<>();
and insert like this..
map['key'].list[0]='item 1';
map['key'].list[1]='item 2';
Is there any direct way, instead of writing a class unnecessarily?
Thanks in advance.
You don't need to write a class - you can use Guava's ListMulitMap. Check out these examples.

Categories

Resources