How to keep JSF flash scope parameters on page reload? - jsf-2

I use flash scope to pass a setting object between #viewscoped contollers. But if I make a page reload on one of them, then the flash map is empty and the setting object is not initialized. Is it possible to keep flash scope on page reload?
My source code to store/retrieve settings:
FistPage.xhtml
...
<p:commandButton value="next"
action="#{firstPageController.transferConfig}"
process="#this" />
...
FirstPageController.java
#ManagedBean(name = "firstPageController")
#ViewScoped
public class FirstPageController {
...
public String transferConfig() {
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("searchConfig", searchConfig);
return "/secondPage.xhtml?faces-redirect=true";
}
...
}
SecondPage.xhtml
...
<h:outputLabel value="value">
<f:event type="preRenderComponent" listener="#{secondPageController.onPageLoad()}"/>
</h:outputLabel>
...
SecondPageController.java
#ManagedBean(name = "secondPageController")
#ViewScoped
public class SecondPageController {
...
public void onPageLoad()
{
flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
searchConfig = ((SearchFilterConfig) flash.get("searchConfig"));
flash.putNow("searchConfig", searchConfig);
flash.keep("searchConfig");
}
...
}
I use Mojarra 2.1.29
Thanks

I just did some tests in my playground project and realized it's actually possible to keep the state of the flash parameters even if you GET the page again, using {flash.keep}. That's how the JSF docs explain it:
The implementation must ensure the proper behaviour of the flash is preserved even in the case of a <navigation-case> that contains a <redirect />. The implementation must ensure the proper behavior of the flash is preserved even in the case of adjacent GET requests on the same session. This allows Faces applications to fully utilize the Post/Redirect/Get design pattern.
Here you've got a nice basic test case:
page1.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head />
<h:body>
<h:form>
<h:button id="nextButton" value="Next (button)" outcome="page2.xhtml" />
<c:set target="#{flash}" property="foo" value="bar" />
</h:form>
</h:body>
</html>
page2.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<head />
<body>foo = #{flash.keep.foo}
</body>
</html>
Just open the first page and click on the button which will redirect you to the second one. Then refresh the second page as many times as you want and you'll find the parameter persisting.
Tested in Mojarra 2.2.6

Related

PrimeFaces based application with PicketLink does not show style in login page

I developed a PrimeFaces based application that I now want to protect with PicketLink in a CDI way. I followed this example and created a login page with several PrimeFaces components including a layout). All styling and functionality is however lost. Even a simplified login.xhtml page (to match the example linked to above) does not have styling.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head/>
<h:body>
<p:panel>
<h:form method="POST" prependId="false">
<p:inputText id="j_username" />
<p:password id="j_password"/>
<p:commandButton id="login" value="Login" action="#{identity.login()}" ajax="false"/>
</h:form>
</p:panel>
<p>Tip: you can login with a username/password of jane/abcd1234.</p>
</h:body>
</html>
The reason the css and js files are not loaded is because the security 'profile' in the original example has all resources protected besides a login.xhtml file. JSF by default loads resources from the 'virtual' javax.faces.resource folder. This needs to be excluded from authentication to. The HttpSecurityConfiguration in the original example should be adapted to exlude this virtual folder in the config.
public class HttpSecurityConfiguration {
public void onInit(#Observes SecurityConfigurationEvent event) {
SecurityConfigurationBuilder builder = event.getBuilder();
builder
.http()
.forPath("/javax.faces.resource/*")
.unprotected()
.forPath("/index.jsf")
.unprotected()
.allPaths()
.authenticateWith()
.form()
.authenticationUri("/login.jsf")
.loginPage("/login.jsf")
.errorPage("/error.jsf")
.restoreOriginalRequest()
.forPath("/logout")
.logout()
.redirectTo("/index.jsf");
}
}

Updating p:graphicImage every n seconds

