How to save and get an idea when you need it

My goal is to keep the session size as small as possible. (Why? .. that's another topic). I have a phase listener declared in faces-config.xml

<lifecycle>
        <phase-listener>mypackage.listener.PhaseListener</phase-listener>   
</lifecycle>

      

I want to store all other views except the last one (maximum two) in some memcache. Getting the session map:

Map<String, Object> sessionMap = event.getFacesContext().getExternalContext().getSessionMap();

      

the beforePhase (PhaseEvent) method gives me access to all views. So here I can store all views in memcache and remove them from the session. The question is where in jsf these views, which are still loaded in the browser, are requested so that I can populate that view if needed. Is it even possible? Thank.

+3


source to share


1 answer


To solve the crux of your question, follow ViewHandler

where you can take control RESTORE_VIEW

and RENDER_RESPONSE

phases / processes. You will save the view during RENDER_RESPONSE

and selectively restore during the phase RESTORE_VIEW

. Your view handler might look something like this:

   public class CustomViewHandlerImpl extends ViewHandlerWrapper{

        @Inject ViewStore viewStore; //hypothetical storage for the views. Could be anything, like a ConcurrentHashMap
        ViewHandler wrapped;

        public CustomViewHandlerImpl(ViewHandler toWrap){          
           this.wrapped = toWrap;
        }

        public UIViewRoot restoreView(FacesContext context, String viewId) throws IOException{

            //this assumes you've previously saved the view, using the viewId

            UIViewRoot theView = viewStore.get(viewId);

            if(theView == null){

               theView = getWrapped().restoreView(context, viewId);              
            }

           return theView;       
        } 


      public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException, FacesException{

          viewStore.put(viewToRender.getId(),viewToRender);

          getWrapped().renderView(context, viewToRender);

      }

   }

      

Just connect your custom viewer using

<view-handler>com.you.customs.CustomViewHandlerImpl</view-handler>

      


Of course, you probably don't want this to appeal to all your views; you can add any conditions to the logic above to implement conditional save and restore.




You should also consider other options. It looks like you are running into problems here. If your true concern is limited to the overhead associated with processing views, you should consider

  • Statuses without statuses , new with JSF-2.2. The stateless view option allows you to exclude specific pages from the JSF prediction persistence engine simply by pointing transient="true"

    to f:view

    . Much cleaner than scolding UIViewRoot

    by hand. Caveat here is that the representation without the state can not be supported by the areas that depend on the state of economy, that is @ViewScoped

    . In a stateless view, the @ViewScoped

    bean will be recreated for every postback. Ajax functionality suffers in this scenario as well, since state persistence is at the heart of ajax operations.

  • Selectively set label components astransient

    Transient property is available to everyone UIComponents

    , which means that for each view, you can mark specific components with transient="true"

    , effectively giving you the same benefits as 1), but on a much smaller scale. No Reverse ViewScoped

EDIT . UIViewRoot#getViewId()

Doesn't return the name of the current view for some reason (this might be an error). Alternatively, you can use

ExternalContext extCtxt = FacesContext.getCurrentInstance().getExternalContext();
String viewName = ((HttpServletRequest)extCtxt.getRequest()).getRequestURI();  //use this id as the key to store your views instead

      

+4


source







All Articles