Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>This seems to be a timing problem. This listener method is invoked during the <code>preRenderView</code> event. According to the source code of <code>ELFlash</code> (Mojarra's <a href="http://docs.oracle.com/javaee/6/api/javax/faces/context/Flash.html" rel="nofollow noreferrer"><code>Flash</code></a> implementation as returned by <code>ExternalContext#getFlash()</code>) it turns out that it won't set the flash cookie when you're currently sitting in the render response phase and the flash cookie hasn't been set yet for the current request:</p> <p>Here are the relevant lines from <code>ELFlash</code>:</p> <pre><code>if (currentPhase.getOrdinal() &lt; PhaseId.RENDER_RESPONSE.getOrdinal()) { flashInfo = flashManager.getPreviousRequestFlashInfo(); } else { flashInfo = flashManager.getNextRequestFlashInfo(this, true); maybeWriteCookie(context, flashManager); } </code></pre> <p>The <code>maybeWriteCookie</code> would only set the cookie when the flash cookie needs to be passed through for the second time (i.e. when the redirected page in turn redirects to another page).</p> <p>This is an unfortunate corner case. This <code>ELFlash</code> logic makes sense, but this isn't what you actually want. <em>Basically</em> you need to add the message during <code>INVOKE_APPLICATION</code> phase instead. There is however no such event as <code>postInvokeAction</code>. With the new JSF 2.2 <code>&lt;f:viewAction&gt;</code> tag it should be possible as it really runs during invoke application phase.</p> <pre><code>&lt;f:viewAction action="#{bean.onload}" /&gt; </code></pre> <p>As long as you're not on JSF 2.2 yet, you'd need to look for alternate ways. The easiest way would be to create a custom <a href="http://docs.oracle.com/javaee/6/api/javax/faces/event/ComponentSystemEvent.html" rel="nofollow noreferrer"><code>ComponentSystemEvent</code></a>.</p> <pre><code>@NamedEvent(shortName="postInvokeAction") public class PostInvokeActionEvent extends ComponentSystemEvent { public PostInvokeActionEvent(UIComponent component) { super(component); } } </code></pre> <p>Now you need somewhere a hook to publish this event. The most sensible place is a <a href="http://docs.oracle.com/javaee/6/api/javax/faces/event/PhaseListener.html" rel="nofollow noreferrer"><code>PhaseListener</code></a> listening on after phase of <code>INVOKE_APPLICATION</code>.</p> <pre><code>public class PostInvokeActionListener implements PhaseListener { @Override public PhaseId getPhaseId() { return PhaseId.INVOKE_APPLICATION; } @Override public void beforePhase(PhaseEvent event) { // NOOP. } @Override public void afterPhase(PhaseEvent event) { FacesContext context = FacesContext.getCurrentInstance(); context.getApplication().publishEvent(context, PostInvokeActionEvent.class, context.getViewRoot()); } } </code></pre> <p>If you register it as follows in <code>faces-config.xml</code></p> <pre><code>&lt;lifecycle&gt; &lt;phase-listener&gt;com.example.PostInvokeActionListener&lt;/phase-listener&gt; &lt;/lifecycle&gt; </code></pre> <p>then you'll be able to use the new event as follows</p> <pre><code>&lt;f:event type="postInvokeAction" listener="#{bean.onload}" /&gt; </code></pre> <hr> <p><strong>Update</strong> this is also available in the JSF utility library <a href="http://omnifaces.org" rel="nofollow noreferrer">OmniFaces</a>, so you don't need to homebrew the one and other. See also the <a href="http://showcase.omnifaces.org/eventlisteners/InvokeActionEventListener" rel="nofollow noreferrer"><code>InvokeActionEventListener</code> showcase example</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload