gwtproject / gwt

GWT Open Source Project
http://www.gwtproject.org
1.52k stars 374 forks source link

Deleting the last element on a CellTree #6676

Closed dankurka closed 9 years ago

dankurka commented 9 years ago

Originally reported on Google Code with ID 6677

Found in GWT Release:

GWT 2.3.0

Encountered on OS / Browser:

Windows 7 Service Pack 1, IE8, hosted mode. This is not an issue on Windows 7 Service
Pack 1 Chorme 13.0.782.112, FF3.5.19

Detailed description:

When we try to delete from a CellTree the last element of a level (from any level of
the CellTree) an Javascript Error occurs:

ERROR: Uncaught exception escaped. com.google.gwt.core.client.JavaScriptException:
(TypeError): 'firstChild' is null or not an object
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:237)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:132)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.dom.client.DOMImpl.getFirstChildElement(DOMImpl.java)
    at com.google.gwt.dom.client.Element$.getFirstChildElement$(Element.java:241)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getCellParent(CellTreeNodeView.java:665)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getCellParent(CellTreeNodeView.java:1044)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.setKeyboardSelected(CellTreeNodeView.java:1239)
    at com.google.gwt.user.cellview.client.CellTree.keyboardSelect(CellTree.java:867)
    at com.google.gwt.user.cellview.client.CellTreeNodeView$NodeCellList$View.loadChildState(CellTreeNodeView.java:345)
    at com.google.gwt.user.cellview.client.CellTreeNodeView$NodeCellList$View.replaceAllChildren(CellTreeNodeView.java:215)
    at com.google.gwt.user.cellview.client.HasDataPresenter.resolvePendingState(HasDataPresenter.java:1360)
    at com.google.gwt.user.cellview.client.HasDataPresenter.access$3(HasDataPresenter.java:1117)
    at com.google.gwt.user.cellview.client.HasDataPresenter$2.execute(HasDataPresenter.java:1042)
    at com.google.gwt.core.client.impl.SchedulerImpl$Task$.executeScheduled$(SchedulerImpl.java:50)
    at com.google.gwt.core.client.impl.SchedulerImpl.runScheduledTasks(SchedulerImpl.java:229)
    at com.google.gwt.core.client.impl.SchedulerImpl.flushFinallyCommands(SchedulerImpl.java:328)
    at com.google.gwt.core.client.impl.Impl.exit(Impl.java:238)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:229)
    at sun.reflect.GeneratedMethodAccessor165.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:167)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:281)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:531)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:352)
    at java.lang.Thread.run(Thread.java:662)

But it works by deleting any of the elements which is not the last one. It work also
if there are only one element.

Shortest code snippet which demonstrates issue:

Here a simple case of a CellTree TreeViewModel with one level of Strings

public class CellTreeModel implements TreeViewModel {

    private ListDataProvider<String> listDataProvider = new ListDataProvider<String>();

    private static int TEST_NUMBER = 0;

    public CellTreeModel() {
        listDataProvider.setList(new ArrayList<String>());
        add();
        add();
        add();
        add();
    }

    @Override
    public <T> NodeInfo<?> getNodeInfo(T value) {
        if (value == null) {
            List<HasCell<String, ?>> hasCells = new ArrayList<HasCell<String, ?>>();
            hasCells.add(new HasCell<String, String>() {
                @Override
                public Cell<String> getCell() {
                    return new ButtonCell();
                }

                @Override
                public FieldUpdater<String, String> getFieldUpdater() {
                    return new FieldUpdater<String, String>() {
                        @Override
                        public void update(int index, final String text, String value)
{
                            delete(text);
                        }
                    };
                }

                @Override
                public String getValue(String node) {
                    return "DELETE";
                }
            });
            hasCells.add(new HasCell<String, String>() {
                TextCell linkData = new TextCell();

                @Override
                public Cell<String> getCell() {
                    return linkData;
                }

                @Override
                public FieldUpdater<String, String> getFieldUpdater() {
                    return null;
                }

                @Override
                public String getValue(String text) {
                    return text;
                }
            });
            return new DefaultNodeInfo<String>(listDataProvider, new CompositeCell(hasCells));
        }
        return null;
    }

    @Override
    public boolean isLeaf(Object value) {
        return value instanceof String;
    }

