My goal is to keep session size as small as possible. (Why?.. it's other topic). What I have is Phase listener declared in faces-config.xml
<lifecycle>
<phase-listener>mypackage.listener.PhaseListener</phase-listener>
</lifecycle>
I want to save all other views, except the last one(maximum two) , in some memcache. Getting the session map:
Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();
in beforePhase(PhaseEvent event) method is giving me access to all views. So here I could save all views to the memcache and delete them from the session. The question is where in jsf these views that are still loaded in the browser are requested so that I can refill with this view if it's needed. Is it possible at all? Thank you.
To address the core of your question, implement a
ViewHandler
, within which you can take control of theRESTORE_VIEW
andRENDER_RESPONSE
phases/processes. You'll save the view during theRENDER_RESPONSE
and selectively restore, during theRESTORE_VIEW
phase. Your view handler could look something like the followingSimply plug in your custom viewhandler, using
Of course, you probably don't want to give this treatment to all your views; you're free to add any conditions to the logic above, to implement conditional view-saving and restoration.
You should also consider other options. It appears that you're conflating issues here. If your true concern is limit the overhead associated with view processing, you should consider
Stateless Views, new with JSF-2.2. The stateless view option allows you to exclude specific pages from the JSF view-saving mechanism, simply by specifying
transient="true"
on thef:view
. Much cleaner than mangling theUIViewRoot
by hand. The caveat here is that a stateless view cannot be backed by scopes that depend on state-saving, i.e.@ViewScoped
. In a stateless view, the@ViewScoped
bean is going to be recreated for every postback. Ajax functionality also suffers in this scenario, because state saving is the backbone of ajax-operations.Selectively set mark components as
transient
The transient property is available for allUIComponents
, which means, on a per-view basis, you can mark specific components withtransient="true"
, effectively giving you the same benefits as 1) but on a much smaller scope. Without the downside of no ViewScopedEDIT: For some reason,
UIViewRoot#getViewId()
is not returning the name of the current view (this might be a bug). Alternatively, you can use