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

Reply via email to