Avoid invoking value-bindings during component initialisation
-------------------------------------------------------------

         Key: MYFACES-920
         URL: http://issues.apache.org/jira/browse/MYFACES-920
     Project: MyFaces
        Type: Improvement
  Components: General  
    Reporter: Simon Kitching


When a component is created by a JSP tag, calls to setStringProperty, 
setBooleanProperty, etc are used to copy the JSP tag attributes onto the new 
component. (NB: other view implementations will be doing something similar I'm 
sure).

The setStringProperty et. al. eventually call
  component.getAttributes().put(propName, value)

Unfortunately, the Map.put method is defined to return the old value of the 
property. While the specs are a little vague on whether a return value is 
actually required as far as I can see, both MyFaces and Sun do try to return 
the old value. But this means calling the getter method on the component, which 
typically calls getValueBinding().

During component initialisation, this call to the component's getter method and 
thence to getValueBinding isn't actually *too* bad; the binding will never be 
found because each attribute is initially null, and is set only once. However 
it's still inefficient; it's a call via reflection, a HashMap lookup, etc. that 
is all completely unnecessary as the return value will (a) always be null, and 
(b) is ignored.

This behaviour *is* a major pain for anyone (like me) who would like to 
override the getValueBinding method for a component; it gets called once for 
each attribute of the JSP tag, and during a time when the component is not 
completely initialised. And there's no way to tell when component 
initialisation has completed as far as I know.

Attached is a proposed solution. The UIComponent.getAttributes method returns a 
custom (private) Map implementation already. It isn't possible to add any 
methods to this, as it's in the API namespace. Instead I've modified the put 
method so that if the provided propName has a special prefix then the method 
doesn't bother to fetch and return the old value. Updating the 
setStringProperty/setBooleanProperty/etc methods to add the prefix then solves 
the issue.

What do people think of this? Is this ok to commit?

NB: I will be creating some unit tests to go along with this, to prove that the 
patch does what it says. I don't have time just now, though, and wanted to post 
this before I left for the weekend.

NB2: If this does go in (or some other solution to this problem) I've got a 
rather cool use for it. A "backingBean" attribute can then be defined on a 
component, and via a customised ValueBinding, any property on the component 
that supports value-binding will automatically try to fetch the data from an 
identically-named property on the specified backingBean for the component.  
It's very useful when dealing with components with lots of bindable properties, 
like a UIData - or my custom extension of that class, which has even more 
properties.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira

Reply via email to