You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Jorg Heymans <jh...@domek.be> on 2004/09/24 15:25:53 UTC

repeater calls row-path method n+1 times

Hi,

Bringing this over from user@ , this is just too unlogical for me.

Say formbean has a Collection called "smallbeans" of "smallbean" objects
and i want to have a repeater for this.

then the binding looks like
<fb:repeater id="myrepeater" parent-path="." row-path="smallbeans">

formbean.java has getSmallbeans() and setSmallbeans().

When loading this repeater, getSmallbeans() gets called n+1 times, where 
n is the number of elements in the collection. Now lets say that the 
repeater is populated from a fairly heave database query that returns 
around 100 entries - you get the picture :)

Is this a normal repeater feature? Shouldn't it be enough for the 
repeater to call the method only once as it returns the whole collection 
anyway?


Thoughts?
Jorg Heymans


Re: repeater calls row-path method n+1 times

Posted by Jorg Heymans <jh...@domek.be>.
PS: tested this against in 2.1.5 and 2.1 trunk, same behaviour.

Jorg Heymans wrote:
> Hi,
> 
> Bringing this over from user@ , this is just too unlogical for me.
> 
> Say formbean has a Collection called "smallbeans" of "smallbean" objects
> and i want to have a repeater for this.
> 
> then the binding looks like
> <fb:repeater id="myrepeater" parent-path="." row-path="smallbeans">
> 
> formbean.java has getSmallbeans() and setSmallbeans().
> 
> When loading this repeater, getSmallbeans() gets called n+1 times, where 
> n is the number of elements in the collection. Now lets say that the 
> repeater is populated from a fairly heave database query that returns 
> around 100 entries - you get the picture :)
> 
> Is this a normal repeater feature? Shouldn't it be enough for the 
> repeater to call the method only once as it returns the whole collection 
> anyway?
> 
> 
> Thoughts?
> Jorg Heymans
> 
> 


Re: repeater calls row-path method n+1 times

Posted by Jorg Heymans <jh...@domek.be>.

Vadim Gritsenko wrote:
> 
> Not to prevent you from tinkering with this code, but a side comment 
> about "hooking up an O/R mapping". I don't think I'd be totally off mark 
>  if I were to say that any respectable O/R mapping will make sure that:
> 
>  * Any obj.get() will pull information from database only once during 
> the life of the transaction, and only in case lazy loading is used

s/will/should/ , and only when configured to do so. It's hibernate i am 
using, for the moment it's setup not to do any caching at all. Note that 
at this point in my app i don't need to write anything back, so there 
are no transactions involved yet.

>  * Any set() won't write anything to database at all till some kind of 
> obj.commit() or service.store(obj) is called
true.

> 
> Given these two points, it becomes less important how many times set/get 
> is called. But it does not mean it should not be fixed :)
Well depends, i don't know (yet) what CForms does 12 times with the 
collection it retrieves. If it's a large collection and CForms is doing 
something else besides array reference assigning then it will become 
problematic in terms of performance.

> 
> PS Never worked with OJB / hibernate yet; how do they operate in such 
> situation? IIRC, JDO operates exactly as described above.

It works quite well up until know. I have a huge datamodel to deal with, 
used middlegen to extract the O/R mapping from the database and generate 
the hibernate classes. It saved me heaps of time.


Jorg


Re: repeater calls row-path method n+1 times

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Jorg Heymans wrote:

> I took the form2bean.flow example that is under CForms Block Samples 
> (link is called "Bean Binding") and enhanced Form2Bean.java with a bit 
> of get/set logging. I changed the calling flowscript method (form2bean 
> in binding_example.js) to add 4 Contacts instead of 1.
> 
> Findings:
> - getContacts() is called 5 times upon loading
> - when removing 3 elements and saving the form, getContacts() is called 
> 7 times. setContacts() is called once for each removed element.
> - at the end getContacts() is called another 3 times.
> 
> This is important to know when hooking up CForms to an O/R mapping. I am 
> curious to know how other people have gotten around this when dealing 
> with large repeaters.

Not to prevent you from tinkering with this code, but a side comment 
about "hooking up an O/R mapping". I don't think I'd be totally off mark 
  if I were to say that any respectable O/R mapping will make sure that:

  * Any obj.get() will pull information from database only once during 
the life of the transaction, and only in case lazy loading is used
  * Any set() won't write anything to database at all till some kind of 
obj.commit() or service.store(obj) is called

Given these two points, it becomes less important how many times set/get 
is called. But it does not mean it should not be fixed :)


PS Never worked with OJB / hibernate yet; how do they operate in such 
situation? IIRC, JDO operates exactly as described above.

Vadim


Re: repeater calls row-path method n+1 times

Posted by Jorg Heymans <jh...@domek.be>.
I took the form2bean.flow example that is under CForms Block Samples 
(link is called "Bean Binding") and enhanced Form2Bean.java with a bit 
of get/set logging. I changed the calling flowscript method (form2bean 
in binding_example.js) to add 4 Contacts instead of 1.

Findings:
- getContacts() is called 5 times upon loading
- when removing 3 elements and saving the form, getContacts() is called 
7 times. setContacts() is called once for each removed element.
- at the end getContacts() is called another 3 times.

This is important to know when hooking up CForms to an O/R mapping. I am 
curious to know how other people have gotten around this when dealing 
with large repeaters.


Here is the output in case anyone is interested.

Upon loading the form initially
---------------------------------
addContact() 1
addContact() 2
addContact() 3
addContact() 4
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()



removed contact 4,3,2 using the repeater remove button, pressed submit
-----------------------------------------------------------------------
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
getContacts() returning collection of size 4
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
     id=4 name=Hermann4
end getContacts()
setContacts() with collection of size 3
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
     id=3 name=Hermann3
end setContacts()
setContacts() with collection of size 2
elements are :
     id=1 name=Hermann1
     id=2 name=Hermann2
end setContacts()
setContacts() with collection of size 1
elements are :
     id=1 name=Hermann1
end setContacts()
getContacts() returning collection of size 1
elements are :
     id=1 name=Hermann1
end getContacts()
getContacts() returning collection of size 1
elements are :
     id=1 name=Hermann1
end getContacts()
getContacts() returning collection of size 1
elements are :
     id=1 name=Hermann1
end getContacts()



Jorg Heymans wrote:
> Hi,
> 
> Bringing this over from user@ , this is just too unlogical for me.
> 
> Say formbean has a Collection called "smallbeans" of "smallbean" objects
> and i want to have a repeater for this.
> 
> then the binding looks like
> <fb:repeater id="myrepeater" parent-path="." row-path="smallbeans">
> 
> formbean.java has getSmallbeans() and setSmallbeans().
> 
> When loading this repeater, getSmallbeans() gets called n+1 times, where 
> n is the number of elements in the collection. Now lets say that the 
> repeater is populated from a fairly heave database query that returns 
> around 100 entries - you get the picture :)
> 
> Is this a normal repeater feature? Shouldn't it be enough for the 
> repeater to call the method only once as it returns the whole collection 
> anyway?
> 
> 
> Thoughts?
> Jorg Heymans
> 
>