Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    Cannot change configuration property '_autoAssignedID' to true after the component ha

    Version:
    Isomorphic SmartClient/SmartGWT Framework (v8.3p_2013-05-23/PowerEdition Deployment 2013-05-23)

    I'm having an issue where when the code create a "new Window()", I sometimes get the error "Cannot change configuration property '_autoAssignedID' to true after the component has been created"

    The code does not call 'setID', it always lets it get auto generated. What I noticed is that when it happens, if I look in the watch tab of the developer console, instead of the control being named 'isc_Window_x', it is named after a window that I've already destroyed.

    I cannot create the error itself in a small program -- I tried without luck, but I can reproduce this odd naming behavior where it gives a new Window the name of the last destroyed object.

    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.google.gwt.core.client.GWT;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.rpc.RPCManager;
    import com.smartgwt.client.data.Record;
    import com.smartgwt.client.data.fields.*;
    import com.smartgwt.client.util.KeyCallback;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.Label;
    import com.smartgwt.client.widgets.Window;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.form.DynamicForm;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    import com.smartgwt.client.widgets.grid.events.RecordClickEvent;
    import com.smartgwt.client.widgets.grid.events.RecordClickHandler;
    import com.smartgwt.client.widgets.layout.VStack;
    import com.smartgwt.client.widgets.toolbar.ToolStrip;
    import com.smartgwt.client.widgets.viewer.DetailViewer;
    
    /**
     * Entry point classes define <code>onModuleLoad()</code>.
     */
    public class HibernateDS implements EntryPoint {
        private ListGrid boundList;
        private DynamicForm boundForm;
        private IButton saveBtn;
        private DetailViewer boundViewer;
    
        /**
         * This is the entry point method.
         */
        public void onModuleLoad() {
    
            
    		KeyIdentifier debugKey = new KeyIdentifier();
    		debugKey.setCtrlKey(true);
    		debugKey.setKeyName("D");
    
    		Page.registerKey(debugKey, new KeyCallback() {
    			public void execute(String keyName) {
    				SC.showConsole();
    			}
    		});
    
    
            
    		RPCManager.setActionURL(GWT.getModuleBaseURL() + "supplyItemHibernateOperations.rpc");
    		
            // instantiate DataSource on the client only (this example explicitly bypasses
            // ISC server-side DataSource management)
    
            DataSource dataSource = new DataSource();
            dataSource.setID("supplyItem");
    
            DataSourceSequenceField itemID = new DataSourceSequenceField("itemID");
            itemID.setPrimaryKey(true);
            itemID.setHidden(true);
    
            DataSourceTextField itemName = new DataSourceTextField("itemName", "Item", 128, true);
    
            DataSourceTextField SKU = new DataSourceTextField("SKU", "SKU", 10);
    
            DataSourceTextField description = new DataSourceTextField("description", "Description");        
            DataSourceTextField category = new DataSourceTextField("category", "Category", 128);
            DataSourceTextField units = new DataSourceTextField("units", "Units", 5);
    
            DataSourceFloatField unitCost = new DataSourceFloatField("unitCost", "Unit Cost");
            DataSourceBooleanField inStock = new DataSourceBooleanField("inStock", "In Stock");
    
            DataSourceDateField nextShipment = new DataSourceDateField("nextShipment", "Next Shipment");
    
            dataSource.setFields(itemID, itemName, SKU, description, category, units, unitCost, inStock, nextShipment);
    
    
            TestVStack vStack = new TestVStack();
            vStack.setLeft(175);
            vStack.setTop(75);
            vStack.setWidth("70%");
            vStack.setMembersMargin(20);
    
            Label label = new Label();
            label.setContents("<ul>" +
                    "<li>click a record in the grid to view and edit that record in the form</li>" +
                    "<li>click <b>New</b> to start editing a new record in the form</li>" +
                    "<li>click <b>Save</b> to save changes to a new or edited record in the form</li>" +
                    "<li>click <b>Clear</b> to clear all fields in the form</li>" +
                    "<li>click <b>Filter</b> to filter (substring match) the grid based on form values</li>" +
                    "<li>click <b>Fetch</b> to fetch records (exact match) for the grid based on form values</li>" +
                    "<li>double-click a record in the grid to edit inline (press Return, or arrow/tab to another record, to save)</li>" +
                    "</ul>");
            vStack.addMember(label);
    
            boundList = new ListGrid();
            boundList.setHeight(200);
            boundList.setCanEdit(true);
            boundList.setDataSource(dataSource);
    
            boundList.addRecordClickHandler(new RecordClickHandler() {
                public void onRecordClick(RecordClickEvent event) {
                    Record record = event.getRecord();
                    boundForm.editRecord(record);
                    saveBtn.enable();
                    boundViewer.viewSelectedData(boundList);
                }
            });
            vStack.addMember(boundList);
    
            boundForm = new DynamicForm();
            boundForm.setDataSource(dataSource);
            boundForm.setNumCols(6);
            boundForm.setAutoFocus(false);
            vStack.addMember(boundForm);
    
            ToolStrip toolbar = new ToolStrip();
            toolbar.setMembersMargin(10);
            toolbar.setHeight(22);
    
            saveBtn = new IButton("Save");
            saveBtn.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    boundForm.saveData();
                    if (!boundForm.hasErrors()) {
                        boundForm.clearValues();
                        saveBtn.disable();
                    }
                }
            });
            toolbar.addMember(saveBtn);
    
            IButton clearBtn = new IButton("Clear");
            clearBtn.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    boundForm.clearValues();
                    saveBtn.disable();
                }
            });
            toolbar.addMember(clearBtn);
    
            IButton filterBtn = new IButton("Filter");
            filterBtn.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    boundList.filterData(boundForm.getValuesAsCriteria());
                    saveBtn.disable();
                }
            });
            toolbar.addMember(filterBtn);
    
            IButton fetchBtn = new IButton("Fetch");
            fetchBtn.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    boundList.fetchData(boundForm.getValuesAsCriteria());
                    saveBtn.disable();
                }
            });
            toolbar.addMember(fetchBtn);
    
            IButton deleteBtn = new IButton("Delete");
            deleteBtn.addClickHandler(new ClickHandler() {
                public void onClick(ClickEvent event) {
                    boundList.removeSelectedData();
                    boundList.deselectAllRecords();
                }
            });
            toolbar.addMember(deleteBtn);
    
            vStack.addMember(toolbar);
    
            boundViewer = new DetailViewer();
            boundViewer.setDataSource(dataSource);
            vStack.addMember(boundViewer);
    
            vStack.draw();
            
            Window x = new Window();
            x.setTitle("x");
            x.show();
            
            Window y = new MyTestWindow();
            y.setTitle("y");
            y.show();
            y.destroy();
            
            Window z = new Window();
            z.setTitle("z");
            z.show();
            
    
            boundList.filterData(null);
        }
    
    }
    I have attached the watch tab from the developer console while running this code. The window 'x' is named isc_Window_0, and with Window 'z' is named isc_MyTestWindow_0, which is the name of the control that was destroyed.

    Note: All the 'test' classes do is extend the existing SmartGWT class so that a different name will be used to auto generate the ID:
    Code:
    package com.smartgwt.sample.client;
    
    import com.smartgwt.client.widgets.Window;
    
    public class MyTestWindow extends Window {
    
    	public MyTestWindow() {
    		super();
    	}
    }

    #2
    Here is the attachment
    Attached Files

    Comment


      #3
      We do actually recycle IDs by design because it's the only way to avoid long-term memory leaks in IE, which does not allow you to entirely clean up a global ID. So that's normal.

      As far as how you could get the issue about being unable to change _autoAssignedID, we've got one other report of this but no definitive test case. We're looking at it, but if you can find a way to reproduce the problem that would allow us to fix it right away.

      Comment


        #4
        That makes sense. I will be trying to track this down, so I will let you know if I find anything useful. Thanks.

        Comment


          #5
          I haven't been able to reproduce the issue in a small sample, but I can reproduce the problem in our large application. Do you have any tips on how I can track this down further? Here is what I have found:

          When it happens, the window that gets the error is creating a new Label control several layers deep, and it tries to use a control name that is already several layers up.

          You can see the difference between Watch_When_Success.jpg and Watch_When_Fail.jpg. The error_displayed.png shows the error dialog that pops up when it tries to create a label for a new control in a Window that is created when the button isc_buttonitem_8_button is pressed.
          Attached Files

          Comment


            #6
            We are investigating this to see if we can pin the cause down on our end. We'll let you know what we find

            Regards
            Isomorphic Software

            Comment


              #7
              Has there been any progress on this issue?
              Also, in the meantime, is there a way for us to turn off the reuse of the Window ID feature?

              Comment


                #8
                We've made a change in SGWT 3.1p so that when you create a new SGWT widget or set its ID, any existing (different) SGWT or SC object bound to that ID is destroyed, and a warning issued. If you were creating a new widget with a duplicate ID, you should no longer get a fatal exception mentioning _autoAssignedID.

                Today's build (built this morning) should have those changes.

                Comment


                  #9
                  I will try the latest build. However, in the cases shown in my previous posts, a new control was reusing an ID that was currently in use by another control. It should not have reused that ID. Are you saying that the other control will be destroyed?

                  Comment


                    #10
                    Nothing's changed about re-use of IDs - that part works the same as it has for years.

                    If you see an ID being re-used, it means either the ID has been recycled after you destroy()d a widget, or that in fact your code uses the same ID, and has been depending on the behavior that that automatically whatever widget is currently using the ID.

                    Comment


                      #11
                      It is behaving as I understood in my previous comment. The code is now destroying a control that is in use.

                      If you look at the image isc_AskValueFormDialog_0_headerLabelParent_label exists.JPG, this shows the watch window with the controls for a dialog that is being displayed in the UI.

                      On this dialog, we have an upload button that when pressed, creates a "please wait" dialog that is displayed over top of this dialog. The "please wait" dialog that we have contains the following code to create a label:

                      final Label waiting = new Label( "Processing..." );

                      It is creation of this label that reuses the identifier from the existing control:

                      11:05:12.296:MUP7:WARN:Log:Specified ID: isc_AskValueFormDialog_0_headerLabelParent_label collides with the ID for an existing object '[Label ID:isc_AskValueFormDialog_0_headerLabelParent_label]'. The existing object will be destroyed and the ID bound to the new object.

                      If you look at the image isc_AskValueFormDialog_0_headerLabelParent_label was removed.JPG, this shows the watch window with the controls for the dialog is now missing the headerLabelParent_label control because it was destroyed.

                      Additionally, we are getting some other odd behaviour with datasources. Every time we call DataSource.get( String ID ), we get a warning saying that it is destroying an object.

                      e.g. of warning with DataSource.get():
                      11:01:28.309:XRP9:WARN:Log:Specified ID: view_device_group collides with the ID for an existing SmartGWT component or object. The existing object will be destroyed and the ID bound to the new object.

                      This leads to other odd behaviour in our UI, presumably because an object in use has been destroyed.
                      Attached Files

                      Comment


                        #12
                        We're looking into the issues you mention. However, note that in the case of the first issue, the problem is not that the existing object is being destroy()ed by the second, but that the second object tries to claim an ID that's already in use. The point of object IDs is that at most a single object should have a given ID at one time. (A workaround for this would be to explicitly set the ID of the second widget.)

                        If you want to provide us with your actual code, it may allow us to reproduce that issue more quickly.

                        Comment


                          #13
                          yes, I understand that the second object is claiming the ID that is already in use. We are not setting our own IDs, they all get auto-generated.

                          I don't think it is feasible to simply set the ID of the second widget since there are too many places where this may occur. The sample I provided is just one place where this occurs where I can reproduce it easily.
                          Last edited by sderouchie; 4 Jun 2013, 08:38. Reason: answering part about workaround

                          Comment


                            #14
                            What sample are you referring to? The sample from the initial post merely demonstrates that IDs are recycled, which is a known and expected behavior.

                            Do you have an actual sample that reproduces the duplicate ID issue?

                            Comment


                              #15
                              I'm talking about the images I posted showing that an existing ID that is actually in use is being destroyed because it's ID gets pick up and reused by a new control.

                              I don't have sample code; I've been trying to produce a small sample, but I'm finding that I can't reproduce in a small sample.

                              Comment

                              Working...
                              X