简体   繁体   English

如何在Ajax调用或重新加载后将对象保留在JSF Flash Scope上?

[英]How to keep objects on JSF Flash Scope after Ajax call or Reload?

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. 我有一个'大'项目,大表和很多关系......所以在我的表单中,我有几个选项卡,一些对话框,以及许多PrimeFaces commandButtons来管理所有带有Ajax请求的CRUD。

The xhtml structure is something like that: xhtml结构是这样的:

<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. 在@ViewScoped控制器的@PostConstruct上。 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. 如果我访问页面而不接触ajax按钮,我可以重新加载页面没有问题...但是,如果我触摸任何导致和ajax请求的东西,JSF Flash Scopre丢失主要对象,因此我不能重新加载页面。

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. 我希望在“意外重新加载”之后保持状态,但是它不适用于Flash。

Also, is it possible to capture/handle the reload event from browser (maybe with js)? 此外,是否可以从浏览器捕获/处理重新加载事件(可能使用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. 我在我的项目中使用PrimeFaces 5.3,JSF 2,Maven,Tomcat 7和Java 7。

Thank you all in advance. 谢谢大家。


Edit 1: After trying the solution mentioned by the user NightEagle, it almost worked... I modified the code: 编辑1:在尝试用户NightEagle提到的解决方案之后,它几乎可以工作......我修改了代码:

<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. 奇怪的是,第一个ajax调用很好,在第二个之后......它开始弹出JSF1095错误。

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. 提前谢谢大家,仍然找到解决方案。

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!)." “在每个HTTP请求上调用preRenderView事件(是的,这也包括ajax请求!)。” (c) https://stackoverflow.com/a/9844616/3163475 (c) https://stackoverflow.com/a/9844616/3163475

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM