Bug 85373 - [RCP] Missing save/restore capabilities of workbench state
Summary: [RCP] Missing save/restore capabilities of workbench state
Status: RESOLVED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 3.1   Edit
Hardware: PC Windows 2000
: P3 normal (vote)
Target Milestone: 3.1 M6   Edit
Assignee: Nick Edgar CLA
QA Contact:
URL:
Whiteboard:
Keywords: api, helpwanted
Depends on:
Blocks:
 
Reported: 2005-02-16 04:25 EST by Daniel Krügler CLA
Modified: 2008-02-29 09:58 EST (History)
4 users (show)

See Also:


Attachments
helper class to expose internals as API (2.41 KB, text/plain)
2005-03-22 11:47 EST, Matthew Hatem CLA
no flags Details
preview (12.34 KB, patch)
2005-03-23 14:11 EST, Matthew Hatem CLA
no flags Details | Diff
final patch candidate (14.98 KB, patch)
2005-03-23 14:43 EST, Matthew Hatem CLA
no flags Details | Diff
Demonstrates how to leverage patch (6.82 KB, patch)
2005-03-24 10:41 EST, Matthew Hatem CLA
no flags Details | Diff
updated based on feedback (14.83 KB, patch)
2005-03-24 13:10 EST, Matthew Hatem CLA
no flags Details | Diff
updated demo based on revised patch (6.81 KB, patch)
2005-03-24 13:11 EST, Matthew Hatem CLA
no flags Details | Diff
Updated patch, solves A and B from comment #14 (16.37 KB, patch)
2005-03-24 16:37 EST, Matthew Hatem CLA
no flags Details | Diff
Updated patch, solves A and B from comment #14 (16.37 KB, patch)
2005-03-24 16:37 EST, Matthew Hatem CLA
no flags Details | Diff
Demonstrates how to leverage patch to solve B from comment 14 (13.88 KB, patch)
2005-03-24 16:46 EST, Matthew Hatem CLA
no flags Details | Diff
Updated patch to check against head, (4.87 KB, patch)
2005-03-25 10:26 EST, Matthew Hatem CLA
no flags Details | Diff
updated demo based on revised patch (14.13 KB, patch)
2005-03-25 10:27 EST, Matthew Hatem CLA
no flags Details | Diff
updated patch to check against head (14.48 KB, patch)
2005-03-28 15:58 EST, Matthew Hatem CLA
no flags Details | Diff
Updated patch to check against head, with error reporting (14.55 KB, patch)
2005-03-28 16:08 EST, Matthew Hatem CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Daniel Krügler CLA 2005-02-16 04:25:26 EST
Currently there exists no official RCP-API to save and restore the workbench
state (on a per page basis) programmatically. This problem was discussed in the
eclipse.platform.rcp news group in article "Closing and reopening
IWorkbenchPage's during runtime".

A typical use case, which would need this kind of controllability, are
login-based RCP's which would like to save the workbench state before login
attempts are taken and to restore the state after successful logins (This would
allow them to save the workbench state user-specifically). Note that I don't
speak here of so-named *primary* logins (during RCP startup) and *final* logouts
(during RCP shut down), which already have the described behaviour, I mean login
changes during runtime, which act on an already constructed workbench.
Comment 1 Matthew Hatem CLA 2005-03-22 11:47:43 EST
Created attachment 19082 [details]
helper class to expose internals as API

Comments from Nick Edgar:

The proxy methods in WorkbenchStateHelper are fine for experimentation, but I
would not want that to be exposed as the API.  How will this be exposed to the
application via the advisors, and what extra API will be needed to override the
default save/close/restore behaviour?
Comment 2 Matthew Hatem CLA 2005-03-22 13:05:07 EST
I was expecting the helper class to be sufficient for an initial pass at this. 
This would be sufficient for Lotus applications.

Another approach would be to apply some strategy or callback pattern to the
WindowConfigurer, passing a StateHandler callback.  The callback object would
specify which level of state to save.  For now we're looking at just
Workbench/Window/Page.

Thoughts?
Comment 3 Nick Edgar CLA 2005-03-22 13:49:38 EST
WorkbenchStateHelper as provided is not proper API.  It's in an internal
package, and even if it wasn't, we probably don't want to expose this as API to
regular plug-ins, just the application driving the workbench.  

The advisor and configurer APIs are the right place for this kind of thing.
I'm thinking of something like the following call chain:

