简体   繁体   English

JSF 2.0:在呈现视图之前未更新数据

[英]JSF 2.0: data not updated before the view is rendered

In my application, I have the following beans: 在我的应用程序中,我有以下bean:

@Named(value = "mrBean")
@SessionScoped
public class MrBean implements Serializable {

    @EJB
    private MrsBean mrsBean;

    private Item item;

    public void updateItem() {
        this.item = mrsBean.updateItem(item.getId());
    }

}

@Named(value = "itemBean")
@RequestScoped
public class itemBean {
    @Inject
    private MrBean mrBean;

    @PostConstruct
    public void init() {
        if (FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("update") != null) mrBean.updateItem();
    }
}

Before showing the item's information on the ViewItem.xhtml page, I will check if the update parameter is submitted to update the item before showing. ViewItem.xhtml页面上显示项目信息之前,我将检查是否提交了update参数以在显示之前更新项目。

When I test the page with the parameter update=true , I have no idea why the old data was rendered instead of the new updated one. 当我使用参数update=true测试页面时,我不知道为什么旧数据被渲染而不是新更新的数据。 In fact, I have to refresh the page before the new data is rendered. 实际上,我必须在呈现新数据之前刷新页面。

From the above result, I wonder if the @PostConstruct method was called after the view was rendered. 从上面的结果,我想知道在渲染视图后是否调用了@PostConstruct方法。

I'd be very grateful if you could give me an advice. 如果你能给我一个建议,我将非常感激。

Best regards, 最好的祝福,

That can happen if #{itemBean} is been referenced for the first time in the view after #{mrBean.item} . 如果可能发生#{itemBean}是已经在视图第一时间引用#{mrBean.item} Eg 例如

#{mrBean.item}
...
#{itemBean}

The managed beans are constructed for the first time when an EL expression references it for the first time and it does not exist in the scope yet. 当EL表达式第一次引用它时,托管bean首次构建,并且它尚未在范围中存在。 On a GET request wherein the managed bean instance is not referenced by a taghandler attribute or a f:event , then it would only be constructed during the render response. 在GET请求中,其中托管bean实例未被taghandler属性或f:event引用,那么它将仅在呈现响应期间构造。

If rearranging them so that the #{itemBean} is always referenced (and thus constructed) before #{mrBean.item} is been referenced is not possible, then better make the @PostConstruct of #{itemBean} a <f:event type="preRenderView"> instead. 如果重排它们,使得#{itemBean} 之前总是引用(和如此构造) #{mrBean.item}是被引用是不可能的,那么较好的使@PostConstruct#{itemBean}一个<f:event type="preRenderView">而不是。

<f:event type="preRenderView" listener="#{itemBean.init}" />

I'm posting another solution just in case it helps you. 我正在发布另一个解决方案以防万一它可以帮到你。 You can try a different approach by invoking an initialization method each time the page is going to be rendered and avoid having a request bean to do the update. 您可以通过在每次要呈现页面时调用初始化方法来尝试不同的方法,并避免让请求bean进行更新。 Add this metadata tag to your xhtml: 将此元数据标记添加到xhtml:

<f:metadata>
    <f:event type="preRenderView" listener="#{mrBean.init}" />
</f:metadata> 

And in your MrBean, define this method: 在你的MrBean中,定义这个方法:

public void init() {
    if(!FacesContext.getCurrentInstance().isPostback() && FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("update") != null) 
        mrBean.updateItem();
}

This way, the updateItem check will be done every time the ViewItem page is rendered. 这样,每次呈现ViewItem页面时都会执行updateItem检查。 If your MrBean was ViewScoped instead of SessionScoped I would have suggested to use a @PostConstruct annotation instead. 如果您的MrBean是ViewScoped而不是SessionScoped,我建议使用@PostConstruct注释。

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

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