Reputation: 149
I have a 'big' project, big table and a lot of relations... So in my form, I have several tabs, some dialogs, and a lot of PrimeFaces commandButtons to manage all the CRUD with Ajax requests.
The xhtml structure is something like that:
<ui:define name="content">
<h:body>
<p:growl id="growl"/>
<h:form id="formCars" enctype="multipart/form-data">
<p:tabView id="formTabView" scrollable="true" >
<p:tab title="Tab1">
<ui:include src="tabOne/tabOne.xhtml" />
</p:tab>
<p:tab title="Tab2">...</p:tab>
...
<p:tab title="Tab8">...</p:tab>
</p:tabView>
<br />
<div align="center">
<p:commandButton id="cmdSave" value="Save"
action="#{controllerMB.save}" icon="ui-icon-disk"
update="@form :growl" process="@form @this" validateClient="true" />
</div>
</h:form>
<p:dialog header="Car Color" id="modalCarColor" widgetVar="modalCarColor" appendToBody="true" modal="true" height="500" width="700" dynamic="true" closeOnEscape="true" >
<p:ajax event="close" listener="#{controllerMB.closeModalCarColor}" update="@this,:formCarColor"/>
<h:form id="formCarColor">
<ui:include src="tabTwo/carColor/carColor.xhtml" />
</h:form>
</p:dialog>
<p:dialog header="Car Size" ...>
<p:ajax event="close" .../>
<h:form id="formCarColor">...</h:form>
</p:dialog>
</h:body>
</ui:define>
And it works flawlessly... The problem is when I try to reload the page... I manage to keep the main object on the flash by using
FacesContext.getCurrentInstance().getExternalContext().getFlash().keep(key)
on the @PostConstruct of the @ViewScoped controller. If I access the page and dont touch the ajax buttons, I can reload the page without a problem... But, if I do touch anything that causes and ajax request, the JSF Flash Scopre loses the main object, therefore I can't reload the page.
My controller is built this way:
@ManagedBean(name="controllerMB")
@ViewScoped
public class ControllerMB implements Serializable{
// attributes
// ----------
@PostConstruct
public void init(){
if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
car = (Car) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("car");
FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
}
if(car==null) {
redirect_back();
return;
}
// attributes initialization and form preparation
// -----
}
// methods
// ----------
}
The "car" as main object is just an example.
Is there any solution or workaround for this?
I want to keep the state after an 'accidental reload' but, it is not working with Flash.
Also, is it possible to capture/handle the reload event from browser (maybe with js)? I mean, then I could process the form in my main object before reload.
I'm using PrimeFaces 5.3, JSF 2, Maven, Tomcat 7 and Java 7 in my project.
Thank you all in advance.
Edit 1: After trying the solution mentioned by the user NightEagle, it almost worked... I modified the code:
<ui:composition ....>
<f:metadata>
<f:event type="preRenderView" listener="#{controllerMB.preRender}"/>
</f:metadata>
<ui:define name="title">...</ui:define>
<ui:define name="header">...</ui:define>
<ui:define name="content">...</ui:define>
</ui:composition>
and
public void preRender()
{
System.out.print("PRE-RENDER ");
if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
System.out.println("KEEP");
FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
} else {
System.out.println("PUT");
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("car",car);
}
}
The weird thing is, the first ajax call is good, after the second... it starts popping the JSF1095 error.
The output after some dialogs openings:
PRE-RENDER PUT
PRE-RENDER KEEP
PRE-RENDER KEEP
Jul 14, 2017 11:43:59 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash. Any values stored to the flash will not be available on the next request.
PRE-RENDER PUT
Jul 14, 2017 11:44:00 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash. Any values stored to the flash will not be available on the next request.
PRE-RENDER PUT
Jul 14, 2017 11:44:04 AM com.sun.faces.context.flash.ELFlash setCookie
WARNING: JSF1095: The response was already committed by the time we tried to set the outgoing cookie for the flash. Any values stored to the flash will not be available on the next request.
Thank you all in advance, still finding a solution.
Upvotes: 4
Views: 2236
Reputation: 211
I think that i know how to resolve it (it helped me in my project)
<f:metadata>
<f:event type="preRenderView" listener="#{myBean.preRender}"/>
</f:metadata>
backed bean:
public class MyBean
{
@PostConstruct
public void init(){
if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
car = (Car) FacesContext.getCurrentInstance().getExternalContext().getFlash().get("car");
FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
}
}
public void preRender()
{
if(FacesContext.getCurrentInstance().getExternalContext().getFlash().containsKey("car")) {
FacesContext.getCurrentInstance().getExternalContext().getFlash().keep("car");
}
}
}
"The preRenderView event is invoked on every HTTP request (yes, this also includes ajax requests!)." (c) https://stackoverflow.com/a/9844616/3163475
Upvotes: 2