Thanks Anissa for this good detailed description. Here's some more info
on the "why" it's this way...
redirect() -- Causes the "browser" to submit a 2nd request to retrieve
the next page.
Since this is a separate request, request parameters may be added to
the URL that you are requesting. It also means that it is not the
first request -- i.e. your request attributes will be gone. The
browser treats all urls as relative to the current page it knows
about... so yes, it will be relative. Java applications have the
concept of a "context root" which makes urls that start with "/"
sometimes confusing. Since the context-root should not be
hard-coded in the app (in most cases), it may be useful to add a
handler to help generate a full path that includes the context-root
-- a redirect will need this for absolute paths.
navigate() -- The server renders the next page during the current request.
The same request that processes the "navigate()" handler will be
sending the response. So while processing the response, the request
attributes are still available -- request attributes live until the
request ends. The request *parameters* (i.e. QUERY_STRING
parameters, or "?paramName=paramVal&another=something" types of
parameters), cannot be added to a request. The Servlet API's do not
allow this. So you may not add these types of parameters. You can
work-a-round this by passing via request attributes, pageSession,
session, or application as appropriate. The navigate handler takes
a "viewId" which, as Anissa pointed out, is relative to the
context-root.
As for beforeCreate events, this event only gets fired during
*creation* not during refresh. Use *initPage* if you need to fire
the event every request (including refresh). Navigating to the same
page may reuse the page and therefor not call beforeCreate(). If
you are seeing that beforeCreate is not called ever when using
navigate()... then this is a bug and should be filed! I don't think
this is the case.
Thanks Anissa... these are great points!
Ken
Anissa Lam wrote:
> Hi,
> I just want to share with you something that i observed with using
> navigate() and redirect() handler. They behave quite differently and
> you may want to decide which is the right one for you when you need to
> go to another page.
> Here is what i observed:
>
> - redirect() :
> the attribute you set before calling this will *NOT* be available
> at the new page
> the request parameter will be available though
> the page parameter that you specify has to be relative from the
> page you are on. You can't use absolute path or assuming it starts
> from context root.
>
> - navigate(): just the opposite of redirect,
> - the request attribute will be available
> - the request parameter will *NOT* be available.
> - if you get to this page via a navigate, any attribute you set
> during a <!beforeCreate> of the page will lost before it even get to
> the <!beforeEncode>. To avoid this problem, try to set your
> attributes in <!beforeEncode> unless you absolutely need that for
> creating the components.
> - the page parameter is from context root.
>
> I spent quite some time playing with these in order to be able to show
> errors in admingui.
> I have attached a testNavigate.jsf that shows you the above findings.
>
> thanks
> Anissa.
> ------------------------------------------------------------------------
>
>
> <sun:page id="page1">
> <!beforeCreate
> setPageSessionAttribute(key="nextPage" value="testNavigate.jsf");
> println(value="before Create : nextPage = '#{nextPage}', errorSummary = '#{errorSummary}'" );
> />
>
> <!beforeEncode
> println(value="before Encode : nextPage = '#{nextPage}', errorSummary = '#{errorSummary}'" );
> />
>
> <sun:html id="html2">
>
> <sun:alert id="pageAlert" type="error" summary="#{errorSummary}" /> "<br /><br />
>
> <sun:staticText text="Request Parameter foo ='$requestParameter{foo}'" /> "<br /><br />
> <sun:form id="propertyForm">
> <sun:button text="Navigate, nextPage=#{nextPage} ,error attr persist but request param is lost" id="navigate" >
> <!command
> println(value="Using Navigate");
> setAttribute(key="errorSummary" value="Since you come here using Navigate, Error is going to occur no matter which button you select. nextPage attribute is lost.");
> navigate(page="#{nextPage}?foo=BAR");
> />
> </sun:button>
>
> "<br /><br />
>
> <sun:button text = "Redirect nextPage=#{nextPage}, error attr is lost, but request param is there" >
> <!command
> println( value="Using Redirect");
> setAttribute(key="errorSummary" value="summary before Redirect, you will never see this !!! ");
> redirect(page="#{nextPage}?foo=BAR");
> />
> </sun:button>
>
> </sun:form>
> </sun:html>
> </sun:page>
>