I tried all the different variations of myMap.get(key)
, myMap[key]
, etc. to get this line of code working where myMap
is a Map<Long,String>
and thing
has a property called state
:
<span th:text="${myMap.get(__${thing.state}__)}"></span>
Any syntactically valid variation I could come up with would only result in empty text.
The only thing that ultimately worked was using a Map<Integer,String>
instead. I'm still passing a long
into myMap.get()
. Thankfully my value range for the particular use case is within the range of Integer
.
How do I write this line of code to be able to use a Map<Long,String>
when I need to?
CodePudding user response:
I tried the following:
Map<Long, String> foodMap = new HashMap<>();
foodMap.put(1L, "Ham & Eggs");
context.setVariable("food", foodMap);
context.setVariable("keyer", new Keyer(1));
With this for my key:
static class Keyer {
public Keyer(long key) {
this.key = key;
}
private long key;
public long getKey() {
return key;
}
public void setKey(long key) {
this.key = key;
}
}
And each of these worked:
<span th:text="${food[keyer.key]}" />
<span th:text="${food.get(keyer.key)}" />
<span th:text="${food.get(1L)}" />
Output:
<span >Ham & Eggs</span>
<span >Ham & Eggs</span>
<span >Ham & Eggs</span>
CodePudding user response:
The reason your example does not work as expected is a combination of these two facts:
- By coding
__${...}__
you trigger preprocessing the contained expression. Preprocessing adds back the result of the expression as text to the surrounding expression and is processed again in a second round. Thymeleaf/SPEL does not have a good hint to interpret the result asjava.lang.Long
and hence the next best attempt is to parse it intojava.lang.Integer
. java.lang.Integer
andjava.lang.Long
do not compare (and maps rely on the result ofequals
).
Integer i = 42;
Long l = 42L;
System.out.println(l.equals(i)); // the output is 'false'
The solution depends on wether you actually need preprocessing and how thing.state
is declared:
- If it is a
long
orjava.lang.Long
and there is no good argument for preprocessing it you can simply write:
${myMap.get(thing.state)}
- If it has a different type (e.g. String) or you definitely need it to be preprocessed you can explicitly convert it to long by adding an 'L' suffix:
${myMap.get(__${thing.state 'L'}__)}
- Similar to option 2 you could adapt your code to make
thing.state
resolve to a string ending with 'L'.
(tested with Thymeleaf 3.0.15.RELEASE)
Hints:
- Option 1 is expected to be slightly faster.
- Option 2 and 3 only will raise an exception if the resulting expression is not numeric (as the original expression would as well).