You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by "Leonardo Uribe (Created) (JIRA)" <de...@myfaces.apache.org> on 2011/11/22 01:39:39 UTC

[jira] [Created] (MYFACES-3404) Add windowId to server side state saving algorithm

Add windowId to server side state saving algorithm
--------------------------------------------------

                 Key: MYFACES-3404
                 URL: https://issues.apache.org/jira/browse/MYFACES-3404
             Project: MyFaces Core
          Issue Type: New Feature
            Reporter: Leonardo Uribe
            Assignee: Leonardo Uribe


>From dev list:

Hi

MS>> The ClientSideWindowHandler solution in CODI looks good so far, but there
MS>> is still a lot to do.

MS>> And like every technology, it has it's pros and cons...

MS>> What do you think about making the windowId provider pluggable in MyFaces
MS>> core first?

I have been thinking about every possible option we have for implement this and
the conclusion was the best way is make something like the hack done in CODI or
a "variant" of it, like the one described on:

http://wiki.apache.org/myfaces/Drafts/WindowId

(Mixed approach of the first prototype)

>From the point of view of MyFaces Core, any solution should be bound to the
renderkit in some way. So, windowId concept has sense to include it on the spec
but its implementation should be done according to the renderkit. If the
renderkit handles html, do the hack proposed but if is xml, do other thing
and so on. It sounds like something to do outside MyFaces Core. Basically the
problem is how to create an interface about something that could require
changes over the renderkit/viewhandler?.

Maybe we can minimize the problem, and provide an interface like this:

public interface WindowIdRenderKitAware
{
   public String getCurrentWindowId(FacesContext facesContext);
}

But let the details about how to "plug" all pieces inside CODI. MyFaces Core
just offer the "integration point", and the default algorithm just do what is
doing right now. Who should implement this interface? the renderkit, even if
in the implementation the value can be stored inside FacesContext attribute
map or request map. There exists a RenderKitWrapper interface, so it is
easy to create a wrapper for default HTML_BASIC renderkit or any other and
then scan through the wrappers and the first one implementing the interface
will be the choosen.

MS>> The REAL problem with JSF and multiple tabs is that once you open 2 tabs
MS>> and click in 1 of them often enough, then you will destroy the state of
MS>> the view in the other tab as well somewhen. Usually after 20 requests
MS>> (default).

 There are two points where this logic could be useful inside MyFaces Core :

1. Server side state
2. Flash scope

But in practice the only really relevant is 1. To implement 2. it is necessary
a "requestId". MyFaces FlashImpl uses a counter and store its value inside
a cookie. To fix this scope properly, the best is create a ExternalContext
wrapper and provide and alternate Flash object, but that sounds like something
that can be done outside MyFaces Core. If you are using CDI scopes, it sounds
reasonable to provide an alternate Flash scope in CODI.

If we can just modify the logic inside server side state to include "windowId"
concept, it will be enough.

MS>> To come over this, we need to store the n last views not only per session,
MS>> but also per browser tab (==windowId).
MS>> Of course, there can be lots of fancy stuff done to detect closed tabs,
MS>> etc. But all this is much more stable if we really have the opportunity
MS>> to distinguish between tabs. We can e.g. also introduce a configuration
MS>> for maximum allowed tabs, to reduce memory blasting.

Really since all state is stored in session, if the session is invalidated all
tabs are removed from memory. Basically we already have params for max number
of sessions and max number of logical sessions (which in fact can be seen
as "tabs"). So what we have right now is ok, we just need to include windowId
concept into the logic and that's it.

MS>> All this is actually completely independent of how the windowId get's
MS>> created and checked imo.

Yes, that's right.

