You can find the full source code for this website in the Seam package in the directory /examples/wiki. It is licensed under the LGPL.
JSF does not cache the results of executing EL value expression. Therefore, you will find that typically a single EL value expression will result in the getter being called at least once, but probably two or three times. Further, if you are using a JSF control which involves some sort of iteration (like <h:dataTable />, <h:selectOneMenu /> etc.) then some value expression will probably called once for each iteration.
What can you do? Make sure your getters are lightweight, and use some sort of lazy initialization.
For example, this would result in your list being built many times:
@Name("fooManager")
@Scope(EVENT)
public class FooManager {
public List<Foo> getFoos() {
return createFooList();
}
}
<h:dataTable value="#{fooManager.foos}">
...
but this simple change fixes the problem:
@Name("fooManager")
@Scope(EVENT)
public class FooManager {
private List<Foo> foos;
public List<Foo> getFoos() {
if (foos == null) {
foos = createFooList();
}
return foos;
}
}
Hi Pete:
I think that is not a good solution, if you put the line getFoos before the line you could see many calls to the getter methods. the many calls cause CPU consumption and obviously the performance is decreased (i.e in a page with a that I tested in my app the delay is 76 seconds). Another better solution that I found by reading posts here and jboss.org, was using @Factory or @Create (the delay on the same page was 4 seconds, very good time!!! :) ), but the problem with these are the memory caching, I have all datatables (h:dataTable) in memory, this is not a good solution too. I saw many posts but all have the same problem.
I will need help with this, because I have many datatables with lot of data and I cannot imaginate my application with 10 users calling the same page with a h:datatable with a delay of 76 seconds.
Cheers,
Gustavo Bustos
PD: Sorry for my bad english.
Pete's solution is not a bad solution. He's merely illustrating why and how to prevent the createFooList() method from being called unnecessarily and thus minimizing a potential performance hit.
In some use cases, you would use @Factory or @Unwrap patterns instead. But it's possible in this case that the getFoos() method really needs to get called every time the JSF is rendered.
Hi Arbi
Hmmm, it's not a bad solution but also not a good solution. In which case do you need to call every time the getters methods? I agree with you in minimizing the performance hit but the many calls are still there. I think that is a jsf or my jsf configuration or seam problem, I am not sure about this because I am new to jsf and seam. I noticed in my app that the getters methods are called many times in the same phase, not in each phase, why does jsf do this?, in some posts on this site some users recommend as solution to use @Factory, etc. but this is caching my returned lists from getters, which is the same as using a "if(foos == null)" line (Pete solution). When doing a test with a SFSB with Conversation Scope, you need to use a refresh control. Going back to the many calls, if it is correct that many calls are normal in jsf (in my case in the same phase), it is unnecesary to call again and again and again.... to the getter method if the method is returning the correct result the first time that is called. Independently of Pete's solution that reduces the performance hit, the performance is still bad, I tested it doing a profiling, as result I get a big delay, in my first post explains better.
Thanks for your response,
Gustavo.-
You may look to a comparison of method result caching techniques