Workbench.shutdown()
  WorkbenchAdvisor.saveState(IMemento)
    IWorkbenchConfigurer.saveState(IMemento) // calls current Workbench.saveState
      for each window,
        WorkbenchWindowAdvisor.saveState(IWorkbenchWindow, IMemento)
          IWorkbenchWindowConfigurer.saveState(IWorkbenchWindow, IMemento) //
calls current WorkbenchWindow.saveState
            for each page
              WorkbenchWindowAdvisor.saveState(IWorkbenchPage, IMemento)
                IWorkbenchWindowConfigurer.saveState(IWorkbenchPage, IMemento)
// calls current WorkbenchPage.saveState

So the app's advisors can intercept the saveState calls, and can call the
matching configurer method to get the default behaviour.

Restore would work similarly.
            
If you're not at the point of being able to provide advisor-level API for 3.1,
that's OK, and you can patch in something like WorkbenchStateHelper for your own
use.
Comment 4 Matthew Hatem CLA 2005-03-22 14:42:57 EST
I now have something very similar to comment #3.  However, instead of baking the
saveState API into the WorkbenchXXXAdvisor/XXXConfigurer I have a setter method
on WorkbenchConfigurer "setSaveRestoreHandler(ISaveRestoreHandler)".  The
handler is then used throughout Workbench/WorkbenchWindow to save/restore state.

I will change my implementation to what you have suggested.  Not sure I'll have
the time to tackle page level save/restore.
Comment 5 Matthew Hatem CLA 2005-03-22 14:58:19 EST
Just to clarify, Nick, the memento objects passed into the saveSate methods are
already populated with state data?  Or are you imagining adding something like
"getState" to IWorkbench/IWorkbenchWindow/IWorkbenchPage that an advisor would
need to call in order to save state.
Comment 6 Nick Edgar CLA 2005-03-22 15:15:46 EST
No, the saveState methods do the saving.

So for example, just for the workbench-level case:
Workbench.shutdown()
  WorkbenchAdvisor.saveState(IMemento)
    - memento is empty at this point
    - call the default save method:
      IWorkbenchConfigurer.saveState(IMemento)
    - the memento now has the saved workbench state
    - return

Likewise for windows and pages.
Comment 7 Matthew Hatem CLA 2005-03-23 12:08:31 EST
There is some difficulty exposing the save/restore of a perspective, for one
there is no public API to pass through the advisor to the WindowConfigurer to do
a default restore.  Something like IPerspective would have to be introduced. 
Second, there is little to no information available about a perspective until
the perspective.restoreState() has been completed, thus there is no valuable
information to pass through to the advisor to indicate which perspective is
actually being restored before it's restored.

One possible workaround to this is to build a proxy memento, use that in the
WindowConfigurer.restoreState(memento) call and parse the memento for
information about the perspective.  I don't think anyone will like this
approach.  We could do this internally and populate some proxy
IPerspectiveDescriptor with the information.  Again, I don't think that would be
acceptable for 3.1, Nick please correct me if I'm wrong and I'll go ahead and
implement.

I think this is a fundemental problem similar to the one Nick faced at the end
of bug #83658

I suggest we support only Workbench and WorkbenchWindow level save/restore. 
Thoughts?
Comment 8 Nick Edgar CLA 2005-03-23 12:59:17 EST
If finer granularity than window is not needed for you or Daniel's scenarios,
then let's limit it to that for 3.1.  Otherwise, we should just defer to 3.2.

Matt, I'll need to review the patch today if it's going to go into tomorrow
morning's warmup build.
Comment 9 Matthew Hatem CLA 2005-03-23 14:11:09 EST
Created attachment 19129 [details]
preview

Nick here is a preview of my patch.  Still need to clean up the Javadoc.
Comment 10 Matthew Hatem CLA 2005-03-23 14:43:54 EST
Created attachment 19133 [details]
final patch candidate

Same as previous patch 19129 just cleaned up Javadoc.
Comment 11 Nick Edgar CLA 2005-03-23 22:46:48 EST
Matt, can you provide an example, modeling how this will used for the LWP use
case?  Also, all new API needs @since 3.1 tags.

Comment 12 Nick Edgar CLA 2005-03-24 07:16:51 EST
In particular, I don't see how this helps you decouple saving/restoring window
state from the workbench save/restore, since there's no way of saying "create a
new window, restored from this memento".
Or is that a different problem?

I guess I need to be clearer on the motivation for this patch.

