JSF2.0:重定向后如何保存视图(target=blank)

JSF2.0:重定向后如何保存视图(target=blank),jsf,redirect,jsf-2,target,Jsf,Redirect,Jsf 2,Target,假设我有jsf表单和打印表单数据报告的按钮。按钮需要打开新页面上的数据(target=blank),但是h:button不适合,因为我需要在打开报告页面之前保存数据。因此,我使用执行保存操作的h:commandButton,然后重定向到报告页面: <h:commandLink styleClass="reportButton" action="#{polisBean.doReportPrint}" target="_blank" id="report

假设我有jsf表单和打印表单数据报告的按钮。按钮需要打开新页面上的数据(target=blank),但是h:button不适合,因为我需要在打开报告页面之前保存数据。因此,我使用执行保存操作的h:commandButton,然后重定向到报告页面:

<h:commandLink styleClass="reportButton" action="#{polisBean.doReportPrint}"
                    target="_blank" id="reportListLink">
                    Print report
                </h:commandLink>

@ViewScoped
@Named
public class PolisBean
  ...
  public Object doReportPrint() {        
    if (canEdit() && this.submit() == null) {
        return null;
    }

    return "printReport";
}
<navigation-case>
        <from-outcome>printReport</from-outcome>
        <to-view-id>/polises/reportList.xhtml</to-view-id>
        <redirect include-view-params="true">
            <view-param>
                <name>id</name>
                <value>#{polis.id}</value>
            </view-param>
        </redirect>
    </navigation-case>

打印报告
@视域
@命名
公共类菜豆
...
公共对象doReportPrint(){
if(canEdit()&&this.submit()==null){
返回null;
}
返回“打印报告”;
}
打印报告
/polises/reportList.xhtml
身份证件
#{polis.id}
实体被完美保存,新页面与报告一起打开。好。但是当我返回到初始表单页面并再次尝试保存时,视图已过期并由new构建(因为这不是回发请求,这是一个全新的JSF请求,因为我刚刚从该页面进行了重定向!)。尽管重定向是在打开第二个页面时完成的,但这并不能防止丢失所有视图范围的bean数据

我尝试了CDI中长期运行的conversationScope,但当我返回初始页面时,它抛出了“ContextNotActivieException:WELD-001303作用域类型javax.enterprise.context.conversationScope无活动上下文”异常


有人解决了这个问题吗?如何在不丢失初始数据的情况下通过重定向(到新页面)提交表单?

如果有人感兴趣,我找到了解决方法。不是很漂亮,但允许重定向到“空白”页面:

在新窗口中打开链接后,收据将刷新初始页面(请参见onclick):

因此,需要完成新jsf请求的更新,而不是简单的JS刷新,它包含新创建实体的id。因此,我使用这种方法:

doReportPrint中,我将新创建的id保存到会话:

public Object doReportPrint() {        
    if (canEdit() && this.submit() == null) {
        return null;
    }
    context().getExternalContext().getSessionMap().put("justUpdatedPolisId", entity.getId());        
    return "printReport";
}
初始页面的刷新方式如下:

public Object doRefresh() {
    Object justUpdatedPolisId = context().getExternalContext().getSessionMap().get("justUpdatedPolisId");
    if (justUpdatedPolisId != null) {
        entity.setId((Long)justUpdatedPolisId);
        context().getExternalContext().getSessionMap().remove("justUpdatedPolisId");
        return "save";
    }
    // If for some reasons we have not found it - moving to polises table
    return "polises?faces-redirect=true";
}
保存结果将导致polis.jsf重新打开(使用faces配置导航),id将自动从entity.id附加

另一个技巧是如何从JS调用JSF操作。我试图模仿h:commandLink单击(只是复制了为链接生成的JS代码),但这不起作用,因为视图被重新创建,bean及其属性也是如此,操作根本没有被调用。因此,我使用了PrimeFaces的JS代码p:commandLink,它对我非常有用(别忘了将“更新”设置为@none,将“进程”设置为@this):


函数刷新页面(){
AjaxRequest('/KaskoCalculator/polies/polis.jsf',{formId:'polisForm',async:false,global:true,源代码:'polisForm:doRefresh',进程:'polisForm:doRefresh',更新:'@none'});
}

因此,在新窗口中保存并打开报告后,初始页面将在2秒钟内刷新。太难看,太累赘了,但对我来说很有效。可能对任何人都有帮助。

我也面临同样的问题。 使用p:commandLink或目标为空的h:commandLink,打开新窗口后,初始页面支持bean数据将消失

刷新将返回到页面的初始状态,而不进行ajax更新。但是我需要在单击print命令之前保持相同的状态

public Object doReportPrint() {        
    if (canEdit() && this.submit() == null) {
        return null;
    }
    context().getExternalContext().getSessionMap().put("justUpdatedPolisId", entity.getId());        
    return "printReport";
}
public Object doRefresh() {
    Object justUpdatedPolisId = context().getExternalContext().getSessionMap().get("justUpdatedPolisId");
    if (justUpdatedPolisId != null) {
        entity.setId((Long)justUpdatedPolisId);
        context().getExternalContext().getSessionMap().remove("justUpdatedPolisId");
        return "save";
    }
    // If for some reasons we have not found it - moving to polises table
    return "polises?faces-redirect=true";
}
<script type="text/javascript"> 
   function refreshPage() {
                        PrimeFaces.ajax.AjaxRequest('/KaskoCalculator/polises/polis.jsf',{formId:'polisForm',async:false,global:true,source:'polisForm:doRefresh',process:'polisForm:doRefresh',update:'@none'});
                        }
   </script>