0

I can't get the preRenderView event listener to work on a GET request in JSF 2.1.

I have found a lot about it but nothing seems to work e.g.:
Conditional redirection in JSF
http://andyschwartz.wordpress.com/2009/07/31/whats-new-in-jsf-2/#get-prerenderview-event
http://developer.am/j2eetutorial/jsf/?page=jsf-2-prerenderviewevent-example
JSF, Spring, and the PreRenderViewEvent
http://balusc.blogspot.dk/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters

I have a template with 4 insert blocks and I have tried to insert the event code at all those places but without any luck. I have tried both with and without the f:metadata tag surrounding it.

<f:event type="preRenderView" listener="#{applicationData.redirectIfNoResults}" />

Bean:

@ManagedBean
@ApplicationScoped
public class ApplicationData implements Serializable {
    public void redirectIfNoResults() throws IOException { 
        if (getTotal() < 1) { 
            ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); 
            ec.redirect(ec.getRequestContextPath() + "/noResults.xhtml"); 
        } 
    } 
    ...
}

Template:

<?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 xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <ui:insert name="beforeHeader" />
    <f:view>
        <ui:insert name="inView" />
    </f:view>
    <h:head>
        <meta http-equiv="cache-control" content="no-store" />
        <link href="style.css" rel="stylesheet" type="text/css" />
        <title>Quick Poll</title>
        <ui:insert name="header" />
    </h:head>
    <h:body>
        <h1>Quick Poll</h1>
        <ui:insert name="content" />
    </h:body>
</html>

View:

    <ui:define name="content">
        #{applicationData.question}?<p/>
        <h:panelGrid columns="3" border="0">
                Yes: 
                <h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.yes/applicationData.total}"/>
                #{applicationData.yes}
                <h:outputText value="No:"/> 
                <h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.no/applicationData.total}"/>
                #{applicationData.no}
        </h:panelGrid>
    </ui:define>
</ui:composition>

Please help me figure out how to get it working..

Update 1:
I have made changes as suggested by BalusC but it is still not working..

Template:

<?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 xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:head>
        <meta http-equiv="cache-control" content="no-store" />
        <link href="style.css" rel="stylesheet" type="text/css" />
        <title>Quick Poll</title>
        <ui:insert name="header" />
    </h:head>
    <h:body>
        <h1>Quick Poll</h1>
        <ui:insert name="content" />
    </h:body>
</html>

View:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
     template="template.xhtml">
    <ui:define name="content">
        <f:event listener="#{applicationData.redirectIfNoResults}" type="preRenderView"></f:event> 
        #{applicationData.question}?<p/>
        <h:panelGrid columns="3" border="0">
                Yes: 
                <h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.yes/applicationData.total}"/>
                #{applicationData.yes}
                <h:outputText value="No:"/> 
                <h:panelGrid bgcolor="black" height="20" width="#{300*applicationData.no/applicationData.total}"/>
                #{applicationData.no}
        </h:panelGrid>
    </ui:define>
</ui:composition>
Community
  • 1
  • 1
Morten Holmgaard
  • 7,484
  • 8
  • 63
  • 85

3 Answers3

2

That <f:view> isn't rightly used, it has to wrap the entire view. Remove it (JSF will implicitly create one), or at least let it wrap the entire view, including <h:head> and <h:body> tags.

By the way, the <f:event> does not need to go in a <f:metadata>. That applies only to <f:viewParam>. A <f:event> listener which depends on results of <f:viewParam> is indeed often for sole self-documentary purposes also placed in the same <f:metadata> block, but that is thus not a requirement of <f:event> itself.

In your case, it'd be easier to just put it in <ui:define name="content">.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Okay.. I have added this line inside the content tag: `` but no change.. – Morten Holmgaard Sep 09 '12 at 12:19
  • Have you removed/fixed the wrong `` as well? The `` is namely implicitly attached to the ``, but if it is wrong/broken, then the chance is reasonable that it won't be invoked. – BalusC Sep 09 '12 at 12:40
  • What JSF impl/version are you using? – BalusC Sep 09 '12 at 12:51
  • "JSF 2.1" is a specification version. I was asking for the implementation name and its version. E.g. "Mojarra 2.1.12" or "MyFaces 2.1.8". – BalusC Sep 09 '12 at 13:56
  • Can't reproduce your problem. Your concrete problem is caused elsewhere. To start, put a debug breakpoint on `UIViewRoot#subscribeToViewEvent()` method to see if the particular `` has been subscribed. If so, put a debug breakpoint at line 108 of `RenderResponsePhase#execute()` (the `facesContext.getApplication().publishEvent()` line) and track from there if the subscribed event is found and the call ends up in the listener method or not. – BalusC Sep 09 '12 at 16:01
  • The subscribe method is only called by a PostAddToViewEvent and PreRemoveFromViewEvent.. So it isn't subscribed - any idea? – Morten Holmgaard Sep 09 '12 at 17:59
  • @mortenholmgaard start a new clean app that only contains the even subscription code. This should work.Step by step copy things from your existing project until it stops working. This should help find the cause. – Mike Braun Sep 10 '12 at 09:26
0

ComponentSystemEvent seems to be missing in the method signature.

Method needs to look like this:

public void newRequest(final ComponentSystemEvent event) {
System.out.println("Someone requested me");
}

And then place a caller in the template or in the seperate views, that won't do any difference.

<f:event listener="#{userSessionAction.newRequest}" type="preRenderView"></f:event>
Karl Kildén
  • 2,415
  • 22
  • 34
  • That argument is optional, so this answer doesn't apply. – BalusC Sep 09 '12 at 12:09
  • I have tried with this signature before also and found in docs that I was not required.. I have tried it again in the beforeHeader tag - no change. Can you get it working with a GET request to the page? Can you get my code working? – Morten Holmgaard Sep 09 '12 at 12:10
0

I ended up making a solution with a PostConstruct method in a view scope bean.
Like this: Initializng a Backing Bean With Parameters on Page Load with JSF 2.0

Bean:

@ManagedBean 
@ViewScoped
public class ResultsController {
    @ManagedProperty(value="#{applicationData.total}")  
    private int total; 
    @ManagedProperty(value="#{applicationData.yes}")  
    private int yes; 
    @ManagedProperty(value="#{applicationData.no}")  
    private int no; 

    @PostConstruct 
    public void postConstruct() {
        if (getTotal() < 1) { 
            ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); 
            try {
                ec.redirect(ec.getRequestContextPath() + "/noResults.jsf");
            } catch (IOException e) {
                System.out.println("noResults.jsf redirect failed.");
                e.printStackTrace();
            } 
        } 
    }
    ...
}

View:

<?xml version='1.0' encoding='UTF-8' ?>
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jsp/jstl/core"
    xmlns:f="http://java.sun.com/jsf/core"
     template="template.xhtml">
    <ui:define name="content">
        #{applicationData.question}?<p/>
        <h:panelGrid columns="3" border="0">
                Yes: 
                <h:panelGrid bgcolor="black" height="20" width="#{300*resultsController.yes/resultsController.total}"/>
                #{resultsController.yes}
                <h:outputText value="No:"/> 
                <h:panelGrid bgcolor="black" height="20" width="#{300*resultsController.no/resultsController.total}"/>
                #{resultsController.no}
        </h:panelGrid>
    </ui:define>
</ui:composition>
Community
  • 1
  • 1
Morten Holmgaard
  • 7,484
  • 8
  • 63
  • 85