Daniel, will the patch as provided address your use case?
Comment 13 Matthew Hatem CLA 2005-03-24 10:41:06 EST
Created attachment 19159 [details]
Demonstrates how to leverage patch

Nick, here is a patch which demonstrates one way an RCP application can benefit
from this patch.  

1) Run the patched browser demo with "-role someOne" change the layout,
shutdown.

2) Then run as "-role someTwo" change the layout to something different than
the layout above and shutdown.

3) Run as "someOne" again and you will get the state of the last time the
workbench ran with that role.

This isn't a fully polished demo, the first time a new role is run he gets the
state of the previous role.  That can be fixed by nuking the real workbench
state file or something better.

But you are correct in that the primary Lotus use case is one of a multiplexed
WorkbenchAdvisor.  Windows are created on demand and state cannot be pushed to
those windows without using internals even with this patch.  I was imagining
that as the Advisor APIs evolved to support multiple WindowAdvisors per
WorkbenchAdvisor the API proposed in this patch with evolve as well.
Comment 14 Matthew Hatem CLA 2005-03-24 10:46:52 EST
I see the patch meeting the following requirements as outlined by Daniel:

A) Allow RCP apps to save the workbench state user-specifically.

But does not yet satisfy this requirement:

B) I mean login changes during runtime, which act on an already constructed
workbench.

This will require new API to allow constructing WorkbenchWindows with a
specified memento.  Do we have time to get this in?
Comment 15 Nick Edgar CLA 2005-03-24 10:51:52 EST
I think it's worth doing B if we can.  We're supposed to be API frozen today,
but I'll extend this to Monday if you can tweak the patch, and ideally provide
another example showing B.

I'm assuming Daniel cares mostly about IWorkbenchWindow granularity, not
IWorkbenchPage, although the UI would be smoother if the same window could be
reused.

Thanks.

Comment 16 Nick Edgar CLA 2005-03-24 11:39:36 EST
API note: need to avoid referring to internal classes in API Javadoc.
IWorkbenchWindowConfigurer.restoreState refers to WorkbenchWindow.
We tend to use generic terms instead of type names in the Javadoc, unless it's
ambiguous.  E.g. "workbench" instead of "Workbench", "workbench window" instead
"WorkbenchWindow".
Comment 17 Nick Edgar CLA 2005-03-24 11:50:57 EST
WorkbenchWindowAdvisor.saveState and restoreState do not need to pass the
IWorkbenchWindow, since the advisor was created for a specific window
(obtainable via getWindowConfigurer().getWindow()).  The default implementations
currently ignore this argument due to the redundancy.
Comment 18 Matthew Hatem CLA 2005-03-24 13:10:41 EST
Created attachment 19165 [details]
updated based on feedback
Comment 19 Matthew Hatem CLA 2005-03-24 13:11:14 EST
Created attachment 19166 [details]
updated demo based on revised patch
Comment 20 Nick Edgar CLA 2005-03-24 16:23:40 EST
Thanks Matt.  

The example patch is interesting.  It saves a separate workbench memento per
user, but the default behaviour of writing to workbench.xml still occurs.  The
new API does not let you override where the workbench state is saved, it just
enables saving an extra copy, and restoring from that instead of the default
workbench.xml (although the workbench.xml is still read).

Due to this, if you run the example with a previously unknown user, it gets the
workbench state from the last user.  This is probably not what you want for LWP <g>.

It seems like we should allow overriding the location of the file, in addition
to being able to intercept and augment the mementos.

Also, are you actually looking into B?
Comment 21 Matthew Hatem CLA 2005-03-24 16:37:56 EST
Created attachment 19175 [details]
Updated patch, solves A and B from comment #14

This introduces one new API on IWorkbench.  Probably obseletes the nees for
save/restore API on WorkbenchAdvisor and IWorkbenchConfigurer.

Demo to follow.
Comment 22 Matthew Hatem CLA 2005-03-24 16:37:56 EST
Created attachment 19176 [details]
Updated patch, solves A and B from comment #14

This introduces one new API on IWorkbench.  Probably obseletes the nees for
save/restore API on WorkbenchAdvisor and IWorkbenchConfigurer.

Demo to follow.
Comment 23 Matthew Hatem CLA 2005-03-24 16:46:39 EST
Created attachment 19178 [details]
Demonstrates how to leverage patch to solve B from comment 14


1) Launch patched browser demo, you wont see a window, only a systemtray icon

2) Right click the icon and launch application one and change the layout to
something unique.  NOTE dont application one.