I was wondering if someone could either explain or point me to a good resource that will help me understand how to update a p:graphicImage in Primefaces 5.0. What I'm trying to do is pretty simple.
<p:graphicImage value="myImage.png"/>
The filename never changes, but it will be updated every n seconds. I'm trying to figure out the easiest way to update that image every n seconds. In this case we'll say every 5.
tyia
Update:
I've tried the suggestions below but poll isn't updating. I've tested this in IE, FF, and Chrome. I'm using the sample code on the prime faces. Here's my bean:
#ManagedBean
#ViewScoped
public class CounterView implements Serializable {
private int number;
public int getNumber() {
return number;
}
public void increment() {
System.out.println("test");
number++;
}
}
I'm outputting to the console to see if increment() is ever executed, which it isn't.
Here's my xhtml:
<?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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title></title>
</h:head>
<h:body>
<h:form>
<p>Welcome, #{loginBean.uname}</p>
<p:commandButton action="#{loginBean.logout}" value="Logout" ajax="false"></p:commandButton>
<br/>
<h:form>
<h:outputText id="txt_count" value="#{counterView.number}" />
<p:poll interval="3" listener="#{counterView.increment}" update="txt_count" />
</h:form>
</h:form>
</h:body>
</html>
The above is the page that I'm redirecting to after a successful login. All output is correct except for txt_count....it stays at 0. I took the image out to get this working before applying it to the image update.
Update 2:
Got the int counter working
<?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:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title></title>
</h:head>
<h:body>
<h:form>
<p>Welcome, #{loginBean.uname}</p>
<p:commandButton action="#{loginBean.logout}" value="Logout" ajax="false"></p:commandButton>
<br/>
<h:outputText id="txt_count" value="#{counterView.number}" />
<p:poll interval="3" listener="#{counterView.increment}" update="txt_count" />
</h:form>
</h:body>
</html>
You might use a poll component with a listener method that changes the image.
<p:poll interval="3" listener="#{your_method_to_change_the_image()}" update="myImage" />
<p:graphicImage id="myImage" value="myImage.png"/>
Disclaimer : Not tested.
According to Primefaces user guide p. 247 you can use a p:imageSwitch for a slideshow. For example:
p:imageSwitch effect="FlyIn">
<p:graphicImage value="/images/nature1.jpg" />
<p:graphicImage value="/images/nature2.jpg" />
<p:graphicImage value="/images/nature3.jpg" />
<p:graphicImage value="/images/nature4.jpg" />
</p:imageSwitch>
You can also set the speed. If I understand you correctly and you change the image serverside I guess you can just alternate between 2 images with the same url. If the browser reads the cached image instead of the updated one I think you can append the current date to the url.

PreRenderView incrementally called on every postback

I have an issue with the order and number of executions of an f:event type="preRenderView".
During my search here I found as usual answers from BalusC in this and this post related to my problem - still it leaves two questions for me:
When I put one f:event type="preRenderView" in the template file (for managing common tasks like checks about the user state which applies for all my views) and another f:event type="preRenderView" in each view (for handling view specific initializations), I wonder why the listener method from the view is called before the one from the template.
When I put the whole <f:metadata><f:event [..] /></f:metadata> after ui:define as suggested, it gets called twice after redirecting to that page from the login page, but when I put it one level higher after ui:composition it only gets called once.
Update: Example
The following example demonstrates the behaviour above:
This is the template file template_test.xhtml, containing a listener for preRenderViewevent calling a common method in a 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 the view file test.xhtml, containing also a listener for preRenderViewevent calling a view specific method in a handler and a command button redirecting via a 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 the 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 the test page:
Init for individual page called.
Common init called.
Init for individual page called.
This shows no. 1, that the event handler from the view is called before the one from the template and no. 2, that the event handler from the view is called twice.
It also shows a 3rd point (that's why I included a button with a redirect to the same page) showing what happens if the page gets requested by redirect - the individual page gets called even more times:
Init for individual page called.
Common init called.
Init for individual page called.
Init for individual page called.
Both no. 2 and 3 can be prevented by either putting the whole metadata section above the ui:define or by adding a dummy parameter to the view's metadata section 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 those cases?
I can reproduce it. This is caused by the presence of /WEB-INF/beans.xml and implicitly thus CDI. It even occurs when you switch back to standard JSF annotations while keeping the beans.xml file. This is already reported as both issue 1771 and issue 2162. However, due to absence of a concrete WAR file reproducing the issue and low votes, the Mojarra developers didn't bother to look closer at it.
I have reported it once 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");
}
}
A missing resource may also cause the listener to be called twice. I'm 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 shouldn't include any missing or obsolete resources in the first place. But let's say you have (by mistake) and your listener gets called twice on and on, you have no chance to find the actual cause of that problem. JSF shouldn't do this.

