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 244294 - Calling of TopComponent newInstance and readProperties via NBLifecycleManager.exit
Summary: Calling of TopComponent newInstance and readProperties via NBLifecycleManager...
Status: NEW
Alias: None
Product: platform
Classification: Unclassified
Component: Window System (show other bugs)
Version: 8.0
Hardware: PC Windows 7
: P3 normal with 2 votes (vote)
Assignee: Stanislav Aubrecht
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-05-05 08:25 UTC by arittner
Modified: 2015-05-26 11:37 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description arittner 2014-05-05 08:25:12 UTC
This is a crazy behavior.

On application exit the NetBeans platform calls first the instanceCreate and then readProperties methods of my top components. IMHO this is not a expected behavior.


NbLifecycleManager.exit -> NbLifeExit.exit -> ModuleSystem.shutDownAsync -> NbLifeExit.doStopInfra -> WindowSystemImpl.save -> PersistenceHandler.getDefault().save -> 

Here the problem with the line WindowManagerConfig wmc = getConfig():

305: public synchronized void save() {
        if( !loaded )
            return; //nothing to save
        if(DEBUG) {
            debugLog("## PersistenceHandler.save"); // NOI18N
        }
        TopComponentTracker.getDefault().save();

        ToolbarPool.getDefault().waitFinished();
        WindowManagerConfig wmc = getConfig();
        PersistenceManager.getDefault().saveWindowSystem(wmc);
    }


PersistenceManager.getConfig -> getConfigFromMode -> 

This calls many methods to read the registered TopComponents via

Central.isModePermanent including:

PersistenceManager.getTopComponentPersistentForID

and this methods invokes instanceCreate for a TopComponent:

570:             if (ic != null) {
                    TopComponent tc = (TopComponent)ic.instanceCreate();

This calls finally readProperties and starts many "live-Up" processes on shut-down.


I see this problem: With reading the Config it starts a harvesting method to collect all window configuration setting. This is going harmful on running the Central.isModePermanent method with the side effect in DefaultModel.isModePermanent:

867:/** Gets used defined. */
    @Override
    public boolean isModePermanent(ModeImpl mode) {
        ModeModel modeModel = getModelForMode(mode);
        if(modeModel != null) {
            boolean result = modeModel.isPermanent();
            if (!result) {
                for (TopComponent tc : mode.getTopComponents()) {
                    result |= tc.getClass().getAnnotation(RetainLocation.class)
                            != null;
                    if (result) {
                        break;
                    }
                }
            }
            return result;
        } else {
            return false;
        }
    }

ModeImpl.getTopComponents() creates new instances of all registered TopComponents. This instances are only used to ask for the Annontation RetainLocation.class (for RetainLocation-Patch, see https://netbeans.org/bugzilla/show_bug.cgi?id=179526 ). IMHO a big overhead and not useful on shut down.

However, a workaround is to ask:

Lookup.getDefault().lookup(LifecycleManager.class).isExiting()

in any readProperties Method to prevent start-up code in TopCompenents (e.g. loading data from files, databases ...). But this is not documented and a bad design. Additionally: Creating TopComponents on shut down is a bad performance killer, too.

br, josh.

At last a complete stack trace up to my constructor:

	at de.sepix.app.custdef.forms.person.empl.EmployeeTopComponent.<init>(EmployeeTopComponent.java:50)
Caused: java.lang.reflect.InvocationTargetException
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
	at org.netbeans.modules.settings.convertors.XMLSettingsSupport.newInstance(XMLSettingsSupport.java:100)
	at org.netbeans.modules.settings.convertors.XMLPropertiesConvertor.defaultInstanceCreate(XMLPropertiesConvertor.java:228)
Caused: java.io.IOException: Cannot create instance of de.sepix.app.custdef.forms.person.empl.EmployeeTopComponent
	at org.netbeans.modules.settings.convertors.XMLPropertiesConvertor.defaultInstanceCreate(XMLPropertiesConvertor.java:230)
	at org.netbeans.modules.settings.convertors.XMLPropertiesConvertor.read(XMLPropertiesConvertor.java:99)
	at org.netbeans.modules.settings.InstanceProvider$InstanceCookieImpl.instanceCreate(InstanceProvider.java:317)
[catch] at org.netbeans.core.windows.persistence.PersistenceManager.getTopComponentPersistentForID(PersistenceManager.java:571)
	at org.netbeans.core.windows.persistence.PersistenceManager.getTopComponentForID(PersistenceManager.java:681)
	at org.netbeans.core.windows.PersistenceHandler.getTopComponentForID(PersistenceHandler.java:478)
	at org.netbeans.core.windows.WindowManagerImpl.getTopComponentForID(WindowManagerImpl.java:962)
	at org.netbeans.core.windows.model.TopComponentSubModel.getTopComponent(TopComponentSubModel.java:378)
	at org.netbeans.core.windows.model.TopComponentSubModel.getTopComponents(TopComponentSubModel.java:90)
	at org.netbeans.core.windows.model.DefaultModeModel.getTopComponents(DefaultModeModel.java:356)
	at org.netbeans.core.windows.model.DefaultModel.getModeTopComponents(DefaultModel.java:944)
	at org.netbeans.core.windows.Central.getModeTopComponents(Central.java:1577)
	at org.netbeans.core.windows.ModeImpl.getTopComponents(ModeImpl.java:220)
	at org.netbeans.core.windows.model.DefaultModel.isModePermanent(DefaultModel.java:874)
	at org.netbeans.core.windows.Central.isModePermanent(Central.java:1556)
	at org.netbeans.core.windows.ModeImpl.isPermanent(ModeImpl.java:422)
	at org.netbeans.core.windows.PersistenceHandler.getConfigFromMode(PersistenceHandler.java:730)
	at org.netbeans.core.windows.PersistenceHandler.getConfig(PersistenceHandler.java:626)
	at org.netbeans.core.windows.PersistenceHandler.save(PersistenceHandler.java:314)
	at org.netbeans.core.windows.WindowSystemImpl.save(WindowSystemImpl.java:93)
	at org.netbeans.core.NbLifeExit.doStopInfra(NbLifeExit.java:150)
	at org.netbeans.core.NbLifeExit.run(NbLifeExit.java:97)
	at org.netbeans.core.startup.ModuleSystem$2.run(ModuleSystem.java:343)
	at org.netbeans.ModuleManager.shutDownAsync(ModuleManager.java:1991)
	at org.netbeans.core.startup.ModuleSystem.shutDownAsync(ModuleSystem.java:349)
	at org.netbeans.core.NbLifeExit.doExit(NbLifeExit.java:137)
	at org.netbeans.core.NbLifeExit.run(NbLifeExit.java:94)
	at org.openide.util.Mutex.doEvent(Mutex.java:1356)
	at org.openide.util.Mutex.readAccess(Mutex.java:355)
	at org.netbeans.core.NbLifecycleManager.exit(NbLifecycleManager.java:213)
	at org.netbeans.core.NbLifecycleManager.exit(NbLifecycleManager.java:119)
	at org.netbeans.core.windows.view.ui.MainWindow$9.windowClosing(MainWindow.java:528)
	at java.awt.AWTEventMulticaster.windowClosing(AWTEventMulticaster.java:349)
	at java.awt.AWTEventMulticaster.windowClosing(AWTEventMulticaster.java:349)
	at java.awt.Window.processWindowEvent(Window.java:2058)
	at javax.swing.JFrame.processWindowEvent(JFrame.java:297)
	at java.awt.Window.processEvent(Window.java:2017)
	at java.awt.Component.dispatchEventImpl(Component.java:4883)
	at java.awt.Container.dispatchEventImpl(Container.java:2292)
	at java.awt.Window.dispatchEventImpl(Window.java:2739)
	at java.awt.Component.dispatchEvent(Component.java:4705)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:746)
	at java.awt.EventQueue.access$400(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:697)
	at java.awt.EventQueue$3.run(EventQueue.java:691)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.awt.EventQueue$4.run(EventQueue.java:719)
	at java.awt.EventQueue$4.run(EventQueue.java:717)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:75)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:716)
	at org.netbeans.core.TimableEventQueue.dispatchEvent(TimableEventQueue.java:159)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Comment 1 arittner 2014-05-05 08:35:44 UTC
