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 109098 - Mode dockin() works incorrectly and led unexpected behavior
Summary: Mode dockin() works incorrectly and led unexpected behavior
Status: VERIFIED FIXED
Alias: None
Product: platform
Classification: Unclassified
Component: Window System (show other bugs)
Version: 6.x
Hardware: All All
: P2 blocker (vote)
Assignee: mslama
URL:
Keywords:
Depends on: 41272
Blocks:
  Show dependency tree
 
Reported: 2007-07-09 05:37 UTC by _ theanuradha
Modified: 2008-12-22 13:24 UTC (History)
1 user (show)

See Also:
Issue Type: DEFECT
Exception Reporter:


Attachments
Project (5.83 KB, application/octet-stream)
2007-07-09 05:38 UTC, _ theanuradha
Details
PACH (1.17 KB, patch)
2007-08-03 08:13 UTC, _ theanuradha
Details | Diff
PATCH (1.17 KB, patch)
2007-08-03 08:13 UTC, _ theanuradha
Details | Diff
PATCH (1.17 KB, patch)
2007-08-03 08:17 UTC, _ theanuradha
Details | Diff
PATCH (2.26 KB, patch)
2007-08-04 06:31 UTC, _ theanuradha
Details | Diff
my version of the patch (1.13 KB, application/octet-stream)
2007-08-06 16:17 UTC, David Simonek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description _ theanuradha 2007-07-09 05:37:06 UTC
When dock in to Mode   works incorrectly and led unexpected behavior

Steps
 1 Create Module Project and add Window system API and UI Utilities API as dependencies 
 2 Add Action to it (Name = Mode Issue)
 3 fill performAction() method with this code

        //get the Project TC 
        TopComponent projectTC = WindowManager.getDefault().findTopComponent("projectTabLogical_tc");
        //get before Id
        String beforId = WindowManager.getDefault().findTopComponentID(projectTC);

        System.out.println("Before Project TC ID : " + beforId);
        //find the output mode
        final Mode findMode = WindowManager.getDefault().findMode("output");
        //dock in
        findMode.dockInto(projectTC);
        /*may be issue topcomponent need to open becouse dock in
        close the topcomponent */
        projectTC.open();
        //get after Id
        String afterId = WindowManager.getDefault().findTopComponentID(projectTC);
        System.out.println("After Project TC ID : " + afterId);
  4 Run Application and invoke the Action

  Note that topcomponent Id change after Dock in and it will close (may be issue).Now close the application and restart
  Two Project Tc will Open
  I Create the Module Project I will attach it with this Issue
Comment 1 _ theanuradha 2007-07-09 05:38:16 UTC
Created attachment 44802 [details]
Project
Comment 2 David Simonek 2007-07-09 16:06:29 UTC
P1 is reserved for crashes and data loss, lowering the priority.

How do you run the application when it is not an application but netbeans module? Do you install the module into running
NetBeans system? It's very strange use case to move with 'live' top components from another modules, why do you need it?

Please describe your steps and motivation in exact details, thanks.
Comment 3 _ theanuradha 2007-07-10 05:26:42 UTC
AFAIK Application or NetBeans system make no deference .I Just pick Project TC as a example what  I have many Module in
Platform Application that Providing different functionalities. The  use case is One Module will handle window Layouts
and allow user to create Custom views and switch between different views as needed. Even this is  very strange use case
Window System Is Core API and must react to specification. Doc says 

dockInto

boolean dockInto(TopComponent c)

    Attaches a component to a mode for this workspace. If the component is in different mode on this workspace, it is
removed from the original and moved to this one.

    Parameters:
        c - component 
    Returns:
        true if top component was successfully docked to this mode, false otherwise


so it must provide functionality what it documented right and even TopComponent unique ID can't be change after calling
dockInto right .Here the steps again