MS>> I now tend to do the following (just atm creating a better playground
MS>> example in CODI + hack on the ClientSideWindowHandler):
MS>>
MS>> a.) the cookie thingy is pretty bääh. it just doesn't work if a
user clicks
MS>> quickly through a list and opens lots of 'detail pages' on different tabs
MS>> within 2 seconds.
MS>>
MS>> b.) it's currently a 'one or the other' thingy, and I now thought about
MS>> combining the lazyWindowIdDropp.js and the current windowhandler.js
MS>>
MS>> My current research goes into the direction of
MS>>
MS>> 1.) always adding the windowId to each and every link and transport the
MS>> windowId only via this parameter.
MS>>
MS>> 2.) For HTML5-browsers (detected via UserAgent) I render the
MS>> windowhandler.html intermediate page which does all the fancy stuff of
MS>> dynamically applying the old DOM on the intermediate page, etc. For other
MS>> clients we rely on the lazyWindowId script.

Ok, sounds promising. So, I'll focus on how to fix the logic for myfaces
core server side state saving
(org.apache.myfaces.renderkit.ServerSideStateCacheImpl), with the alternative
proposed in this mail (WindowIdRenderKitAware interface, and then use a
RenderKit wrapper).


The idea is doing this simple steps:

<faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
              xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" 
              version="2.0">

  <render-kit>
      <render-kit-id>HTML_BASIC</render-kit-id>
      <render-kit-class>org.apache.myfaces.renderkit.windowid.WindowIdRenderKitWrapper</render-kit-class>
  </render-kit>

</faces-config>

And writing a wrapper like this:

public class WindowIdRenderKitWrapper extends RenderKitWrapper implements WindowIdRenderKitAware
{
    
    private RenderKit delegate;

    public WindowIdRenderKitWrapper(RenderKit delegate)
    {
        super();
        this.delegate = delegate;
    }

    @Override
    public RenderKit getWrapped()
    {
        return delegate;
    }

    public String getCurrentWindowId(FacesContext facesContext)
    {
        return facesContext.getExternalContext().getRequestParameterMap().get("windowId");
    }
}

Allow server side state saving to get a windowId identifier to "chain" the views inside a window and use that logic to discard old views and prevent view expired exceptions.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

       

[jira] [Updated] (MYFACES-3404) Add windowId to server side state saving algorithm

