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 35036 - JNLP installer should not use autoupdate
Summary: JNLP installer should not use autoupdate
Alias: None
Product: installer
Classification: Unclassified
Component: Code (show other bugs)
Version: 3.x
Hardware: All All
: P3 blocker (vote)
Assignee: David Strupl
Keywords: ARCH
: 232119 (view as bug list)
Depends on: 29128
Blocks: 28376
  Show dependency tree
Reported: 2003-07-21 23:39 UTC by David Strupl
Modified: 2013-07-07 13:23 UTC (History)
3 users (show)

See Also:
Exception Reporter:


Note You need to log in before you can comment on or make changes to this bug.
Description David Strupl 2003-07-21 23:39:19 UTC
In the proposed solution the current NetBeans JNLP
installer will not be present and the nbm files
will not be used.
Download of the class files (and others) would be
handled by JNLP. Then only information required
for the module system to work is from what module
the class comes from. I propose to solve this by
packing the jars in following way: if we have
class xyz.Foo i propose to use
following path inside the jar:
mymodule1.1/xyz/Foo.class. With
this layout and with some additional information
available as some XML file the module system could
work as it works now but load the classes by the
classloader of the JNLP client. The additional
information would have to be provided by some
servlet similarly as it is now. The output of this
servlet should tell the module system what modules
and in what directories are available.

From the user perspective the proposed solution
would seem as if only the JNLP client is used. But
I propose to still use the regular splash for the
NetBeans framework startup (as it is now without
the installer and nbm unpacker).

JNLP classloader shouldn't be directly used IMHO
since it "flattens" the classpath and does not
allow for the module system functionality -
managing dependencies, code isolation etc. I hope
that the delegating
approach (special classloaders delegating to the
JNLP classloader) can work.

Deployment solution: the build scripts would build
jar files for the JNLP server solution. The
contents of the jar files would contain one
additional directory besides the normal content.
The jnlp file (currently nb-launch.jnlp) + maybe
one additional descriptor xml file  could be
generated dynamically by some servlet (index
servlet). The configuration of the client would be
determined by those two servlets (or by one if I
am able to squeeze it into .jnlp file).

The classes that would have to be modified in core:

totally rewrite:
partially rewrite:
couple of other classes from
org/netbeans/core/modules/ like

Current status
I have quite messy changes in the NetBeans module
system. They include a class called
DelegatingClassLoader - it is a replacement for
the JarClassLoader. In the current state I am able
to load classes using the DelegatingClassLoader -
not completely working but at least a rough idea
works (getting the JNLP classloader and delegating
the finding of the
resource). I did not implement the list of modules

Further work
1. implement loading the list of modules from some
xml file or from
the jnlp file
2. change build scripts to package the modules
according to the proposal
3. debug and polish hacks from the current state
of the prototype
Comment 1 Jesse Glick 2003-07-22 00:28:02 UTC
Re. "only information required for the module system to work is from
what module the class comes from" - this information is probably
worthless in a JNLP scenario; it is only used by InstanceDataObject to
tell when to not load a setting when a module is disabled. But you
would not have this situation under JNLP, I suppose. Also this kind of
class-based settings persistence is planned for complete replacement
in the next NB version (cf. nbdev discussions on the new Convertor
API, which will not need such information ever). Even with a flat
classpath, the association from class to module is easily available,
should you ever need it, by using
Class.protectionDomain.codeSource.location and comparing to that of
known JAR manifests - maybe in other ways too, e.g. java.lang.Package.

Re. "module system functionality - managing dependencies, code
isolation etc." - IMHO all this is useless under JNLP since you
control the module set that is provided. All of these features
ultimately serve *only* the purpose of permitting binary-compatible
upgrades of sections of the NB installation without any changes to
existing sections. Under JNLP-style server distribution this is not an
issue. If you don't have such requirements (or others, like
componentized security, that are not met by NB anyway), you might as
well use the plain Java classpath - simpler and probably more efficient.

Re. classes to rewrite - if you just load everything directly from the
JNLP class loader, things are much simpler, I think.
org.netbeans.core.modules.Module already works correctly with
classpath modules, AFAIK. ModuleList would just be a no-op - no JARs
to list. InstalledFileLocatorImpl of course needs to be replaced (you
can do this with a fresh class registering itself in
META-INF/services, rather than patching the original impl).
JarClassLoader doesn't need to be touched - it simply won't be used,
since there won't be any non-classpath modules. Main & similar
org.netbeans.core.* classes just need to be patched a little bit to
not halt when it discovers that there is no $userdir/modules dir nor
$nbhome/modules dir; generally, to rely less on the existence of these

I feel that all the required changes could be kept small and harmless
enough to be left permanently in the NB core code, with a small
JNLP-specific piece of code activated in JNLP mode (e.g. by adding a
special JAR to the classpath with a few overriding service impls,
where this JAR is not normally part of the distribution).

Also if you use a flat CP, there is no need for any list of modules.
The existing module system code already autodiscovers this by looking
for META-INF/MANIFEST.MF resources.

Really the only things that shouldn't work "out of the box" with a
flat CP are (1) overlapping packages and so on, which you can just
solve by cleaning up library usage among modules you include, (2) the
standard InstalledFileLocator impl, since you need one that knows
where to look for things, (3) module management UI - of course all
modules will be listed, but you will not be able to disable them.
Comment 2 David Strupl 2003-07-22 13:35:18 UTC
Suppose you have xyz10 and xyz12 (when 10 being version 1.0 and 12
being version 1.2 of xyz). And a bunch of code depending on xyz.
Moreover you have managed to update only part of those depending
modules. So you need to have both xyz10 and xyz12 for all things to work.

This scenario could not be supported by the flat classloader. If we
drop this usecase than I am not aware of any other. But we have to
decide whether we need this or not.
Comment 3 Jesse Glick 2003-07-22 15:03:59 UTC
"Suppose you have xyz10 and xyz12 (when 10 being version 1.0 and 12
being version 1.2 of xyz). And a bunch of code depending on xyz.
Moreover you have managed to update only part of those depending
modules." - i.e., some incompatible change made to an API module
without changing the package name(s). In that case of course you need
to update everything depending on the old version in order to use the
new version.

Typically though the actual updating of code is not so hard - that is
what refactoring tools are for, to help speed it up. Most incompatible
changes that are kept in the same package tend to be pretty small
things anyway, like adding a method to an interface, where it is
generally clear what you need to do in order to upgrade.

In cases where you are completely redesigning a whole subsystem, of
course the matching code changes elsewhere are more complex. But
either (1) the subsystem is a "pure" library, in which case you should
just be changing package names anyway, which works fine in a flat
classpath; or (2) binary compatibility with the old API requires some
sort of runtime bridge or compatibility wrapper, which is usually also
a lot of work to develop, and is going to require lots of QA time to
verify - you are unlikely to save engineering effort relative to just
updating your other code.

The harder part (at least in my experience) is usually dealing with
deployment-time binary incompatibilities and infrastructure to support
incremental updates in the field, including warning users of possible
problems, etc. This issue vanishes under a JNLP-type system since you
completely control what goes into the module configuration, and don't
publish anything until you are sure it all works together smoothly.

(I am assuming we are talking about situations where you are basically
in control of the modules you are publishing to the JNLP server. If
you are including third-party modules that you did not write, and
whose source code you either have no access to or do not understand,
then you are in trouble if you cannot use runtime compatibility
bridges. However if there are bugs in the third-party code, good luck
fixing them!)

Of course if you are doing the implementation work, it is up to you to
decide what you need. I am just saying that I doubt a release of the
standard NB distribution would want to have coexisting
binary-incompatible modules to begin with, and I doubt any Sun product
would find this acceptable either. On the other hand, if support for
per-module class loaders in JNLP turns out to have a relatively simple
or well-isolated implementation that is not a maintenance problem for
the rest of the module & startup system, then there is no harm in
supporting it, if someone finds it useful.

(BTW I am assuming that your proposed class loading system still uses
JNLP's native JAR diff/download, so the way in which classes are
loaded is mainly an internal detail.)
Comment 4 Jesse Glick 2003-07-23 17:46:48 UTC
See issue #29128: probably if NB/JNLP uses the classpath, it will not
want to include boot.jar. (It *could* but it should not need it.) So
registration of the security manager, currently somewhere in core.jar,
should be moved to boot.jar (org.nb.Main) so that NB/JNLP does not
call it. Whatever permissions are configured by JNLP itself should be

(Though you will need to check up on registration of
URLStreamHandlerFactory - does JNLP permit this? NB needs it. I have
long wanted to clean up all registration of VM-global things in NB,
since they cause major problems for (1) unit tests, (2) NB-based tools
like the <makeparserdb> Ant task.)

Re. use of ProxyClassLoader - (1) Module uses it if and only if you
create a module from JAR (which NB/JNLP never would if using
classpath), but still it statically refers to the class. (2)
ModuleManager currently uses it *always*, for systemClassLoader, even
though with all modules in the classpath it could simply return
ClassLoader.systemClassLoader (i.e. the app startup loader), and
disable all the code to set the Thread.contextClassLoader. Probably
all the code in org.netbeans.core.modules.* which deals with
Proxy/JarClassLoader or creates class loaders at all, should be
factored out into a simple interface with an impl in Lookup, so that
NB/JNLP (if using classpath) could provide a trivial alternate impl
and not use boot.jar classes in any way.

This (cleaning up org.netbeans.core.modules.* as above) will be a bit
of work, hopefully not much. I may have time to help with that.

Also core-execution.jar currently registers SecurityManager extensions
to TopSecurityManager. This also needs to be worked on. (1) If there
is no TopSecurityManager, of course it can't do that. Maybe the
registration could be declarative - e.g. add SM instances to
META-INF/services Lookup? NB/JNLP would then just ignore the
registration. (2) What happens if these SM hooks are not run, during
execution? System.exit() calls from executed processes will probably
really halt the VM, rather than stop the task. This is probably only a
problem for users of JavaThreadExecutor, which is somewhat deprecated
anyway. External execution, Ant, etc. should not have this problem.
(All other code in TopSecurityManager seems to be miscellaneous stuff
we could do without, including some startup optimizations.)
Comment 5 David Strupl 2003-07-23 19:06:03 UTC
Jesse, thanks for the offer to help with this. I just need to do the
changes as patches to release35. So if you do something in trunk I
will backport your changes to release35 on my private branch. Also
during next 2-3 weeks I will not yet work on this. I plan to finish
the zeroadmin module (that is sort of connected to this work) and
implement one more feature before I really star to to work on this one.

So there is at least for me still some time for discussion what should
be done here. I am also waiting for a management decision whether we
will need to support two versions of the same class simultaneously
loaded by the platform (the incompatible API change issue you
mentioned previously). I should know this some time next week.

Also my goal is for all the changes that would allow JNLP start to be
done such they can stay in trunk (4.0 or whatever). As I said it is ok
for me to support release35 on a private branch. But even there the
goal is to have the changes as little as possible.

Currently my changes are on branch platform_32247. Please note that I
was using special string "memory" as a value of "netbeans.user" to
indicate that we in fact run without the user dir. I thought about
using the same for "netbeans.home" and having null only in
"netbeans.dirs". What do you think?

Also is the state of the module system you are talking about from
release35 or were you talking about trunk? I would like to backport as
little as possible.
Comment 6 David Strupl 2003-09-23 23:06:05 UTC
The new version of my patches to core on branch platform_32247 is in
the cvs. I have added also a new documentation for the prefixed solution.
I have changed the installer/jnlp/build.xml to build the prefix solution.

I know that my changes to the core's module system classes might be
more chaotic than acceptable for the trunk. But I would really like to
have the solution in the trunk. I am ready to work on the trunk version.

Why had I implemented the prefix solution: the requirement to support
two versions of the same class is mandatory for me. The rationale
behind the decision are following: our product will contain quite a
huge number of modules. The modules will depend on 3rd party libs.
Different modules can depend on different versions of the libs - so we
have to support loading the different versions of the libs at the same
time. The flat classloader cannot do this - and we don't have full
control of the all the jar files making our product.

The new doc is here:
Comment 7 David Strupl 2006-06-05 12:07:03 UTC
I think this issue is obsoleted by Jarda's new implementation.
Comment 8 Jiri Rechtacek 2013-07-07 13:23:54 UTC
*** Bug 232119 has been marked as a duplicate of this bug. ***