Steps
 1 Create Module Project and add Window system API and UI Utilities API as dependencies 
 2 Add Action to it (Name = Mode Issue)
 3 fill performAction() method with this code

        //get the Project TC 
        TopComponent projectTC = WindowManager.getDefault().findTopComponent("projectTabLogical_tc");
        //get before Id
        String beforId = WindowManager.getDefault().findTopComponentID(projectTC);

        System.out.println("Before Project TC ID : " + beforId);
        //find the output mode
        final Mode findMode = WindowManager.getDefault().findMode("output");
        //dock in
        findMode.dockInto(projectTC);
        /*may be issue topcomponent need to open becouse dock in
        close the topcomponent */
        projectTC.open();
        //get after Id
        String afterId = WindowManager.getDefault().findTopComponentID(projectTC);
        System.out.println("After Project TC ID : " + afterId);

  4 Run Module it will open new NetBeans system right then  invoke the Action that we create 

Look at output window sop details unique ID got changed and after close and run module again will open two Project
topcomponents that really  unexpected behavior

Comment 4 _ theanuradha 2007-08-03 08:08:03 UTC
I found the bug in Nb source (I think) 

  whan calling dockInto() it calls its IMPL class "SOURCE_PATH"\core\windows\src\org\netbeans\core\windows\ModeImpl.java
   dockIntoImpl(final TopComponent tc, final boolean select) method.
   before dock it close TopComponent and remove from previous mode. to remove from previous mode it call method

   removeModeTopComponent(ModeImpl mode, TopComponent tc) 
   in  "SOURCE_PATH"\core\windows\src\org\netbeans\core\windows\Central.java 

   In that method it call removeGlobalTopComponentID(String id) in 
   "SOURCE_PATH"\core\windows\src\org\netbeans\core\windows\persistence\PersistenceManager.java

   that method clearly say "make sure you call this only on TCs that are NOT TC.PERSISTENT_ALWAYS" so thats the 
   mistake so we need to make sure you call this only on TCs that are NOT TC.PERSISTENT_ALWAYS .

   So I create diff patch to Central.java .I'll attach that.

   (PS I didn't fill  a Contributor Agreement. I'll do it today :))




 
Comment 5 _ theanuradha 2007-08-03 08:13:38 UTC
Created attachment 46102 [details]
PACH
Comment 6 _ theanuradha 2007-08-03 08:13:55 UTC
Created attachment 46103 [details]
PATCH
Comment 7 _ theanuradha 2007-08-03 08:17:31 UTC
Created attachment 46104 [details]
PATCH
Comment 8 _ theanuradha 2007-08-03 08:24:43 UTC
sorry for mistake use last  patch and ignore previous ones sorry 
Comment 9 _ theanuradha 2007-08-04 06:31:45 UTC
Created attachment 46150 [details]
PATCH
Comment 10 _ theanuradha 2007-08-04 06:36:47 UTC
I just attach better patch.I did find all usage go  removeGlobalTopComponentID(String id) and make sure to call this 
only on TCs that are NOT TC.PERSISTENT_ALWAYS
Comment 11 David Simonek 2007-08-06 15:40:28 UTC
Wow, thanks for the patch, it appears that it may be right one, I just need to verify and understand the code a bit more
before integration.

Ccing Marek who knows perhaps more about TopComponent IDs.
Comment 12 David Simonek 2007-08-06 16:17:56 UTC
Created attachment 46215 [details]
my version of the patch
Comment 13 David Simonek 2007-08-06 16:21:48 UTC
theanuradha, it seems your findings were exact and good. I just simplified the patch a bit, because there is already a
method WindowManagerImpl.isTopComponentPersistentWhenClosed which does the test.

I verified that the patch works. I'm leaving on vacation right now, so Marek feel free to integrate if you want. But
maybe the best solution would be also to add a check, perhaps even assertion into removeGlobalTopComponentID, to never
call it on persistent TCs.
Comment 14 _ theanuradha 2007-08-07 14:50:07 UTC
So Marek any comments about integrate the Patch ?
Comment 15 mslama 2007-08-07 15:50:47 UTC
Do I understand problem correctly that TC ID generated for given TC instance is different second time it is registered
in winsys?

This is all wrong. Original issue #41272 introduced removeGlobalTopComponentID to avoid memory leak. (Internal map
<String,WeakReference<TopComponent>> was not cleared when TopComponent instance was garbage collected. BUT this way is
wrong as map should be cleared AFTER TopComponent instance was gc'ed. In current situation we remove ID from map and
cache BEFORE TC is gc'ed. It can result in this behavior: ID assigned to TC second time is different from original TC ID
because removeGlobalTopComponentID was called between.