3) Right click again on the icon and launch application two and change the
layout to something unique.

4) Now take turns closing and launching applications one and two (always keep
at least one application/window open) and note that the state for each
application is remembered.

The patch to the workbench is not final.  Some Javadoc still needs updating and
the API on WorkbenchAdvisor and IWorkbenchConfigurer still need to be validated
as useful.
Comment 24 Matthew Hatem CLA 2005-03-24 16:48:00 EST
"NOTE dont application one. " should read "NOTE dont close application one."
Comment 25 Nick Edgar CLA 2005-03-24 17:24:11 EST
Matt, are you available to chat?  I'm on ST.
Comment 26 Nick Edgar CLA 2005-03-24 17:46:31 EST
This support for B looks good, and the example is cool.

However, I think we need to clarify what problem(s) we're trying to solve here.
The ones on the plate are:
1) Maintaining and switching between different states for different users
1a) for the whole session
1b) within a session

2) Allowing windows to be saved and reopened independently of the workbench
session, for the same user.

3) Letting advisors tack on their own workbench-level or window-level state


I think we can achieve (2) and (3) for 3.1, but not (1).

The reason being is that there is lots of per-user state in the instance area
besides just the workbench layout: preferences, dialog settings, random plug-ins
saving stuff in the metadata area (e.g. the workspace if using
org.eclipse.core.resources).  Supporting multiple users with the same eclipse
install can currently only be done by prompting for the instance area when the
application starts.  It may be possible for the app to restart the workbench
with a different instance area after it exits, but even that is dicy because
plug-ins often only save their state when they're being stopped.

Matt and Daniel, can you please clarify which cases you really care about, or
comment if I've missed a case.
Comment 27 Nick Edgar CLA 2005-03-24 23:16:01 EST
Re comment 22, the method to create and restore a window from a memento should
go on IWorkbenchConfigurer, not IWorkbench it should not be exposed to regular
plug-ins.
Comment 28 Matthew Hatem CLA 2005-03-25 08:41:04 EST
Agree with comment #27 and will update patch.  I think an "on demand" API like
recordWindowState(IMemento) and restoreWindowState(IMemento) might be better (at
least for Lotus) than  baking the API into the life cycle methods.  This is more
inline with my helper approach.  Protecting access to this API from regular
plugins is the right approach. 

Re. comment #26, our use case is not that of multiple users sharing the same
instance area.  Instead we have one user with multiple applications/windows
sharing the same process and instance area.  An application here is just another
workbench window on the same workbench instance.  This is done by multiplexing
the advisor.  My previous patch is a crude demo of this multiplexing.
Comment 29 Matthew Hatem CLA 2005-03-25 10:26:55 EST
Created attachment 19191 [details]
Updated patch to check against head, 

This patch introduces a simpler API that allows RCP applications to record the
state of any IWorkbenchWindow instance at any time.

Updated demo patch to follow
Comment 30 Matthew Hatem CLA 2005-03-25 10:27:41 EST
Created attachment 19192 [details]
updated demo based on revised patch
Comment 31 Michael Van Meekeren CLA 2005-03-25 18:01:17 EST
I like this version.  I've tried out the patches with the demo, works well.  I'm
checking this in to HEAD for M6.  I have not released the example.

I think it might be a good idea to consider whether
restoreWorkbenchWindow(IMemento) should show the window, this might not be the
desired behaviour.

Matt, could you also prepare a couple JUnit tests for these two new methods?

Comment 32 Michael Van Meekeren CLA 2005-03-25 18:02:42 EST
Again, would be nice to know if Daniel (original bug reporter) could indicate
whether this solves his needs as well.  Leaving open at least to see if we hear
something next week (before April 1st).
Comment 33 Matthew Hatem CLA 2005-03-28 10:23:36 EST
I will provide a JUnit test for the new API soon.  Thanks.
Comment 34 Nick Edgar CLA 2005-03-28 12:51:18 EST
It seems like this will address scenario 2 but not 3 (see comment 26), which I
thought was important to Matt (we discussed this over Sametime).  With the
latest patch, there's no way for the advisor to save its own state, either at
workbench or window level, for a regular workbench save.

Also, I'd prefer to see the recordWorkbenchWindowState method on
IWorkbenchWindowConfigurer rather than being on IWorkbenchConfigurer and having
to take an IWorkbenchWindow arg.  Should also call it "saveState" for
consistency with other workbench API (e.g. IPersistable/IPersistableElement).

