Re: [ajax] UIViewRoot and (optimized) custom lifecycle

2008-02-25 Thread Martin Marinschek
Bug in the spec ;)

regards,

Martin

On Fri, Feb 22, 2008 at 6:35 PM, Matthias Wessendorf [EMAIL PROTECTED] wrote:
 Hi,

  it can be the case, that this mail may be a bit long..., but the main
  question I think is:
  Is there a public getPhaseListeners() method missing on UIVIewRoot ?

  Some general information since JSF 1.2... there is a public
  addPhaseListener() on UIViewRoot.
  So you can register a PhaseListener with the current view root (per
  view) to have beforePhase and afterPhase called
  on these lifecycle phases:
  -ApplyReqValue
  -processValidation
  -UpdateModel
  -Invoke App
  -RenderResponse

  You can add such a PL (PhaseListener) via the mentioned Java API or:
  f:phaseListener type=blah.MyPL /
  (this internally uses the Java API )

  Fine.

  now when you render a page and do a (regular) postback the
  phaselistener (its methods...) is executed.
  Fine.

  Now the ajax scenario.

  Some libraries (like ADF Faces Rich Client or Apache MyFaces
  Tobago(not Trinidad ;-) )) offer a custom lifecycle to call the
  lifecycle methods (such as processXyz()) only
  on the components, that are part of the ajax postback (why doing a
  decode on not effected components?).

  we do it like:
  uiViewRoot.invokeOnComponent(context, clientId, callback);

  where the *callback* is something like:
  static private class UpdateModelValuesCallback implements ContextCallback
  {
   public void invokeContextCallback(FacesContext context,
 UIComponent target)
   {
 target.processUpdates(context);
   }
  }

  usually these *optimized* lifecycles offer optimization for these phases:
  -ApplyReqValue
  -processValidation
  -UpdateModel

  not on:
  -Invoke App
  -RenderResponse

  For these, we just do a delegate back to the standard (default) behavior, 
 like:
  viewRoot.processApplication(context);

  So now the processXyz (like processUpdates()) is only! called on
  the ajax components!
  (Tobago does that in a similar way. They *fake* invokeOnComponent,
  since that lib is JSF 1.1 based)

  What does that mean, when submitting an ajax postback (maybe triggered
  by inputText autoSubmit=true /) ?
  The (to uiviewRoot) attached PL is only invoked for these phases:
  -Invoke App
  -RenderResponse

  Why?
  The big problem (IMO) is, that the PhaseListener(s) attached to the
  current (per view) UIViewRoot are *triggered* by the processXyz() of
  UIViewRoot itself (and encodeEnd and encodeBegin for RenderResponse phase).
  So... when only invoking them on the effected ajax components the
  before/afterPhase is never triggered (for the optimized phase).

  The optimized lifecycle could get the attached PhaseListeners, in case
  there where a public getPhaseListeners() method on UIViewRoot.
  I am wondering why there is none ? Simply forgotten?

  Please note, that (also since JSF 1.2) you can register methodExpression 
 like:
  f:view beforePhase=#{methodExpression} 
 afterPhase=#{otherMethodExpression}

  but... there is acutally a public getBeforePhaseListener() and a
  getAfterPhaseListener() as well.
  So a optimized lifecycle could get these MethodExpressions.

  What is your take on that?

  Thanks for reading,
  Matthias

  --
  Matthias Wessendorf

  further stuff:
  blog: http://matthiaswessendorf.wordpress.com/
  sessions: http://www.slideshare.net/mwessendorf
  mail: matzew-at-apache-dot-org




-- 

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces


[ajax] UIViewRoot and (optimized) custom lifecycle

2008-02-22 Thread Matthias Wessendorf
Hi,

it can be the case, that this mail may be a bit long..., but the main
question I think is:
Is there a public getPhaseListeners() method missing on UIVIewRoot ?

Some general information since JSF 1.2... there is a public
addPhaseListener() on UIViewRoot.
So you can register a PhaseListener with the current view root (per
view) to have beforePhase and afterPhase called
on these lifecycle phases:
-ApplyReqValue
-processValidation
-UpdateModel
-Invoke App
-RenderResponse

You can add such a PL (PhaseListener) via the mentioned Java API or:
f:phaseListener type=blah.MyPL /
(this internally uses the Java API )

Fine.

now when you render a page and do a (regular) postback the
phaselistener (its methods...) is executed.
Fine.

Now the ajax scenario.

Some libraries (like ADF Faces Rich Client or Apache MyFaces
Tobago(not Trinidad ;-) )) offer a custom lifecycle to call the
lifecycle methods (such as processXyz()) only
on the components, that are part of the ajax postback (why doing a
decode on not effected components?).

we do it like:
uiViewRoot.invokeOnComponent(context, clientId, callback);

where the *callback* is something like:
static private class UpdateModelValuesCallback implements ContextCallback
{
  public void invokeContextCallback(FacesContext context,
UIComponent target)
  {
target.processUpdates(context);
  }
}

usually these *optimized* lifecycles offer optimization for these phases:
-ApplyReqValue
-processValidation
-UpdateModel

not on:
-Invoke App
-RenderResponse

For these, we just do a delegate back to the standard (default) behavior, like:
viewRoot.processApplication(context);

So now the processXyz (like processUpdates()) is only! called on
the ajax components!
(Tobago does that in a similar way. They *fake* invokeOnComponent,
since that lib is JSF 1.1 based)

What does that mean, when submitting an ajax postback (maybe triggered
by inputText autoSubmit=true /) ?
The (to uiviewRoot) attached PL is only invoked for these phases:
-Invoke App
-RenderResponse

Why?
The big problem (IMO) is, that the PhaseListener(s) attached to the
current (per view) UIViewRoot are *triggered* by the processXyz() of
UIViewRoot itself (and encodeEnd and encodeBegin for RenderResponse phase).
So... when only invoking them on the effected ajax components the
before/afterPhase is never triggered (for the optimized phase).

The optimized lifecycle could get the attached PhaseListeners, in case
there where a public getPhaseListeners() method on UIViewRoot.
I am wondering why there is none ? Simply forgotten?

Please note, that (also since JSF 1.2) you can register methodExpression like:
f:view beforePhase=#{methodExpression} afterPhase=#{otherMethodExpression}

but... there is acutally a public getBeforePhaseListener() and a
getAfterPhaseListener() as well.
So a optimized lifecycle could get these MethodExpressions.

What is your take on that?

Thanks for reading,
Matthias

-- 
Matthias Wessendorf

further stuff:
blog: http://matthiaswessendorf.wordpress.com/
sessions: http://www.slideshare.net/mwessendorf
mail: matzew-at-apache-dot-org