JSF 2.0: data not updated before the view is rendered

Refresh

February 2019

Views

1.2k time

1

In my application, I have the following beans:

@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.

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. 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.

I'd be very grateful if you could give me an advice.

Best regards,

2 answers

1

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. Add this metadata tag to your xhtml:

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

And in your MrBean, define this method:

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. If your MrBean was ViewScoped instead of SessionScoped I would have suggested to use a @PostConstruct annotation instead.

2

That can happen if #{itemBean} is been referenced for the first time in the view after #{mrBean.item}. E.g.

#{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. 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.

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.

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