For symmetry and consistency with the rest of the advisor methods, the restore
method should probably return an IWorkbenchWindowConfigurer too.
Comment 35 Matthew Hatem CLA 2005-03-28 15:58:03 EST
Created attachment 19240 [details]
updated patch to check against head

Patch updated based on Nick's comments in #34.
Comment 36 Matthew Hatem CLA 2005-03-28 16:08:07 EST
Created attachment 19242 [details]
Updated patch to check against head, with error reporting

added some error reporting
Comment 37 Nick Edgar CLA 2005-03-28 20:06:24 EST
Thanks Matt, I've reviewed and released the last patch with the following tweaks:
- changed restoreWorkbenchWindow to return an IWorkbenchWindowConfigurer
- described default behaviour and subclassing contract for advisor
save/restoreState methods
- minor changes to wording in Javadoc

If you could supply JUnit tests for these new APIs for M6, that would be great.
 Such tests are especially important in cases like this, where the IDE will not
be exercising the API.
Comment 38 Nick Edgar CLA 2005-03-28 20:09:30 EST
You can take a look at the existing RCP test suite in org.eclipse.ui.tests.rcp.
When creating the "JUnit Plug-in Test" launch config for RCPTestSuite, specify
"[No Application] - Headless mode" as the application, as these test are
intended to drive the workbench as if they were the app, not run within an
existing app like the other UI tests.
Comment 39 Daniel Krügler CLA 2005-03-29 02:17:53 EST
I read your proposal and implementations and I'am very happy concerning your
current state of development - congratulations!
Matthews interface nicely allows additional user-specific save/restore steps 
and also on-demand-restore/save, which is very fine.
One weak point, as also recognized by you in point (1) of comment #26, is that
this does not allow a full-fledged user-change during runtime (at least, if I
read everything carefully enough), which indeed applies for our application. One
example would be a realization of user-specific perspective loading as described
in thread "How to dynamically chose a perspective if
configurer.setSaveAndRestore(true)?".
Given my original bug description I think one should accept the currently
proposed AP extensions and marking this bug as fixed (because the originally
demanded callback points do now exist).

But I would really appreciate further developement concerning a full user-based
save-restore mechanism, because I assume, that user-based RCP's play an
important "role" ;-). Do you see a realistic chance for that request?

I would also like to humbly ask, how you resolve this issue given the current
state? Lets again take the example of user-specific perspective loading. The
current behaviour always loads the perspective of the most recent saving step,
but that saving step might belong to any arbitrary user. Do you see any point to
realize that?
Comment 40 Nick Edgar CLA 2005-03-30 13:29:22 EST
Closing PR as fixed.  Filed bug 89637 for the tests.
Please open separate PRs if problems with the new API are encountered.

> I would really appreciate further developement concerning a full user-based
save-restore mechanism ... Do you see any point to realize that?

I think we should continue the discussion.  Could you please open a separate
enhancement request, providing details of your scenario and how you envision
handling other state like preferences, workspace or other model data, etc.?

> how you resolve this issue given the current state?

I think the best (and safest) approach in 3.1 is to only allow user switching on
startup, and choose a different instance area based on user id (similarly to how
the IDE prompts for workspace on startup -- see IDEApplication in the
org.eclipse.ui.ide plug-in).  

You could try using the APIs added here, e.g,
- within Bob's session, allow a "Change User" action
- this prompts for a new user
- user chooses "Fred"
- your app then:
  - uses the new APIs to save the state for all open windows in a memento
  - saves the memento in your plug-in's metadata area, keyed by Bob's id
  - closes all open windows
  - retrieves the memento for Fred (if any)
  - restores the windows previously stored there using the new APIs

However, this will not save any workbench state above the level of windows, and
does not address other per-user state (prefs, data model, etc).
Comment 41 Mahesh Sooriarachchi CLA 2008-02-29 09:58:05 EST
I am in a very similar situation.  We have an intro from which the user can login.  After the login is when I want to restore the workbench and I havent been able to figure out a way to do this properly.  I tried deffering restoring the workbench until the user logs in, and doing the following, but it opens a new window

ApplicationWorkbenchAdvisor advisor = ApplicationWorkbenchAdvisor.getInstance();
IWorkbenchConfigurer config = advisor.getConfigurer();
config.setSaveAndRestore(true);
config.restoreState();

Also, another thing I noticed is that if you have a view maximized before quitting the app, the intro will not be shown on re-launch of the application.  This is what prompted me to try to defer the restoring the workbench.