Oh dear, isExiting() is not declared in the interface LifecycleManager. It's a static method in NbLifecycleManager.

So, no workaround...
Comment 2 Jaroslav Tulach 2014-05-06 09:54:30 UTC
Yeah, I don't see a reason why components not yet in memory should be loaded on system exit. The bug however needs to be handled in window system.

A traditional workaround is to have own ModuleInstall.closing method and when it returns true, remember that the system is likely shutting down.
Comment 3 arittner 2015-05-01 20:30:36 UTC
IMHO another sideeffect on this bug:

http://forums.netbeans.org/viewtopic.php?p=163668

Is it possible to take a look on this?
Comment 4 cezariusz 2015-05-02 07:30:31 UTC
This problem hits me too. In my application some top components are heavy, and it takes some time to initialize. Because of this bug closing the application takes way longer than it should.
Comment 5 _ tboudreau 2015-05-02 21:38:48 UTC
Ancient but vaguely related:
https://netbeans.org/bugzilla/show_bug.cgi?id=28960
Comment 6 arittner 2015-05-26 10:52:52 UTC
(In reply to Jaroslav Tulach from comment #2)
> Yeah, I don't see a reason why components not yet in memory should be loaded
> on system exit. The bug however needs to be handled in window system.
> 
> A traditional workaround is to have own ModuleInstall.closing method and
> when it returns true, remember that the system is likely shutting down.

Yes, but you need a ModuleInstall or @OnStop Hook in any modul to catch the current shutdown state. So you spreed the "workaround"/"hack" in hundred of modules and add in hundred of TopComponents a "isShutDown" query...

:-/
Comment 7 arittner 2015-05-26 11:37:58 UTC
Some additional side effects:

Not only the <init> constructors from TopComponents are called. After that the shutdown process calls any writeProperties method.

This may bring more problems.