If this is the case I will close this issue, reopen issue #41272 and fix memory another way.
Comment 16 mslama 2007-08-07 17:41:45 UTC
This issue will be solved with fix of #41272. I will close this issue as I verify this using provided test case.
Probably I will write test for it too.
Comment 17 _ theanuradha 2007-08-08 05:31:13 UTC
I think this  issue #41272 introduced removeGlobalTopComponentID nothing to do with this issue because
removeGlobalTopComponentID clearly say "make sure you call this only on TCs that are NOT TC.PERSISTENT_ALWAYS" so that's
the 
   mistake so we need to make sure you call this only on TCs that are NOT TC.PERSISTENT_ALWAYS .I think
TC.PERSISTENT_ALWAYS Tc must hold reference to persist regardless of open or not .So My suggest is just  make sure you
call this only on TCs that are NOT TC.PERSISTENT_ALWAYS .
Comment 18 mslama 2007-08-08 07:25:24 UTC
I explain issue in mode detail as it is closely related to TC instance lifecycle. Requirements for TC ID:
1.TC ID must be unique.
2.TC ID assigned to TC must stay fixed once it is assigned. This requirement is not so strong we could live without it
but I believe this is reasonable and makes things clearer for user of Window System API.

For always persistent TC it is quite simple. Usually such TC is singleton so once instantiated it is never gc'ed because
singleton keeps strong reference to TC instance in its private static field. So this is root and TC cannot be gc'ed.

For non persistent and peristent only opened it is more complex. Look at this use case:
1.Create TC instance at runtime.
2.You must somehow register TC instance with winsys eg. open TC or dock and open.
3.When you now close this TC removeGlobalTopComponentID will be invoked. It will deregister TC in winsys.
4.When you now open this TC again it will be again registered and possibly new TC ID different from previous one will be
assigned by winsys to this TC even if this TC is not persistent.

This is I want to avoid. My fix will release used TC ID AFTER Tc instance is gc'ed. I hope it is clearer now and you
understand why I belive yoyur patch is not sufficient and it will solve problem only for persistent TC.

In addition current impl of removeGlobalTopComponentID says it should be called only for non persistent TC but of course
there is no check for it. Really error prone.
Comment 19 mslama 2007-08-08 07:26:04 UTC
I explain issue in mode detail as it is closely related to TC instance lifecycle. Requirements for TC ID:
1.TC ID must be unique.
2.TC ID assigned to TC must stay fixed once it is assigned. This requirement is not so strong we could live without it
but I believe this is reasonable and makes things clearer for user of Window System API.

For always persistent TC it is quite simple. Usually such TC is singleton so once instantiated it is never gc'ed because
singleton keeps strong reference to TC instance in its private static field. So this is root and TC cannot be gc'ed.

For non persistent and peristent only opened it is more complex. Look at this use case:
1.Create TC instance at runtime.
2.You must somehow register TC instance with winsys eg. open TC or dock and open.
3.When you now close this TC removeGlobalTopComponentID will be invoked. It will deregister TC in winsys.
4.When you now open this TC again it will be again registered and possibly new TC ID different from previous one will be
assigned by winsys to this TC even if this TC is not persistent.

This is I want to avoid. My fix will release used TC ID AFTER Tc instance is gc'ed. I hope it is clearer now and you
understand why I believe your patch is not sufficient and it will solve problem only for persistent TC.

In addition current impl of removeGlobalTopComponentID says it should be called only for non persistent TC but of course
there is no check for it. Really error prone.
Comment 20 _ theanuradha 2007-08-08 09:07:49 UTC
Thanks For details.  Now I got the issue. 
Comment 21 mslama 2007-08-08 20:50:16 UTC
Issue #41272 is fixed. I also run your test case and it works fine now. Please verify. Let me know if you find any
problem. Thanks for catching this tricky issue.
Comment 22 _ theanuradha 2007-08-09 06:26:34 UTC
verifyed