Great discussion. Thanks guys. I will follow up on your pointers.

FYI, here's the original code that was doing the double database hit for me. 
Note that in this version I was using JSP as the view handler and had to use 
Trinidad tags to get the repeater functionality that I needed. Perhaps, I need 
to change my thinking on when the database should be hit. This is where I liked 
the concepts suggested in 
http://bugs.sakaiproject.org/confluence/pages/viewpage.action?pageId=4981&showComments=true
 (as reffered in the earlier post by Tom Innes on this subject). Haven't tried 
it yet.

Page A:
(see tr:commandLink below, populates forumDetailsBean.forumId from 
forumListBean.forums):

<h:form>
    <div id="List">
        <tr:forEach var="forum" items="#{forumListBean.forums}">
            <f:verbatim><h2></f:verbatim>
            <tr:commandLink immediate="true" text="#{forum.title}" 
action="showForum">
                <tr:setActionListener
                    from="#{forum.id}"
                    to="#{forumDetailsBean.forumId}"/>
            </tr:commandLink>
            <f:verbatim></h2></f:verbatim>
            <div class="ForumPreview">
                <tr:outputText value="#{forum.description}" />
            </div>
        </tr:forEach>
    </div>
</h:form>

Page B:
(uses forumDetailsBean only)

<f:verbatim><h2></f:verbatim>
    <h:outputText value="#{forumDetailsBean.forum.title}" />
<f:verbatim></h2></f:verbatim>

ForumListBean:
Here is the lazy loading call to the service in an accessor. This is the one 
that is called twice.

    public ForumVO[] getForums() {
        if (forums == null) {
            forums = getForumService().getAllForums();
        }
        return forums;
    }

ForumDetailsBean:
Here I need to initialize forumId, so that forum details can be lazy loaded 
when needed.

public class ForumDetailsBean {
    // ----- Attributes -----
    private Long forumId;
    private ForumDetailsVO forum;

    // ----- Accessors -----
    public Long getForumId() {
        return forumId;
    }
    public void setForumId(Long forumId) {
        this.forumId = forumId;
    }

    public ForumDetailsVO getForum() {
        if (forum == null) {
            forum = getForumService().getForumDetails(forumId);
        }
        return forum;
    }
    ...
}

Naresh 
________________________________________
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Craig McClanahan
Sent: Thursday, November 30, 2006 12:54 AM
To: MyFaces Discussion
Subject: Re: Saving state in page


On 11/29/06, Simon Kitching <[EMAIL PROTECTED]> wrote:
Craig McClanahan wrote:
>
>
> On 11/29/06, *Naresh Bhatia* <[EMAIL PROTECTED]
> <mailto:[EMAIL PROTECTED] >> wrote:
>
>     Hi Simon,
>
>     Thanks for a quick response.
>
>     When I said "navigates through a link", I had first tried h:commandLink.
>     However, as you mention below, it was posting back to page A and causing 
>     an unnecessary database read (I was doing lazy loading in my bean and
>     since this was a brand new bean, it was hitting the DB for no good
>     reason).
>
>
> FWIW, this is the kind of use case that Shale[1] tries to solve with the 
> view controller paradigm.  The idea is that you put logic like this
> database lookup into the prerender() method of the backing bean, which
> will only be called if *this* is the view that will be rendered, not if 
> you navigated to somewhere else instead.
>
> Craig
>
> [1] http://shale.apache.org/

Is what you describe what Naresh really wants? I though he simply wants 
a link on the page that navigates to another page without any logic
being processed on the backing bean for the current page.

Shale's view controller can be very useful, and can certainly be used as
you describe to avoid performing database access until the render phase, 
but that's not quite the same thing.

WIthout seeing the actual code its impossible to know for sure, but I've seen 
*lots* of people do database lookups like this in the constructor of their 
backing beans, where it's going to get executed whether you need it (because 
you are going to redisplay the current page) or not (because you are going to 
navigate somewhere else instead).  I read into his comment about the wasted 
database access that he was doing something like this -- which gets bypassed 
when you use hyperlinks (or <h:outputLink> to navigate between pages, instead 
of something like <h:commandLink> which submits the form (and therefore goes 
through the JSF lifecycle) on the current page. 

The view controller solution still executes "logic" on the submitted-to page 
... the trick is to only execute the database query when you need it.  And, it 
solves his other complaint, of keeping the navigation logic centralized in the 
navigation rules configuration, rather than being spread out across all the 
pages. 
Regards,

Simon

Reply via email to