Igor, again, thanks for the great writeup.  I have a few follow-up questions
for you or Matej, or anyone else who has had their hands dirty with the page
versioning / management stuff for 1.5.

So, in looking through the code, it appears that the automatic multi-window
support is gone (for now, at least; see http://tinyurl.com/2ut3mmd).  I
understand that a lot of it may not be needed any more because of the exact
situation you described.  But, it seems that one very useful purpose of it
is to allow you to partition the storage of pages per window, allowing X
number of pages in session per Y windows.  It also provided a convenient way
of partitioning session data, which I never personally did, but know several
clients who did, basically using a Map<String, SomeDataObject> where the key
was the page map name.  This provided them a sort of "conversation" scope.

Imagine that you want to allow a max of 7 pages per window, and you have the
following flow:

- start flow 1, page 1
- go to flow 1, page 2
- go to flow 1, page 3
- start a subflow in a new window (flow 2, page 1)
- go to flow 2, page 2
- go to flow 2, page 3 (and so on for several clicks)
- go to flow 1, page 7, where you are complete, and close the window
- now you're back on flow 1, and want to continue to page 4, but it's
expired because it's been at least 7 pages since you were last here

Previously, you could have supported this by doing this:

getSessionSettings().setMaxPageMaps(2);
getSessionSettings().setPageMapEvictionStrategy(new
LeastRecentlyAccessedEvictionStrategy(7));

In my limited estimation, I don't think this would be extremely difficult to
implement.  With my limited knowledge of the new page manager stuff, I think
you could do the following.  Igor (or Matej), could you confirm this theory?

- WebPage#PageMapChecker (linked to above) uses the same JS it was using,
and in the listener method, instead of cloning page and moving it to the new
page map (old functionality), it simply sets the new window name as metadata
on the page (it should also be renamed, but that's minor).
- the page manager keeps an internal Map<String, Collection<PageReference>>
that represents the different windows that are open
- wherever the expiration of old pages happens [1], you are given the
ability to expire based on a custom strategy; one strategy that is provided
is MaxPagesPerWindow strategy that takes X (pgs / wdw) and Y (max windows)

[1] - From looking through the code, it appears that each IDataStore is left
to implement this themselves.  In the case of IDataStore, it does it in
savePage(int, byte[]) by delegating to the PageWindowManager, which resets
its pointer to the beginning of the file if you've hit X pages.  For the
proposal above, I think this would have to be abstracted out of
PageWindowManager, and the IDataStore would ask a IExpirationStrategy if the
page should overwrite a previous one, similar to
what IPageMapEvictionStrategy was doing before.

What are your thoughts?  If my basic proposal above seems like it would
work, I would like to dig in and add this feature personally.  But, I want
to run it by those who have the experience in this section of the code
first.

One last question - it appears that there is no direct replacement for the
HttpSessionStore that previously existed.  There is InMemoryPageStore, but
that isn't public, and it says it's for testing only.  It seems that quite a
few people used HttpSessionStore because of their clustering configuration
or because of the lack of ability to write to the file system (i.e.
AppEngine, etc).  Is there a replacement for it?

-- 
Jeremy Thomerson
http://www.wickettraining.com

On Mon, Oct 18, 2010 at 12:02 PM, Igor Vaynberg <[email protected]>wrote:

> basically pagemaps are gone. this was made possible by changing how
> page versioning works and has resulted in much simpler code to both
> committers and clients.
>
> in 1.4.x a page has both id and version. id is assigned on page
> creation and version is incremented every time the page is tweaked.
> page history is kept as a series of undo objects. problems: undo
> objects are cumbersome to create and maintain. since IChange only has
> undo and not redo once we roll back a version there is no way to go
> back.
>
> lets take a look at how this effected simple things such as multi tab
> browsing:
>
> user loads page id 5 version 3 in browser tab 1.
> right clicks a link and clicks open in new tab.
> without multi tab support enabled
>    link handler executes, creates version 4
>    page id 5 version 4 opens in a new tab
>    user switches to old tab and clicks a link
>    page is reverted to version 3 because that is the version of the
> link in the old tab
>        version 4 that is open in tab 2 is evicted by the undo operation
>        new version 4 is created for the page in tab 1
>   user switches to tab 2, clicks, gets component not present or weird
> effect
> with multi tab support enabled
>    link handler executes, creates version 4
>    wicket detects page id 5 version 4 is opened in a new tab
>    wicket clones page into new pagemap
>    user interacts with new page in the new pagemap, page open in tab
> 1 is not affected.
>
> in 1.5.x there is no version, there is just the page id. whenever a
> user creates a change in a page that previously required a new version
> in 1.5.x we clone the entire page into one with a new page id.
> effectively creating a DAG of versions of a page as it is being
> modified.
>
> lets take a look at how this eliminates the need for complex code like
> multi tab support:
> user loads page id 5 in browser tab 1.
> right clicks a link and clicks open in new tab.
> link handler is invoked, modifies the page, page id is changed to 6
> page 6 renders in tab 2
> user clicks a link in tab 2, handler invoked, page id is changed 7
> user goes back to tab 1 - that has page 5
> clicks a link, handler invoked, page id changed to 8
>
> so the graph of the page diverged and looks like this
> 5<-6<-7 (open in tab 2)
> 5<-8 (open in tab 1)
>
> this change also eliminates the need for nasty undo objects, so where
> as before we had to do:
>
> addStateChange(new IChage() {
>    final int oldValue=value;
>   void undo() {
>        value=oldValue;
>    }
> });
>
> we can now simply say:
>
> getPage().dirty();
>
> pros/cons of new approach:
>
> con: before we had to maintain just the small undo object for each
> change, now we have to clone the entire page. why this doesnt matter
> much? we cloned the page anyways when we stored it to disk, so there
> is not that much overhead in the new scheme.
>
> pro: undo objects gone, they were cumbersome and sometimes complicated
> pro: complexity of versioning is gone
> pro: version manager is gone - the thing that maintained undo objects
> pro: complexity of pagemaps is gone
> pro: overall simplified requirements for handling pages and therefore
> simpler code in the core
>
> hope this sums it up, probably needs to be fixed up some and then it
> can go onto the wiki. looking at you jeremy :)
>
> -igor
>
>
>
> On Sat, Oct 16, 2010 at 8:49 PM, Jeremy Thomerson
> <[email protected]> wrote:
> > Has anyone written up information about the removal of page maps in 1.5?
>  I
> > have had some users asking about whether there is still multi-window
> > support, and what replaced page maps in 1.5, and I couldn't find a page
> to
> > point them to.  I didn't see either of those questions answered on the
> wiki
> > [1], and I have not dug very deeply into the internals of 1.5 myself.
> >
> > [1]- https://cwiki.apache.org/WICKET/migration-to-wicket-15.html
> >
> > --
> > Jeremy Thomerson
> > http://www.wickettraining.com
> >
>

Reply via email to