Posted by "Leonardo Uribe (Updated) (JIRA)" <de...@myfaces.apache.org>.
     [ https://issues.apache.org/jira/browse/MYFACES-3404?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Leonardo Uribe updated MYFACES-3404:
------------------------------------

    Status: Patch Available  (was: Open)
    
> Add windowId to server side state saving algorithm
> --------------------------------------------------
>
>                 Key: MYFACES-3404
>                 URL: https://issues.apache.org/jira/browse/MYFACES-3404
>             Project: MyFaces Core
>          Issue Type: New Feature
>            Reporter: Leonardo Uribe
>            Assignee: Leonardo Uribe
>         Attachments: MYFACES-3404-1.patch
>
>
> From dev list:
> Hi
> MS>> The ClientSideWindowHandler solution in CODI looks good so far, but there
> MS>> is still a lot to do.
> MS>> And like every technology, it has it's pros and cons...
> MS>> What do you think about making the windowId provider pluggable in MyFaces
> MS>> core first?
> I have been thinking about every possible option we have for implement this and
> the conclusion was the best way is make something like the hack done in CODI or
> a "variant" of it, like the one described on:
> http://wiki.apache.org/myfaces/Drafts/WindowId
> (Mixed approach of the first prototype)
> From the point of view of MyFaces Core, any solution should be bound to the
> renderkit in some way. So, windowId concept has sense to include it on the spec
> but its implementation should be done according to the renderkit. If the
> renderkit handles html, do the hack proposed but if is xml, do other thing
> and so on. It sounds like something to do outside MyFaces Core. Basically the
> problem is how to create an interface about something that could require
> changes over the renderkit/viewhandler?.
> Maybe we can minimize the problem, and provide an interface like this:
> public interface WindowIdRenderKitAware
> {
>    public String getCurrentWindowId(FacesContext facesContext);
> }
> But let the details about how to "plug" all pieces inside CODI. MyFaces Core
> just offer the "integration point", and the default algorithm just do what is
> doing right now. Who should implement this interface? the renderkit, even if
> in the implementation the value can be stored inside FacesContext attribute
> map or request map. There exists a RenderKitWrapper interface, so it is
> easy to create a wrapper for default HTML_BASIC renderkit or any other and
> then scan through the wrappers and the first one implementing the interface
> will be the choosen.
> MS>> The REAL problem with JSF and multiple tabs is that once you open 2 tabs
> MS>> and click in 1 of them often enough, then you will destroy the state of
> MS>> the view in the other tab as well somewhen. Usually after 20 requests
> MS>> (default).
>  There are two points where this logic could be useful inside MyFaces Core :
> 1. Server side state
> 2. Flash scope
> But in practice the only really relevant is 1. To implement 2. it is necessary
> a "requestId". MyFaces FlashImpl uses a counter and store its value inside
> a cookie. To fix this scope properly, the best is create a ExternalContext
> wrapper and provide and alternate Flash object, but that sounds like something
> that can be done outside MyFaces Core. If you are using CDI scopes, it sounds
> reasonable to provide an alternate Flash scope in CODI.
> If we can just modify the logic inside server side state to include "windowId"
> concept, it will be enough.
> MS>> To come over this, we need to store the n last views not only per session,
> MS>> but also per browser tab (==windowId).
> MS>> Of course, there can be lots of fancy stuff done to detect closed tabs,
> MS>> etc. But all this is much more stable if we really have the opportunity
> MS>> to distinguish between tabs. We can e.g. also introduce a configuration
> MS>> for maximum allowed tabs, to reduce memory blasting.
> Really since all state is stored in session, if the session is invalidated all
> tabs are removed from memory. Basically we already have params for max number
> of sessions and max number of logical sessions (which in fact can be seen
> as "tabs"). So what we have right now is ok, we just need to include windowId
> concept into the logic and that's it.
> MS>> All this is actually completely independent of how the windowId get's
> MS>> created and checked imo.
> Yes, that's right.
> MS>> I now tend to do the following (just atm creating a better playground
> MS>> example in CODI + hack on the ClientSideWindowHandler):
> MS>>
> MS>> a.) the cookie thingy is pretty bääh. it just doesn't work if a
> user clicks
> MS>> quickly through a list and opens lots of 'detail pages' on different tabs
> MS>> within 2 seconds.
> MS>>
> MS>> b.) it's currently a 'one or the other' thingy, and I now thought about
> MS>> combining the lazyWindowIdDropp.js and the current windowhandler.js
> MS>>
> MS>> My current research goes into the direction of
> MS>>
> MS>> 1.) always adding the windowId to each and every link and transport the
> MS>> windowId only via this parameter.
> MS>>
> MS>> 2.) For HTML5-browsers (detected via UserAgent) I render the
> MS>> windowhandler.html intermediate page which does all the fancy stuff of
> MS>> dynamically applying the old DOM on the intermediate page, etc. For other
> MS>> clients we rely on the lazyWindowId script.
> Ok, sounds promising. So, I'll focus on how to fix the logic for myfaces
> core server side state saving
> (org.apache.myfaces.renderkit.ServerSideStateCacheImpl), with the alternative
> proposed in this mail (WindowIdRenderKitAware interface, and then use a
> RenderKit wrapper).
> The idea is doing this simple steps:
> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" 
>               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
>               xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd" 
>               version="2.0">
>   <render-kit>
>       <render-kit-id>HTML_BASIC</render-kit-id>
>       <render-kit-class>org.apache.myfaces.renderkit.windowid.WindowIdRenderKitWrapper</render-kit-class>
>   </render-kit>
> </faces-config>
> And writing a wrapper like this:
> public class WindowIdRenderKitWrapper extends RenderKitWrapper implements WindowIdRenderKitAware
> {
>     
>     private RenderKit delegate;
>     public WindowIdRenderKitWrapper(RenderKit delegate)
>     {
>         super();
>         this.delegate = delegate;
>     }
>     @Override
>     public RenderKit getWrapped()
>     {
>         return delegate;
>     }
>     public String getCurrentWindowId(FacesContext facesContext)
>     {
>         return facesContext.getExternalContext().getRequestParameterMap().get("windowId");
>     }
> }
> Allow server side state saving to get a windowId identifier to "chain" the views inside a window and use that logic to discard old views and prevent view expired exceptions.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira