This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

Bug 19025 - Enhance module system to deal with downgrading modules versions
Summary: Enhance module system to deal with downgrading modules versions
Status: VERIFIED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: -- Other -- (show other bugs)
Version: 3.x
Hardware: PC Linux
: P3 blocker (vote)
Assignee: Jan Pokorsky
URL:
Keywords:
: 19995 (view as bug list)
Depends on:
Blocks: 17924
  Show dependency tree
 
Reported: 2002-01-04 09:18 UTC by Jaroslav Tulach
Modified: 2008-12-22 17:35 UTC (History)
6 users (show)

See Also:
Issue Type: ENHANCEMENT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jaroslav Tulach 2002-01-04 09:18:18 UTC
We have problems reported in issue 19001 and issue 19015 that are caused by the
user running code from release33 and main trunk at once. Most of the modules in
main trunk now have version 1.8 and those from release33 have version 1.7.1. As
a result .settings file (which contain version of module that provides them) are
ignored by module version 1.7.1 if written by module 1.8.

This is ok, we cannot support future compatibility, but we have to do something
with this.

Honza suggested to enhance module system to store the version of each module
that the IDE started with and if started with older version refuse to start or
disable the module. Is it reasonable?
Comment 1 Jaroslav Tulach 2002-01-04 09:19:41 UTC
Btw. another possible enhancement would be to ask user whether to
disable to module, not start at all or "pretend that the module is of
newer version". Last is dangerous but in our current situation would
work...

Comment 2 Jesse Glick 2002-01-04 17:23:01 UTC
I don't see any reason to prevent a user from using an older version
of a module! There may be very good reasons for a user to want to do
that. Issue 19001 just demonstrates that
SharedClassObject.findObject(Settings.class,true) is safer than
Lookup.gD().lookup(Settings.class). As far as I can see the core is
behaving correctly here, there was a bug in the Java module's code.
What is the justification for this?
Comment 3 Jaroslav Tulach 2002-01-07 08:40:19 UTC
Ok Jesse, here are the consequences:

File UI/Services/java.settings has been changed in newer version as
such it is not recognized by InstanceDataObject in old version. As
such it does not have InstanceCookie nor it has properties that would
allow user to modify it. (There is an obscure way how to get the
original option - tools/options/thesetting + expand layer info and
move the setting from info to the most right column -> this should
delete the settings from the newer version).

Anyway from above I conclude that it is not good to run the IDE with
downgraded version of a module.
Comment 4 Jesse Glick 2002-01-07 12:00:47 UTC
I don't draw that conclusion at all. The problem is not with running
an older module as such, it is that the structure of settings requires
that when a .settings file is presented in the layer, the user have an
opportunity to modify it. Apparently InstanceDataObject is not
currently doing this usefully. If there are stored settings with a
newer module version than is currently installed, rather than skipping
the instance cookie altogether and just showing "Broken Settings", it
should IMHO do either of the following:

1. As now, but with an obvious way in the UI to discard the unusable
state and reset it to the older module version's pristine state (i.e.
delete from system folder). Perhaps a menu item on the IDO, or just a
less cryptic UI for the Settings dialog.

2. In this situation, provide an IDO consisting of the pristine state
immediately, and permit it to be edited (clobbering the unusable newer
settings).

I somewhat prefer #1 I guess. Note that the IDO does not really know
where it is coming from (what layer etc.) so in fact the IDO itself
cannot reasonably handle this. However the Settings dialog could, I
think. There may need to be some way to communicate from a DataObject
to the dialog that it wants to be reverted somehow, i.e. that its
current state is bogus and that it ought to be restored to a pristine
editable state if that is possible, which would permit the dialog to
e.g. prompt the user to discard unusable settings in a batch, or
something like this. One easy mechanism would be to retain our current
system of providing a dummy InstanceCookie when there are broken
settings, but to standardize what the broken settings instance name is
- then the settings dialog could look for instances claiming to be
broken and attempt to revert them or otherwise warn/guide the user.

As with issue 19001, it ought never be the case that the module does
not work when some of its settings are broken. The module should
always have some backup scheme: it should not assume that objects
provided in its layer which are placed in user-editable areas
(settings, ....) will be in any particular state. Thus it should use
SharedClassObject.findObject for options, recover gracefully when
there is no applicable executor available from lookup, and so on. Such
robustness gives the user a chance to correct the settings without
getting exceptions all over the place first.
Comment 5 Jan Pokorsky 2002-01-07 14:11:12 UTC
Jesse I would agree with (1.). It is already possible to reset broken
settings by deleting its node and UI could be improved. But what
settings which are e.g. hidden (not all are presented in Options
window)? Moreover  it requires user to find out all these broken
settings and reset them.
Comment 6 Jesse Glick 2002-01-08 13:57:02 UTC
1. For settings which are hidden and not presented in Options, how
would they have gotten set at all? I can only think of a couple of
examples, like AutoUpdate's "last connected to server" etc. Probably
the module writing out such settings needs to decide whether it wants
to clobber old data or not. Better yet, it should not use versioning
stamps on such settings to begin with. Needs more thought.

2. Finding all the broken settings - yes this is probably a needed UI
improvement. See my suggestion about a dummy InstanceCookie. Or
something like this.
Comment 7 Pavel Buzek 2002-01-08 18:02:21 UTC
I am not sure if it should be _possible_ to downgrade, but it is IMHO it is unacceptable to let the user 
downgrade modules and just silently ignore all their settings and let it up to the user to find it out, 
go to Options and revert them to defaults. I gues there are multiple options which can be done:
1. disallow the downgrade
2. inform the user the they are using an older version of module and may have problems and
 a) disable the module
 b) revert settings to defaults
 c) ignore this fact and try to read new settings with old module - it may work, espacially in the case 
that it is similar version (like a beta and main trunk at the same time)
 - we can choose some of these options or let the user to choose
Comment 8 Jesse Glick 2002-01-08 21:00:17 UTC
I guess 2b. sounds most attractive (tho a confirmation from the user
is needed first to avoid possible data loss - if rejected, the module
should continue running but stored settings will not be available and
it may not be possible to make changes to existing settings).

Unfortunately I don't see how to do it. There is no trivial way to
find all customized settings originating from a given module. You can
look for settings files matching those in the layer, but this will not
cover newly-created services and so on. It might be possible to:

1. Store all customized settings in a special system folder named
according to the originating module (TBD how to tell which module this
is). All these would then be merged together by SessionManager. Might
be desirable in its own right anyway: cleaner management of different
modules.

2. Keep a file attr. associated with layer-installed settings
indicating its originating module and perhaps version (the module name
would be needed for pnejedly's SystemFileSystem.localizingBundle idea
anyway). Let it be copied to new files created in the SFS by changing
contents of the layer file (e.g. options) or by copying/creating from
template (e.g. services). Then later on if you want to revert all
customizations from a module en masse, you can do so by just searching
for this file attribute. It might also be used, if this were helpful,
to perform the logic currently handled case-by-case in
InstanceDataObject and window system XML files to ignore files from
uninstalled modules.

3. Some sort of combination of 1. and 2.: a simple attr provided for
every layer file which can be used for various purposes, and
SystemFileSystem when creating a writable layer for a file switches to
some subdirectory according to this info.

Of course these suggestions are significant architectural changes, but
I don't think any less so than deciding "users can never run an older
version of a module again" which does not sound too popular.

Probably the thread should be transferred to dev@openide, I have not
heard any suggestion which is trivial to do and obviously a good solution.
Comment 9 Jesse Glick 2002-01-08 21:01:36 UTC
Pavel, probably you meant to be CC'd here...
Comment 10 Jaroslav Tulach 2002-01-09 09:55:45 UTC
Jesse, your suggestion to store module settings in special module
directory is good, and I would like to suggest it to module writers.
Will we suggest - /system/Data/org.netbeans.modules.java/... this
could clean the mass that is on SFS...

Anyway we need something simpler right now.
Comment 11 Jaroslav Tulach 2002-01-09 10:02:51 UTC
The simplest is likely to modify InstanceDataObject load downgraded
settings anyway and if it fails present a reasonable description -
"You have tried to load settings from stored by a newer version of
module XYZ (2.1.43) but it does not seem to be readable with your
current version (2.0.3), please upgrade the module."

Second simplest and IMHO nicer solution is to modify the module system
to at least notice that the system runs older version of the warn the
user. But I can see that it is not Jesse's favourite.
Comment 12 Jesse Glick 2002-01-09 10:50:34 UTC
1. Yes we need something simpler than per-module dirs for the short term.

2. Per-module settings cannot be left up to module authors. The system
expects certain SFS folders to be used for certain purposes. The
merging has to be done by the session manager.

3. A warning from IDO might work, though this would be ugly in non-GUI
mode I think, and could be very annoying if there are dozens of such
dialogs.

4. A warning from the module system that an older version of the
module is being run and that some settings may not be available would
be OK. (I mostly object to *preventing* downgrades.) It does not help
the user much, however, if the user wishes to really use this version
of the module, and wishes to discard the old settings. So it would
only be a partial solution.
Comment 13 Pavel Buzek 2002-01-24 15:47:21 UTC
Jan Chalupa made a suggestion in off-line discussion, let me describe it. I know that it may not be 
possible in current implementation, but I think that it should first be clear how settings updates 
*should* behave, then we can look for impl. It questions the statement in the beginning of discussion 
that we cannot support future compatibility.

1. In number of cases (I did not check the percentage) there is actually no change in the module 
settings. At least in the content :-)
2. In addition there are many cases when settings are just extended by newer version and if this 
extension would be ignored then settings could be used by an older version.

At least in these cases the settings _could_ be fw compatible. For both cases we do not make it possible 
to downgrade module and use settings because we do not know it. We are using the spec. version of module 
as a version of settings, which means that with every release we assume that settings have changed (case 
1). This could be changed by introducing a separate spec. version for settings which does not need to 
change if the settings format did not change.
The second case would require the format of settings to be specified and to make it possible to keep 
ignored data untouched.

opinions?
Comment 14 Jesse Glick 2002-01-24 19:30:31 UTC
For Pavel's #1 - yes, this is surely true, but the IDE should have to
be told by the module that its format has not changed, as currently
the expectation is that the format may change without notice. I.e.
default should be to assume it is not compatible.

For #2 - I am against introducing a special spec version for settings,
it seems ugly. However if data were just stored in a different format
to begin with, e.g. XML files with versioned DTDs, it would be up to
modules to handle their own upgrading and downgrading, and the core
would not have to deal with it. More work for module authors, but
would probably result in better reliability in the long run, because
it is clear that the core knows nothing of your format, so you do not
expect too much and have to think about what will happen. We would
have to compensate by providing a usable API to help modules manage
the timing: when to load settings, when to save, when to revert, etc.
Comment 15 Pavel Buzek 2002-01-25 10:19:57 UTC
You say that module should be able to tell that settings have not changed. That is my point. Whether it 
is by a separate spec. No. or in other way (how then?, by version of DTD?) does not matter that much from 
my point to view.
Comment 16 Jaroslav Tulach 2002-01-28 12:00:15 UTC
Ok, so we can change the issue as wontfix and concentrate on issue
17924 - custom format for IDO...
Comment 17 David Konecny 2002-01-28 13:55:30 UTC
May I ask a question? If I understood it well the whole problem is 
caused by spec version of the module which is stored in .settings 
files. But why is the spec version stored in .settings files at all? I 
don't understand its purpose.

Let me summarize my understanding how .settings file works and correct 
me please if I misunderstood something:

There are two types of versioning. First, the structure of the 
.settings file itself. This is handled by used DTD. Second, versioning 
of the module's settings stored in the .settings file. This is 
module's task - module must take care about this versioning and about 
backward compatibility.

Storing module's settings in .settings file in XML form is better than 
serialized form, but even the serialized form should not cause so much 
troubles. It is possible I'm missing something as I'm not expert in 
serialization. But if module:
* uses the same serialVersionUID
* and did not remove the class
* and did not change the semantic of the properties of serialized 
class
then they should be able to deserialize newer and older versions of 
the class. If module deserializes the old version of the class, all 
new fields must be initialized by module in readObject() method. If 
the module deserializes some newer version of the class, all new 
properties are ignored (right?). (if the settings are stored in some 
human readable format, the situation is almost the same - module 
should be able to recover from the missing/new fields)

So, where is the problem? Why we need to have spec version in 
.settings files. Something like spec version can be handy, but only in 
case that module did some really big incompatible changes in almost 
all of its settings. Otherwise they should use the mechanism above and 
recover from minor changes.
Comment 18 Jan Pokorsky 2002-01-28 14:26:39 UTC
The purpose of the spec. version in .settings files is to allow the 
settings framework to ignore settings from disabled/missing modules 
otherwise CNF would be still thrown.
Comment 19 David Konecny 2002-01-28 14:37:09 UTC
Jan, but for this you need just name of the module and not the spec 
version.
Comment 20 Jan Pokorsky 2002-01-28 14:59:40 UTC
I do not think so. If a setting is introduced in the newer version of 
a module and you would downgrade to the older one just the module name 
is not sufficient.
Comment 21 Jesse Glick 2002-01-28 15:23:43 UTC
Spec version in settings file can also be used to indicate that a
setting is not reverse-compatible. To David K.: yes unused fields and
missing fields are handled somehow by Java Serialization, but the
result may be an object with inconsistent state. E.g. you had:

public class Foo implements Serializable {
    private static final long serialVersionUID = 123L;
    private String thingy;
    // ...
}

and you change it to:

public class Foo implements Serializable {
    private static final long serialVersionUID = 123L;
    private String[] thingies;
    // ...
    private void readObject(...) ... {
        // getFields, look for "thingy" and for "thingies",
        // set thingies instance var appropriately
    }
}

This works fine. But the new state will not work in the old version of
the class, and it is too late to make it work, probably.

If you are careful in your module, and design all serializable classes
to be bidirectionally compatible for the future (using a map of
properties and so on), and design some system for handling problems
gracefully in both directions, great. Remove the specification version
from your .settings file in the layer, and IDO should let the user
downgrade and keep your settings. Just as if you were storing data in
XML files using some custom versioned DTD and wanted to manage
upgrades/downgrades yourself.
Comment 22 Pavel Buzek 2002-01-28 15:38:56 UTC
to: Yarda (this is really becoming a discussion forum:-)
please leave this issues open so that we make sure that the fix of 
http://openide.netbeans.org/issues/show_bug.cgi?id=17924 also fully resolves this issues, then close it.
Comment 23 David Konecny 2002-01-28 15:56:01 UTC
Yes, Jesse, you are right. The scenario you have described will fail 
even in case we have nicely human readable XML. And in this case the 
increased spec version would make perfect sense. But shouldn't it be 
then the module owner who should decide when it is necessary to change 
the "version" of the setting? Because I tend to believe than in most 
of the cases the settings are compatible. The module owners just must 
be aware of the compatibility issue and design the changes according 
to it. Marking the settings automatically as incompatible after each 
release just causes a lot of problems. (I think this is what Pavel and 
Honza proposed - to have separate "spec version" for settings)
Comment 24 Jan Chalupa 2002-01-28 16:51:48 UTC
IMO, the problem with the current approach is that the decision about
compatibility is being made at the core level, although it should be
made at the module level. The spec version number in the settings file
is just a hint to tell core that things have probably changed, but
there's not enough information available to deal with potential
incompatibilities at that level.

I think that the format of the settings and dealing with compatibility
issues should be left up to the module developer. The settings format
(preferably human-readable) should be carefully specified, versioned
and treated as an API. There have to be good reasons to change the
format and the module developer should take responsibility for
handling all issues resulting from that change. The module should be
able to read all older versions of its settings. (In a perfect world,
it should also be able to save in older formats :-).

Last but not least, I think that we would be facing far less
compatibility problems if the module developers were forced to think
about the data they really need to persist in the first place.


Comment 25 Jesse Glick 2002-01-29 10:41:47 UTC
David K. - no one is forcing you to mark settings as incompatible! If
you put a spec version in your *.settings, it will be used. If you
don't, it is assumed that any version of your module can read that file.

Jan Ch. - yes there is a need for better formats and more module
involvement in the process, we're trying to come up with something;
but I think it is out of scope for this issue, which should
concentrate on properly handling downgrades of settings as we have
them now, i.e. plain serialized SystemOption's, ServiceType's, etc.

I think this is another issue that needs to be moved to dev@openide
and probably marked RESOLVED LATER since there is no single option
settled on here.
Comment 26 David Konecny 2002-01-29 11:49:38 UTC
Jesse, I did not know that module can say whether they want spec 
version in settings file or not. This is good. But still, once they 
have put it there (e.g. in version 2.0 of my module I did some 
incompatible changes in settings), it will be automatically updated 
according to module spec version, right? So although I did not change 
the settings and they are still backward and forward compatible for 
all >=2.0 version, the spec version is automatically increased for all 
2.1, 2.2, 3.0 releases and that causes problem reported in this issue.
Comment 27 Tomas Hurka 2002-02-01 08:37:30 UTC
*** Issue 19995 has been marked as a duplicate of this issue. ***
Comment 28 Jan Pokorsky 2002-05-16 06:52:20 UTC
The implementation is based on the decision that each major release 
(3.3, 3.4, ...) introduces own user dir. So, it is possible to safely 
downgrade in the scope of that release (e.g. 3.4.2 -> 3.4.1).

The current settings implementation handles the setting versions in 
following manners:

old serialdata format:
significant is just the code name of the module. Remaining attributes 
like the spec. version or the release version are ignored.

custom convertor format:
convertors do not use the ModuleInfo any more. The setting's 
availability is given by its dtd's public identifier registration in a 
module layer. The content of .settings file is not dependent on a 
setting object class either. 

Now, It is module writers job to provide proper registrations using 
convertors and classes suitable for the given version.

For more details see the core/settings module.
Comment 29 Jaroslav Tulach 2003-07-14 15:23:22 UTC
Ok, different directories will work.