preRenderView method get call every time dataTable paginate

UI Components for JSF
Post Reply
smithh032772
Posts: 6144
Joined: 10 Sep 2011, 21:10

28 Mar 2012, 04:40

Don't know why this topic was deleted, but I find it interesting, so I had to re-add it, since I was responding at the time it was deleted, and someone else may learn from this forum topic. I value topics discussed here in this forum, and learn a lot that way.
KingdomHeart wrote:I am not sure if this is a correct behavior but it look odd to me. Every time, my dataTable paginate, the method init() from <f:event type="preRenderView" listener="#{myBean.init}"/> get called. Here is a simple reproducible code

Code: Select all

        <f:metadata>
            <f:viewParam name="foodId" value="#{myBean.foodId}"/>            
            <f:event type="preRenderView" listener="#{myBean.init}"/>
        </f:metadata>

        <p:growl id="message" showDetail="true"/>
        <h:form>
            <p:dataTable value="#{myBean.foodList}" var="item"
                         paginator="true" rows="10"  
                         paginatorTemplate="{CurrentPageReport}  {FirstPageLink} 
                         {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} 
                         {RowsPerPageDropdown}">
                <p:column>
                    <h:outputText value="#{item}"/>
                </p:column>
            </p:dataTable>
        </h:form>

Code: Select all

@ManagedBean
@ViewScoped
public class MyBean implements Serializable {
    private List<String> foodList; 
    private String foodId;    
    @PostConstruct
    public void construct(){
        foodList = new ArrayList<String>();
        foodList.add("1");
        foodList.add("2");
        foodList.add("3");
        foodList.add("4");
        foodList.add("5");
        foodList.add("6");
        foodList.add("7");
        foodList.add("8");
        foodList.add("9");
        foodList.add("10");
        foodList.add("11");
        foodList.add("12");
        foodList.add("13");
        foodList.add("14");
        foodList.add("15");
        foodList.add("16");
    }
    
