Map iteration doesn't work if the key is a Class instance
Generates text that depends on changing data (like dynamic HTML).
Brought to you by:
revusky
The values are always null, because ${map[key]) will first toString() the Class instance.
Also, Map entry set iteration is a big pita (and a small performance leak):
http://colinyates.blogspot.be/2009/05/freemarker-iterating-map.html
Simply put, FTL doesn't know non-string keys. This is not really a bug in that this is a historical design limitation (yeah, that's a polite word for that...) which is "well known"/documented. Fixing this is difficult, especially as backward-compatibility is important at this point. Same kind of problem with entrySet. (I actually plan to fix this in the summer, together with a lot of other historical baggage.) (To work this around right now, you could use pure BeansWrapper with setSimpleMaps set to true, and then you can do map(key) instead of map[key].)
Thanks for replying.
I don't think this historical design limitation isn't well known/documented: I came across the problem, google about the problem (not the solution because I don't know that) for hours with no result. It's very unintuitive that "map[myClass]" calls "map.get(myClass.toString())" when "map instanceof Map<MyClass, Value>" and always returns null.
So bascially, Java with FTL does this code:
// In Java when populating the data
Map<Color, String> map = new HashMap<Color, String>();
map.put(Color.RED, "beautifull");
// In FTL when rendering the data
String value = map.get(Color.RED.toString()); // RETURNS NULL
Who would want to return null there?
By not returning null, I don't think you're breaking backwards compatbility: I think you're fixing a bug :)
By fixing this, and making the intuitive one the default behavior, I would break many existing templates, and that's of course unacceptable.
As of this being not well documented, it's in the FAQ. And if someone looks at the API (OK, that's not common), it turns out that TemplateHashModel.get wants a String parameter... so you just can't pass anything else to it. That's basically the historical reason, and also why changing it upsets the code base pretty much. TemplateHashModel was for sub-variables originally, that had a name.
TemplateMapModel
will have to be added (whileTemplateHashModel
-s reamin for B.C.) to put an end to the non-string-keys issues, and there entry listing will have to be a function of this model.Meanwhile,
?api
allows using the Java API-s of wrappedMap
-s.