You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Erik Gustavson <go...@gmail.com> on 2005/06/12 03:46:47 UTC

managed map properties - bug or spec loophole?

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

Re: managed map properties - bug or spec loophole?

Posted by Martin Marinschek <ma...@gmail.com>.
Ok, it's been some time, but I have implemented your suggestion...

try it out in SVN-Head (or the nightly build)...

I think that you are right, even if the spec is not clear about that
issue, it might be nice for the users to have that feature.

regards,

Martin

On 6/12/05, Erik Gustavson <go...@gmail.com> wrote:
> 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
>  
>  
>  
>              
>