JSF ViewScope - returning null on actions do not update the view

I have a Managed Bean in ViewScope mode. So, when I call some action from this Managed Bean my page do not update. I see that my action is invoked well and returning null (viewscope work flow is OK).
So, what am I doing wrong?
If I rerender the page using Ajax it works fine.
EDIT:
My Versions are:
JSF 2.1.14 with Primefaces 3.4.1
My Code:
#ManagedBean(name = "test")
#ViewScoped
public class TestMB implements Serializable {
private String status;
public String getStatus() { return this.status; }
public void setStatus(String status) { this.status = status; }
public String changeStatus() {
this.status = "ViewScope Works!";
return null;
}
}
My page:
<!DOCTYPE HTML>
<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:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/template/ui.xhtml">
<ui:define name="head">
</ui:define>
<ui:define id="teste" name="content">
<h:form id="form">
<h:outputText id="status" value="OK?: #{test.status}" />
<p:commandButton id="myAction" value="Do it!" action="#{test.changeStatus}" />
</h:form>
</ui:define>
</ui:composition>
On my screen, the status variable dont change. And, yes.. the action is called OK. Some tip ?
You were using <p:commandButton> to submit the form. It sends by default an ajax request. It updates by default nothing. The behaviour you're observing is thus fully expected. There are several ways to solve this "problem" (quoted, as it's actually not a problem, but just a conceptual misunderstanding):
Tell it to not use ajax.
<p:commandButton ... ajax="false" />
Tell it to update the form.
<p:commandButton ... update="#form" />
Replace by standard JSF component, which doesn't use ajax by default.
<h:commandButton ... />
Note that this concrete problem is unrelated to the view scope itself. You'd have exactly the same problem (with exactly the same solutions) when using another scope, including the request scope.

f:ajax method gets called on load of the jsf page

I've simple 3line jsf page and a backing bean. I'm using command button in my page. Onclick event I'm calling ajax. where ajax method adds an output text component to child. Now the problem is. Out put text component is rendered on load of the page rather than on click of the page.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form>
<h:commandButton id="button1" action="return false" value="Submit">
<f:ajax execute="#{bb.method1()}" render="#form" transient="true" event="click" />
</h:commandButton>
</h:form>
</h:body>
</html>
Backing bean code
#Named("bb")
#SessionScoped
public class BackingBean implements Serializable {
public BackingBean() {
}
public void method1()
{
HtmlOutputText out=new HtmlOutputText();
out.setValue("Text1");
FacesContext context=FacesContext.getCurrentInstance();
context.getViewRoot().getChildren().add(out);
context.getViewRoot().setTransient(true);
}
}
on click of button firebug show status 200 OK.. But I can see no changes at the page
The execute attribute should refer a space separated collection of client IDs of input components which needs to be processed during ajax submit. This attribute is evaluated when the view get rendered and any method bound to it thus get invoked immediately.
You should be using the listener attribute instead.
<f:ajax listener="#{bb.method1()}" render="#form" transient="true" event="click" />
The same is true for the render attribute.
See also:
<f:ajax> tag documentation

Resources