    public void delete(final String text) {
        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
            @Override
            public void execute() {
                if (text != null && listDataProvider.getList().contains(text)) {
                    listDataProvider.getList().remove(text);
                }
                listDataProvider.refresh();
            }
        });

    }

    public void add() {
        listDataProvider.getList().add("TEST" + TEST_NUMBER++);
    }
}

Workaround if you have one:

Tried to extract the delete button from the CellTree and have one unique Delete button
which delete the selected elements (via a CheckBoxCell) but the same error occurs

Links to relevant GWT Developer Forum posts:

http://groups.google.com/group/google-web-toolkit/browse_thread/thread/73f7a73d059c0f51/fbebd749e64550f5#fbebd749e64550f5

Reported by lordether on 2011-08-11 09:31:21

dankurka commented 9 years ago
Hi

Is there any news about this issue? 
Even an workaround. 
Sorry to "bump" it but it's very important for us.

Thanks

Reported by lordether on 2011-08-30 08:39:07

dankurka commented 9 years ago
Hi,

I encountered the same issue, in our case we have problems only with IE (CellTree,
delete last child of a node breaks the tree, refresh is needed).

Regards,
Zolie

Reported by zetedi on 2011-09-02 08:09:48

dankurka commented 9 years ago
Add this to the list of one line fixes that take an hour to track down.  I'll send the
patch for review, but I attached it here in case you want to try it.

Reported by jlabanca@google.com on 2011-09-06 21:07:25


dankurka commented 9 years ago
Tanks a lot.
We have still time to see if it will be present on the next GWT release. If not we
have at least a workaround.

Reported by lordether on 2011-09-07 08:51:34

dankurka commented 9 years ago
committed as r10624

Reported by jlabanca@google.com on 2011-09-07 20:38:42

dankurka commented 9 years ago
I applied the patch, and bug still happens when refreshing a child of root with  
java.lang.AssertionError: Child index out of bounds

Reported by rsallar on 2011-11-11 14:51:42

dankurka commented 9 years ago
rsallar, can you try GWT trunk and see if you still have problems? If you do have this
problem, can you confirm that the original CellTreeModel example above reproduces it?
Or alternatively provide your own simple reproduction? Thanks!

Reported by stephen.haberman on 2011-11-19 04:25:39

dankurka commented 9 years ago
Got the similar issue. The patch works, thanks!

Tue Feb 14 15:52:30 GMT-800 2012 com.google.gwt.logging.client.LogConfiguration SEVERE:
(TypeError): Unable to get value of the property 'firstChild': object is null or undefined
com.google.gwt.core.client.JavaScriptException: (TypeError): Unable to get value of
the property 'firstChild': object is null or undefined
at Unknown.$fillInStackTrace(StackTraceCreator.java:168)
at Unknown.JavaScriptException_0(StackTraceCreator.java:421)
at Unknown.caught_0(Exceptions.java:29)
at Unknown.$setKeyboardSelected(CellTreeNodeView.java:1239)
at Unknown.$keyboardSelect(CellTree.java:867)
at Unknown.$loadChildState(CellTreeNodeView.java:345)
at Unknown.replaceAllChildren_3(CellTreeNodeView.java:215)
at Unknown.$resolvePendingState(HasDataPresenter.java:1365)
at Unknown.execute_8(HasDataPresenter.java:1055)
at Unknown.runScheduledTasks(SchedulerImpl.java:228)
at Unknown.$flushFinallyCommands(SchedulerImpl.java:327)
at Unknown.entry0(Impl.java:237)
at Unknown.anonymous(Impl.java:57)

Reported by zhutony on 2012-02-15 00:53:54

dankurka commented 9 years ago
Is there a way to test the fix? Maybe a gwt-2.5-snapshot.jar ?

Reported by marco.samstag on 2012-02-22 16:19:52

dankurka commented 9 years ago
I made the changes manually to the sources of 2.4.0 based on the r10624. Unfortunately
the problem remains.

Please post a solution for this.

Reported by kklearchou on 2012-06-05 17:46:17

dankurka commented 9 years ago
kklearchou, there has been a solution posted for this, it's in GWT trunk. You can either
build trunk yourself:

https://developers.google.com/web-toolkit/makinggwtbetter#compiling

Or wait for GWT 2.5 to be released.

Reported by stephen.haberman on 2012-06-07 04:55:29

dankurka commented 9 years ago
Bulk edit: should be fixed in the GWT 2.5 release candidate.

