Leonardo,
While I understand more can be done with respect to stateless
and also the view pooling you mentioned my goal was to limit
the changes required to a minimum while still satisfying the
wishes of our community as expressed by the specification
issue.
@ViewScoped
With respect to @ViewScoped I don't think it's appropriate to
make @ViewScoped work with this limited proposal since, by
definition, the developer is agreeing to a stateless view.
Poolable views
While I like to be able to see this to become part of the
specification I think to tackle this now is too large of an
undertaking with too many unknowns.
I hope you can sign off on the limited scope so we can get it
as it stands into the 2.2 release, and then we will address the
other changes in the next release.
Kind regards,
Manfred
On 2/25/2013 10:56 PM, Leonardo Uribe wrote:
> Hi
>
> At first view it sounds like a good idea, but looking in deep there are some
> details that makes me doubt about the convenience of use "transient"
> attribute, and instead use an specific attribute for this one.
>
> In few words, the problem is @ViewScope uses an structure stored in the
> view attribute map to hold the state, so inside UIViewRoot we have two
> separate states:
>
> - The state related with UIViewRoot component itself.
> - The state related with @ViewScope.
>
> In this moment we have 3 methods:
>
> public void restoreState(FacesContext context, Object state)
> public Object saveState(FacesContext context)
> /**
> * @since 2.2
> **/
> public void restoreViewScopeState(FacesContext context, Object state)
>
> If "transient" attribute is used, saveState() will be skipped, and the
> view scope will not work.
>
> Why use something like "transient" attribute? the justification is that
> with an attribute it is possible to just skip save/restore logic and make
> the request a little bit faster. I have measured the time spent and in
> my opinion the gain is small compared with the time spent rendering
> the view or inclusive building the view.
>
> Probably the right thing to do is provide a new method to save the
> view scope state, so "transient" flag only takes effect over UIViewRoot
> component state.
>
> I still have doubts about if it is convenient to use "transient" flag
> in practice, because the evidence suggest that the calculation of
> the view state is quite cheap, and the side effects that can be
> introduced by the user without warning when using components that relies
> on the state can be negative. Why? because it suppose the user should
> know which components can be used in "stateless" mode and which others
> should not be used, and that goes against encapsulation principles
> (you shouldn't worry about how a component implements its logic).
>
> Anyway, it seems to be there is an "audience" that strongly wants something
> like this just to say "... JSF has a stateless mode and in that way it has
> nothing to be afraid about other stateless web frameworks from performance
> perspective ...". But in reality, "... JSF takes care about stateful/stateless
> logic for you, so in that sense it is a far more advanced technology and it
> performs pretty well from performance perspective even against stateless
> frameworks ... ".
>
> In my opinion, if the people really wants something like this we should do
> it, but from performance perspective it is more interesting to change the
> spec just a little bit to allow "Poolable Views".
>
> The concept has been already studied and there is a prototype for MyFaces
> here:
>
> http://markmail.org/message/54rb3aphc6txwzbr
>
> "... In few words, the proposal is go "Beyond JSF Stateless Mode", and instead
> blame the state, make it your friend. Let's just take advantage of the
> stateful nature of JSF to allow reuse views fully or partially. ..."
>
> The interesting part of this study is to make it feasible, the only change
> we really need into JSF spec is introduce a way to reset the state, doing
> some changes over UIComponent.saveState() method.
>
> In theory there are two kinds of reset:
>
> - RESET_MODE_SOFT : Clear only all transient state (datatable model,
> transient attributes, view listeners, ...)
> - RESET_MODE_HARD : Clear transient state and restore the component to
> the state it was before the call to markInitialState().
>
> The idea is add some methods in UIViewRoot:
>
> int getResetSaveStateMode()
> void setResetSaveStateMode(int resetMode)
>
> public boolean isPoolable();
> public void setPoolable(boolean poolable);
>
> And in UIComponent.saveState() implementations check this flag and do what's
> necessary:
>
> public Object saveState(FacesContext context)
> {
> //1. Check the reset flag
> ...
> //2. If there is a soft reset clear transient data, calculate the delta
> // state as usual and return it.
> ...
> //3. If there is a hard reset, clear transient data and the state, and
> // calculate the delta state if applies. If the hard reset cannot be
> // done, just do the usual, calculate the delta and return it.
> ...
> //4. If no reset flag do the usual.
> ...
> }
>
> Maybe add some methods in StateHelper to deal with this logic:
>
> public Object resetHardState(FacesContext context)
> public Object resetSoftState(FacesContext context)
>
> And that's it. With these changes, it is possible to create a reusable view
> pool for JSF. The only limitation is that on navigation, the views cannot be
> put on the pool because a broadcast is in progress so the reset does not work
> correctly, but we can go further in this part doing some changes over how
> navigation works and reuse a view across navigations if we just make a
> "deferred navigation", which means do not do the navigation directly on the
> default ActionListener, just add a flag, let the broadcast ends and before
> the phase ends do the navigation.
>
> The limitations of this technique is that PostAddToViewEvent is not executed
> at each request, so some tricks that worked before when creating dynamic views
> will not work, but in most cases it will work.
>
> The hack is promising, but there was a discussion about this topic in MyFaces
> dev list:
>
> http://markmail.org/message/pc42cbcvvhlboivb
>
> and the problem of include the code is mostly related to the spec. If this is
> not in the JSF spec, third party libraries will not implements what's
> necessary to make it work, so the scope of the hack will be limited only to
> MyFaces libraries or views using only components included in JSF by default.
>
> In conclusion:
>
> - +1 for include "transient" as an attribute of f:view, but add
> saveViewScopeState and keep view scope working even for transient views.
>
> - ++1 for allow poolable views in JSF, doing some hack like the one proposed
> here or something better.
>
> regards,
>
> Leonardo Uribe
>