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?