I've been playing around with managed properties recently and noticed
some behavior that I did not quite expect when using map-entries
against a Map property on my managed bean.
If I create a set of map values like this, everything works fine and I get my values in a map in my managed bean.
....
<managed-property>
<property-name>someMapping</property-name>
<map-entries>
<map-entry>
<key>key1</key>
<value>value1</value>
</map-entry>
<map-entry>
<key>key2</key>
<value>value2</value>
</map-entry>
</map-entries>
</managed-property>
....
However, I decided I wanted my values to be sorted, so I added in a
line to specify the exact type of Map (TreeMap) class I wanted to be
created for me:
....
<managed-property>
<property-name>someMapping</property-name>
<property-class>java.util.TreeMap</property-class>
<map-entries>
<map-entry>
<key>key1</key>
<value>value1</value>
</map-entry>
<map-entry>
<key>key2</key>
<value>value2</value>
</map-entry>
</map-entries>
</managed-property>
....
When MyFaces attempt to create my bean, it blows up trying to coerce a
HashMap to a TreeMap (see stack trace at end of email). Looking through
the code, I can see that in ManagedBeanBuilder.initializeProperties the
value is being created as a HashMap. To me, this looks like a bug...
the value should be created as a HashMap only if the property's Class value is not set (and if it's type is set to a non-Map, an class-cast exception would be thrown)
something like:
case ManagedProperty.TYPE_MAP:
if (property.getPropertyClass != null) {
Class mapClass =
ClassUtils.simpleJavaTypeToClass(property.getPropertyClass());
value = mapClass.newInstance();
} else {
value = new HashMap();
}
initializeMap(facesContext, property.getMapEntries(), (Map) value);
break;
etc... etc... same would probably go for Lists as well.
Any thoughts on this? I'm not an expert of the JSF spec - is there any
mention about if its legal to combine map-entries with a specific
property class in your faces config xml?
--- Stack Trace Below ------------
Caused by: javax.faces.FacesException: Cannot coerce java.util.HashMap to java.util.TreeMap
at org.apache.myfaces.util.ClassUtils.convertToType(ClassUtils.java:321)
at
org.apache.myfaces.config.ManagedBeanBuilder.initializeProperties(ManagedBeanBuilder.java:150)
at
org.apache.myfaces.config.ManagedBeanBuilder.buildManagedBean(ManagedBeanBuilder.java:63)
at
org.apache.myfaces.el.VariableResolverImpl.resolveVariable(VariableResolverImpl.java:328)
at
org.apache.myfaces.el.ValueBindingImpl$ELVariableResolver.resolveVariable(ValueBindingImpl.java:637)
at org.apache.commons.el.NamedValue.evaluate(NamedValue.java:124)
at org.apache.commons.el.ComplexValue.evaluate(ComplexValue.java:140)
at org.apache.myfaces.el.ValueBindingImpl.getValue(ValueBindingImpl.java:441)
... 42 more
Caused by: javax.servlet.jsp.el.ELException: Attempt to coerce a value of type "java.util.HashMap" to type "java.util.TreeMap"
at org.apache.commons.el.Logger.logError(Logger.java:481)
at org.apache.commons.el.Logger.logError(Logger.java:498)
at org.apache.commons.el.Logger.logError(Logger.java:566)
at org.apache.commons.el.Coercions.coerceToObject(Coercions.java:799)
at org.apache.commons.el.Coercions.coerce(Coercions.java:343)
at org.apache.myfaces.util.ClassUtils.convertToType(ClassUtils.java:314)
... 49 more
- managed map properties - bug or spec loophole? Erik Gustavson
- Re: managed map properties - bug or spec loophole? Martin Marinschek

