PreRenderView calls each postback stepwise

I have a problem with the order and number of executions of f:event type="preRenderView" .

During my search here, I found as usual answers from BalusC in this and this article related to my problem - nevertheless it leaves me two questions:

  • When I put one file f:event type="preRenderView" in the template file (for managing common tasks such as checking user status that apply to all my views) and another f:event type="preRenderView" in each view ( to handle specific initializations), I wonder why the listener method from the view is called before from the template.

  • When I put the integer <f:metadata><f:event [..] /></f:metadata> after ui:define , as suggested, it is called twice after redirecting to this page from the login page, but when I put one level higher after ui:composition , it gets only once.


Update: Example

The following example shows the behavior above:

This is the template file template_test.xhtml , containing a listener for the preRenderView event, calling the general method in the handler for all views:

 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xml:lang="de" lang="de" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> <link rel="stylesheet" type="text/css" href="../resources/css/style.css" /> </h:head> <h:body> <f:event type="preRenderView" listener="#{testHandler.initCommon()}" /> <div id="content"> <ui:insert name="content" /> </div> </h:body> </html> 

This is a file of the form test.xhtml , which also contains a listener for the preRenderView event, which calls the presentation-specific method in the handler and redirects the command using the handler method:

 <?xml version="1.0" encoding="UTF-8"?> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" template="template_test.xhtml"> <ui:define name="content"> <f:metadata> <f:event type="preRenderView" listener="#{testHandler.initIndividual()}"></f:event> </f:metadata> <h:form> <h:commandButton value="Redirect" action="#{testHandler.redirect()}" /> </h:form> </ui:define> </ui:composition> 

This is the Handler class TestHandler.java , containing 3 methods:

 package test; import java.io.Serializable; import javax.enterprise.context.SessionScoped; import javax.inject.Named; @Named @SessionScoped public class TestHandler implements Serializable { private static final long serialVersionUID = -2785693292020668741L; public void initCommon() { System.out.println("Common init called."); } public void initIndividual() { System.out.println("Init for individual page called."); } public String redirect() { return "test/test.xhtml?faces-redirect=true"; } } 

Now this is what I see in my tomcat log when requesting a test page:

 Init for individual page called. Common init called. Init for individual page called. 

It does not show. 1, that the event handler from the view is called before from the template and not. 2 that the event handler from the view is called twice.

It also shows the 3rd point (why I turned on the redirect button to the same page), showing what happens if the page is requested by redirection - a separate page is called even more times:

 Init for individual page called. Common init called. Init for individual page called. Init for individual page called. 

Both are not. 2 and 3 can be prevented by putting the entire metadata fragment above ui:define or by adding a dummy parameter to the metadata section of the view, which is not included in the URL:

 <f:metadata> <f:viewParam name="dummyToDenySecondRedirect" /> <f:event type="preRenderView" listener="#{testHandler.initIndividual()}"></f:event> </f:metadata> 

Can someone tell me the reason for these cases?

+6
source share
2 answers

I can play it. This is caused by the presence of /WEB-INF/beans.xml and thus implicitly the CDI. This happens even when switching to standard JSF annotations while saving the beans.xml file. This has already been reported as issue 1771 and issue 2162 . However, due to the lack of a specific WAR file that reproduces the problem and low voices, Mojarra developers did not bother to look at it.

I reported this again as issue 2719 . The problem can be reproduced with a smaller example:

 <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" > <f:metadata> <f:event type="preRenderView" listener="#{bean.preRenderView}" /> </f:metadata> <h:head> <title>preRenderView fail</title> </h:head> <h:body> <p>On initial request, you'll see the listener being invoked twice instead of only once.</p> <p>On every postback by the below button, you'll see the listener being invoked once more.</p> <h:form> <h:commandButton value="submit" /> </h:form> <p>Note however that this increments every time you issue the postback.</p> <p>If you remove <code>/WEB-INF/beans.xml</code> and redeploy, then the issue will disappear.</p> </h:body> </html> 

and

 package com.example; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; @ManagedBean @RequestScoped public class Bean { public void preRenderView() { System.out.println("preRenderView called"); } } 
+5
source

A missing resource can also cause a listener to be called again. I am using MyFaces 2.2 here:

 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets"> <f:metadata> <f:event type="preRenderView" listener="#{testController.update()}" /> </f:metadata> <h:head> <script type="text/javascript" src="#{resource['/js/missing.js']}" /> <title>Test</title> </h:head> <h:body> <p>TestController.update() is called twice.</p> </h:body> </html> 

Obviously, you should not include any missing or outdated resources in the first place. But let me say what you have (by mistake), and your listener is called twice twice, you cannot find the actual cause of this problem. JSF should not do this.

0
source

All Articles