    public void init() {
        if(foodId != null){
            try{
                int id = Integer.parseInt(foodId);
            }catch(NumberFormatException e){
                FacesContext.getCurrentInstance().addMessage(null, 
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error", "Id must be number"));
            }
        }
    }
    //Setter, getter ...
    ...
}
Put a break point inside the init() method, and every time I paginate, it get inside the init() method (no page refresh occur). Issue is reported here: http://code.google.com/p/primefaces/iss ... il?id=3824
zoigl wrote:It's a normal behavior. preRenderView is for EVERY request.

Also this is no PrimeFaces problem whether any problem. That's defined in the JSF specs and logical correct.
smithh032772 wrote:Interesting topic and response from zoigl. Thanks!
Hamsterbau wrote:
zoigl wrote:It's a normal behavior. preRenderView is for EVERY request.
You mean Everquest, didn't you :twisted:

Ok to the problem mentioned above, perhaps this little line help you out, so you can choose whether or not to execute your stuff in your preRenderView method:

Code: Select all

FacesContext.getCurrentInstance().isPostback()
Additional informations you can find here:
http://stackoverflow.com/questions/2830 ... nders-some

And the source is like so often, BalusC :D
KingdomHeart wrote:@All: I found it a bit odd, this is where people usually bind the userId or any type request parameter. Let say it is userId, I see people put db code here to query the user object back from the userId. Why would they do this, if this get execute at every request. I even see BalusC doing this, that where I learn it from. Here is where BalusC showcase this technique

http://balusc.blogspot.com/2011/09/comm ... Parameters
we can see that in his bean, after validate that id is not null, he then

Code: Select all

user = userService.find(id);
and userService is inject with @EJB, so it is every likely that this is a db operation. Wonder why BalusC did this when it is such a costly operation that will get invoke at every request.

If this invoke at every request, then I am going back to have init() annotated with @PostConstruct
Hamsterbau wrote:It depends on the use case. You could also use one SessionScoped bean to hold a user object and inject it to your other beans. PostConstruct can also be used smoothly or use ManagedParameter with listener that will be called by user interaction.

What i like is, that PostConstruct automatically changes with the scope of the bean. But if you want to use metadata, you have to use an preRenderView init() method or use the hack to retrieve the request parameters from FacesContext by yourself in PostConstruct annotated method (with problems for ViewScoped beans :( ).

Good night!
smithh032772 wrote:
Hamsterbau wrote:And the source is like so often, BalusC :D
BalusC? I love that guy and his contribution to the world of JSF developers, and I always recommend his posts/answers/blogs. :)
KingdomHeart wrote:@All: I found it a bit odd, this is where people usually bind the userId or any type request parameter. Let say it is userId, I see people put db code here to query the user object back from the userId. Why would they do this, if this get execute at every request. I even see BalusC doing this, that where I learn it from. Here is where BalusC showcase this technique

http://balusc.blogspot.com/2011/09/comm ... Parameters
we can see that in his bean, after validate that id is not null, he then

Code: Select all

user = userService.find(id);
and userService is inject with @EJB, so it is every likely that this is a db operation. Wonder why BalusC did this when it is such a costly operation that will get invoke at every request.

If this invoke at every request, then I am going back to have init() annotated with @PostConstruct
I think BalusC's 'example' is a good one to demonstrate the use of the tags. In a concurrent user web app where the data is possibly updated by other users, I think a costly db operation is good, as I am requesting latest data from the database as much as possible in the JSF/PrimeFaces web app that I've been developing.

Also, for BalusC's example, the expensive db operation will get the latest data for sure instead of relying on a cached set of data. If you look at the following, you will see the word, simplest:
In the user.xhtml file, you can at its simplest use <f:viewParam> to set the id as a property of the managed bean and use <f:event type="preRenderView"> to trigger a managed bean method whenever all view parameters have been set:
Personally, I don't like requestScope and GET parameters. I'd rather go with view/sessionscoped and POST.
KingdomHeart wrote:@Hamsterbau: Why is using @PostConstruct create problem in ViewScoped bean?
@Smith: get request make it easier for bookmarkability, and SEO friendly (search engine optimization). Using POST is fine, but make sure that use keep PRG pattern in mind.
KingdomHeart wrote:@Hamsterbau: Why is using @PostConstruct create problem in ViewScoped bean?
I think the answer is in BalusC's blog: The benefits and pitfalls of @ViewScoped
KingdomHeart wrote:@Smith: get request make it easier for bookmarkability, and SEO friendly (search engine optimization). Using POST is fine, but make sure that use keep PRG pattern in mind.
I hope I remember this when I get to the point of developing bookmarkable pages and search engine optimization. Right now, that is out of scope of the project I'm working on. I only want Login page to be bookmarked, and I heard/read requestscope is perfect for login pages, but I'm still not using requestscoped for login page either. Well, PRG is JSF 1.2 concept, right, but no longer needed with 2.1, right?

I had BalusC's PRG phase listener in place even though web app was configured for JSF 2.1. later on, I removed BalusC's PRG phase listener and made few other changes, and i've been doing good with majority of beans as viewscoped and usermanager bean as session and pageNavigator bean as sessionscoped, too. that all works for me.
Howard

PrimeFaces 6.0, Extensions 6.0.0, Push (Atmosphere 2.4.0)
TomEE+ 1.7.4 (Tomcat 7.0.68), MyFaces Core 2.2.9, JDK8
JUEL 2.2.7 | OmniFaces | EclipseLink-JPA/Derby | Chrome

Java EE 6 Tutorial|NetBeans|Google|Stackoverflow|PrimeFaces|Apache

Hamsterbau
Posts: 409
Joined: 28 Dec 2011, 17:44

28 Mar 2012, 09:27

First, thanks for reopening this thread. preRenderView as well as PostConstruct drives me nuts some time ago.
@Hamsterbau: Why is using @PostConstruct create problem in ViewScoped bean?
You cannot retrieve Request-Parameters in every method call (and as BalusC said, it will be called to often for ViewScoped).

Edit: I see the thread on page 2 :D
Primefaces 8.0.7 (PF Extensions 8.0)
JSF: Mojarra 2.3.2 (Spec 2.3) - running on WildFly 22

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 46 guests