myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Simon Kitching <skitch...@obsidium.com>
Subject value-bindings fetched during component initialisation
Date Tue, 06 Dec 2005 04:51:46 GMT
Hi,

Quick summary:
   UIComponent.getAttributes().put(propName, value)
returns the old value of the property. When the property is a 
value-binding this can cause problems, but there is no obvious way to 
set a property without getting the old value returned.

== details

When a component is created and initialised by a JSP tag, attributes are 
commonly assigned to the component by calls to:
   UIComponentBodyTagBase.setStringProperty(component, propName, value).

This method delegates to UIComponentTagUtils.setStringProperty, which 
implements this as:
   if (isValueReference(value))
   {
      ValueBinding vb =
        context.getApplication().createValueBinding(value);
      component.setValueBinding(propName, vb);
   }
   else
   {
      component.getAttributes().put(propName, value);
   }


The problem is that the component.getAttributes() method returns an 
instance of _ComponentAttributesMap, and the put method of that class 
tries to return the old value of the property.

Fetching the old value of the property typically invokes the getXXX 
method of the component, which calls getValueBinding("XXX"), just to 
return a value that the caller then ignores.

This is a waste of cpu.

It's also causing me problems because I want to override getValueBinding 
in a custom component, but am finding that this method is being called 
during the initialisation of the component which was not expected.

Unfortunately, I can't see an easy fix. This would be nice:
   else
   {
     _ComponentAttributesMap attrs =
       (_ComponentAttributesMap) component.getAttributes();
     attrs.putNoReturn(propName, value);
   }
however the _ComponentAttributesMap class is package-scope only.

_ComponentAttributesMap can't be made public, as new classes can't be 
added to the javax.faces packages.  It can't be moved out of the "api" 
project (eg into "share", as the api project shouldn't have compile 
dependencies on other subprojects).

Duplicating the _ComponentAttributesMap logic isn't good, as it's 
non-trivial code. It also contains a very useful cache of 
PropertyDescriptors that it would be a shame to recalculate.


Question: is it actually part of the JSF standard for the attributes.put 
method to return the old value? That is indeed part of the java.util.Map 
definition, but this class is only very loosely a Map.

Any thoughts???

Regards,

Simon

Mime
View raw message