myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leonardo Uribe <>
Subject [core] discussion about stateless jsf implementation
Date Tue, 21 Feb 2012 00:04:54 GMT

I have been studying the proposed code attached to MYFACES-3465.
Unfortunately, I have found some issues with the related code that
needs to be discussed under dev list. The code has the following

- It uses request uri to mark the views instead viewId. This causes
when multiple POST are chained with stateless views, a
ViewExpiredException is thrown. It is known there's a difference about
how myfaces and mojarra deals with viewId, which were clarified in JSF
2.1, with the introduction of ViewHandler.deriveLogicalViewId(). So
instead use request uri as the marker, a combination of
viewId/deriveLogicalViewId() should be used.

- Instead use vdl.buildView() call, it replaces it with
com.rits.cloning.Cloner, to duplicate the view and use it on the
current request. I think in this case, vdl.buildView() will be faster
and more optimal from memory perspective, because we can cache
information at Facelet/TagHandler/TagAttribute level like
ValueExpressions, attribute values and others, and a deep clone will
create unnecessary objects each time. Comparing MyFaces and Mojarra,
our implementation of vdl.buildView() is very fast, and for cases when
the view is has no dynamic parts it is only built once, so from
MyFaces perspective the is not visible difference here (but from
Mojarra you can see a difference). This means we don't really need the
cache proposed at all. Sometimes less is more.

- Some synchronized blocks can slow down performance without need (by
thread contention), and I have found other bugs when the code deals
with high concurrency.

Anyway, the trick is good enough, in cases where you don't want to
deal with view state load, even if with the changes done over the time
in that part until 2.1.6 have made view state very small. It is an
easy way to say to the state manager "... don't save the state for
this view ...".

After looking the code, I think we could add this as an built-in
specific feature for MyFaces Core, rather than a subproject.

Anyway, I have an idea that we can do for enhance performance in a
significant way.

In theory, we can classify JSF views into two groups

- static view: views that as an invariant always has the same
structure and state once vdl.buildView and render code is called for
first time.
- dynamic views: views that has some parts that change according to
expressions (c:if ....) in vdl.buildView or has programatically added
components based on conditions when the render code is called for
first time.

Also we can classify JSF views into another two groups

- stateful: Requires to store some data on the view to work after
markInitialState is called.
- stateless: Does not require to store anything on the state, because
we can duplicate it safely just calling vdl.buildView().

There is a lot of views that on the first request, or in other words,
when the view is created by first time and then rendered does not
change. The rendered page could change, but the view tree itself do
not. Later, on further postbacks, the view state might change for both
stateful and stateless views.

Here is the trick, if by some way we can make the component tree
"thread safe" making it immutable and moving some temporal variables
(clientId, rowIndex, dataModel, ...) from the component to
FacesContext attribute map, we could use the same view across multiple
requests. Then, on a postback (normal submit or ajax), we can build
the view as usual. This would involve some changes over
UIComponentBase/UIData/UIRepeat internals, to switch between
thread-safe or immutable mode and normal mode, and we could expect
more calls over FacesContext.getCurrentInstance() because we can't
cache FacesContext at UIComponent level, but it will work. A fast
proof-of-concept test done shows a big improvement, because we can
skip vdl.buildView in some cases and reducing memory usage. Obviously
there will be a lot of component that will not support that mode.
Anyway, it will not be an easy trick.

Suggestions are welcome.


Leonardo Uribe

View raw message