Reported by skybrian@google.com on 2012-06-27 03:38:12

dankurka commented 9 years ago
Hi to all,

certainly this issue has been corrected but not 100%.
I am still able to reproduce it with my CellTree and unfortunately the consequences
are not nice.
The cell tree disappears from the user's view.

Here is the error use case:
Root:
--> Child 1
----> Child 1.1
--> Child 2

While child 2 is selected delete child 1 and all the children under it.
We use SingleSelectionModel.

Here is a stacktrace:
Uncaught exception: com.google.gwt.core.client.JavaScriptException: (TypeError) @com.google.gwt.dom.client.DOMImpl::getFirstChildElement(Lcom/google/gwt/dom/client/Element;)([null]):
Unable to get value of the property 'firstChild': object is null or undefined
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:249)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.dom.client.DOMImpl.getFirstChildElement(DOMImpl.java)
    at com.google.gwt.dom.client.Element$.getFirstChildElement$(Element.java:267)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getImageElement(CellTreeNodeView.java:733)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getImageElement(CellTreeNodeView.java:1121)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.updateImage(CellTreeNodeView.java:1415)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.access$8(CellTreeNodeView.java:1396)
    at com.google.gwt.user.cellview.client.CellTreeNodeView$NodeCellList$View.setLoadingState(CellTreeNodeView.java:274)
    at com.google.gwt.user.cellview.client.HasDataPresenter.updateLoadingState(HasDataPresenter.java:1512)
    at com.google.gwt.user.cellview.client.HasDataPresenter.resolvePendingState(HasDataPresenter.java:1342)
    at com.google.gwt.user.cellview.client.HasDataPresenter.access$3(HasDataPresenter.java:1062)
    at com.google.gwt.user.cellview.client.HasDataPresenter$2.execute(HasDataPresenter.java:984)
    at com.google.gwt.core.client.impl.SchedulerImpl$Task$.executeScheduled$(SchedulerImpl.java:50)
    at com.google.gwt.core.client.impl.SchedulerImpl.runScheduledTasks(SchedulerImpl.java:228)
    at com.google.gwt.core.client.impl.SchedulerImpl.flushFinallyCommands(SchedulerImpl.java:327)
    at com.google.gwt.core.client.impl.Impl.exit(Impl.java:266)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:257)
    at sun.reflect.GeneratedMethodAccessor126.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Unknown Source) 

As I said in the past (GWT 2.4) this kind of errors were considerably more (and easily
reproducible) than in GWT 2.5.

Best regards,
Klearchos

Reported by kklearchou on 2012-11-05 14:21:17

dankurka commented 9 years ago
Do you think you can provide a reproducible test case?
Ideally something similar to https://code.google.com/p/google-web-toolkit/source/diff?spec=svn10624&old=9403&r=10624&format=unidiff&path=%2Ftrunk%2Fuser%2Ftest%2Fcom%2Fgoogle%2Fgwt%2Fuser%2Fcellview%2Fclient%2FAbstractCellTreeTestBase.java
that could be integrated to the test suite and serve as a regression test.

Reported by t.broyer on 2012-11-14 23:18:01

dankurka commented 9 years ago
I also get this exception.
It's very strange because in an other tree I don't get this exception.
I played around with the isLeaf method, because I was thinking that
there could be the problem but without any effect.

I can reproduce the error every time I delete the last element but only
in one tree. I don't know where the difference is between my two trees.

Is it possible to find out the problem with the stack trace?

