0

I'm experimenting with JSF scopes, and have some issues when using a session scoped bean within a request scoped bean.

The basic workflow is that the user would click a View button on an item from the home page, which then calls my code to load & display that item's information.

Here's my UPDATED code:

@ManagedBean(name="itemViewBean")
@RequestScoped
class ItemViewBean {
    @ManagedProperty("#{itemBean}")
    private ItemBean itemBean;

    private ItemViewObject itemViewObject;
    private int itemId;

    public void init() {
         itemViewObject = itemBean.readItem(itemId);
    }

    public String readItem(int itemId) {
     //     itemViewObject = itemBean.readItem(itemId);  // moved to init();
          return "/pages/viewItem.xhtml?faces-redirect=true";
    }

    public ItemViewObject getItemViewObject() {
          return itemViewObject;
    }

    // getters & setters as needed

}

@ManagedBean(name="itemBean")
@SessionScoped
class ItemBean {
    public ItemViewObject readItem(int itemId) {
        // hardcoded creating a ItemViewObject for now.
        // eventually would be loaded from the database.
        ....
    }
}

My UPDATED view page then has things like:

<!-- added the metadata -->
<f:metadata>
    <f:viewParam name="id" value="#{itemViewBean.itemId}" />
    <f:event listener="#{itemViewBean.init}" type="preRenderView" />
</f:metadata>

<!-- same as before -->
<h:outputText value="#{itemViewBean.itemViewObject.description}" />

If my viewBean is request scoped (or view scoped), I get empty data on the view page. If the viewBean is session scoped, things work. And I'm not understanding why?

From what I see in my debugger, readItem(itemId) is called (from the home page when clicking a view button), but when the view page itself calls the getItemViewObject(), the itemViewObject is null.

What am I doing wrong?

UPDATE I forgot to mention earlier how my home page was calling readItem method, and that was through a command button:

<h:commandButton class="btn btn-mini firefoxBtnMiniCorrection"
    value="View"
    action="#{itemViewBean.readItem(b.itemId)}"/>

Each item listed in the home page has its own View button.

Also forgot to mention that both the home page and my view page are using JSF Templates. I don't know if that matters.

From the comments below which people have made, I came up with the code changes above. And things work now. Using either request scope or view scope with ItemViewBean works now.

And I am surprised this worked! I'm not quite certain I fully understand why it works.

Are my changes the correct way to do things? Or is there a better way?

Also, I'm using JSF 2.1.

Update 2 It doesn't work. The scoping works, but I discovered that the itemId in the viewParam is always null. Why?

Cœur
  • 37,241
  • 25
  • 195
  • 267
Chris
  • 391
  • 2
  • 4
  • 15
  • I personally don't like this kind of flow. Why do you really need to have this kind of data in session? If you're going to display it for a specific view, just load it in the `@ViewScoped` bean. The method which loads the initial data for the view should be called [through a `f:viewAction` binding](https://stackoverflow.com/a/6377957/1199132), this ensures it is called only once, thus not making unecessary calls to the DB. – Aritz Apr 29 '18 at 16:19
  • @XtremeBiker Thanks. Based on the post you sited, plus looking at an article from BalusC, I updated the code above. And things work. Is there any other way, or better way, to do this? Thanks again! – Chris Apr 30 '18 at 15:50
  • this was the [article](http://balusc.omnifaces.org/2011/09/communication-in-jsf-20.html#ProcessingGETRequestParameters) from @BalusC I was looking at. – Chris Apr 30 '18 at 15:55

1 Answers1

0

itemViewObject is private in a RequestScoped bean. After readItem() got a value for itemViewObject, this value will be forgotten after this request and will be null at the next request (`@RequestScoped').

Holger
  • 899
  • 2
  • 7
  • 12