com.google.gwt.core.client.JavaScriptException: (TypeError) @com.google.gwt.dom.client.DOMImpl::getFirstChildElement(Lcom/google/gwt/dom/client/Element;)([null]):
Für die Eigenschaft "firstChild" kann kein Wert abgerufen werden: Das Objekt ist Null
oder undefiniert
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:249)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:571)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:279)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.dom.client.DOMImpl.getFirstChildElement(DOMImpl.java)
    at com.google.gwt.dom.client.Element$.getFirstChildElement$(Element.java:267)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getImageElement(CellTreeNodeView.java:733)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.getImageElement(CellTreeNodeView.java:1121)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.updateImage(CellTreeNodeView.java:1415)
    at com.google.gwt.user.cellview.client.CellTreeNodeView.access$8(CellTreeNodeView.java:1396)
    at com.google.gwt.user.cellview.client.CellTreeNodeView$NodeCellList$View.setLoadingState(CellTreeNodeView.java:274)
    at com.google.gwt.user.cellview.client.HasDataPresenter.updateLoadingState(HasDataPresenter.java:1512)
    at com.google.gwt.user.cellview.client.HasDataPresenter.resolvePendingState(HasDataPresenter.java:1342)
    at com.google.gwt.user.cellview.client.HasDataPresenter.access$3(HasDataPresenter.java:1062)
    at com.google.gwt.user.cellview.client.HasDataPresenter$2.execute(HasDataPresenter.java:984)
    at com.google.gwt.core.client.impl.SchedulerImpl$Task$.executeScheduled$(SchedulerImpl.java:50)
    at com.google.gwt.core.client.impl.SchedulerImpl.runScheduledTasks(SchedulerImpl.java:228)
    at com.google.gwt.core.client.impl.SchedulerImpl.flushFinallyCommands(SchedulerImpl.java:327)
    at com.google.gwt.core.client.impl.Impl.exit(Impl.java:266)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:257)
    at sun.reflect.GeneratedMethodAccessor40.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Unknown Source)

Reported by marco.samstag on 2013-01-19 12:24:47

dankurka commented 9 years ago
I have pretty much the exact same issue. Has anyone figured out a solution for this?
I'll provide any additional info requested to help solve this. 

This occurs on a CellTree when I close the child nodes. I have a CellTree where I have
completely replaced the nodes in the Model. The Tree displays OK and when I click to
expand the Tree it opens OK with no errors.

However when I click to collapse the tree I get the following errors. The Tree does
close OK and appears to function OK except for the repeated error messages as I repeatedly
close the tree nodes.

03:09:33.615 [ERROR] [lm] Uncaught exception escaped

com.google.gwt.core.client.JavaScriptException: (TypeError) @com.google.gwt.core.client.impl.Impl::apply(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)([JavaScript
object(3164), JavaScript object(1587), JavaScript object(7279)]): elem is null
    at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:249)
    at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:576)
    at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:284)
    at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
    at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:347)
    at sun.reflect.GeneratedMethodAccessor38.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Unknown Source)

Reported by bob@staats.me on 2014-04-12 10:18:23

dankurka commented 9 years ago
I discovered the source of my issue. I have a CompositeCell in my CellTree. I changed
from a table layout on the cell back to the default span and forgot to change the getContainerElement
method to return the correct element.

I had: 

@Override
                    protected Element getContainerElement(Element parent) {
                        // Return the first TR element in the table.
                        return parent.getFirstChildElement().getFirstChildElement().getFirstChildElement();
                    }

I needed to change to:

@Override
                    protected Element getContainerElement(Element parent) {

                        return parent;
                    }

Reported by bob@staats.me on 2014-04-15 03:51:36

dankurka commented 9 years ago
I also have this issue with GWT 2.6.1, I'm changing the size of my cell table contents
depending on the filters applied. I still didn't grab when it exactly happens, I'll
keep you informed as I'm getting to a bug fix phase
ServerExceptionHandler caught exception toIndex = 2
java.lang.IndexOutOfBoundsException: toIndex = 2
    at java.util.ArrayList.subListRangeCheck(ArrayList.java:962)
    at java.util.ArrayList.subList(ArrayList.java:954)
    at com.google.gwt.user.cellview.client.HasDataPresenter.resolvePendingState(HasDataPresenter.java:1361)
    at com.google.gwt.user.cellview.client.HasDataPresenter.access$3(HasDataPresenter.java:1062)
    at com.google.gwt.user.cellview.client.HasDataPresenter$2.execute(HasDataPresenter.java:984)
    at com.google.gwt.core.client.impl.SchedulerImpl$Task$.executeScheduled$(SchedulerImpl.java:50)
    at com.google.gwt.core.client.impl.SchedulerImpl.runScheduledTasks(SchedulerImpl.java:180)
    at com.google.gwt.core.client.impl.SchedulerImpl.flushFinallyCommands(SchedulerImpl.java:277)
    at com.google.gwt.core.client.impl.Impl.exit(Impl.java:380)
    at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:371)
    at sun.reflect.GeneratedMethodAccessor347.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
    at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
    at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
    at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:293)
    at 
com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:547)
    at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:364)
    at java.lang.Thread.run(Thread.java:745)

Reported by 1vue.eu on 2014-06-23 13:47:26