weblaf icon indicating copy to clipboard operation
weblaf copied to clipboard

Potential NPE with WebTreeModel when using CheckStateChangeListener

Open mgarin opened this issue 4 years ago • 5 comments

Was mentioned by @Abu-Abdullah on Gitter.

This listener:

searchTree.addCheckStateChangeListener(new CheckStateChangeListener<DefaultMutableTreeNode>()
{
    @Override
    public void checkStateChanged(WebCheckBoxTree<DefaultMutableTreeNode> searchTree, List<CheckStateChange<DefaultMutableTreeNode>> checkStateChanges)
    {
        final java.util.List<DefaultMutableTreeNode> checkedNodes = searchTree.getNodes(CheckState.checked);
        ....

Throws next exception:

java.lang.NullPointerException
    at com.alee.extended.tree.NodesPositionComparator.compare(NodesPositionComparator.java:90)
    at com.alee.extended.tree.NodesPositionComparator.compare(NodesPositionComparator.java:36)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:356)
    at java.base/java.util.TimSort.sort(TimSort.java:220)
    at java.base/java.util.Arrays.sort(Arrays.java:1306)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1720)
    at java.base/java.util.Collections.sort(Collections.java:179)
    at com.alee.extended.tree.DefaultTreeCheckingModel.getNodes(DefaultTreeCheckingModel.java:137)
    at com.alee.extended.tree.WebCheckBoxTree.getNodes(WebCheckBoxTree.java:454)
    at com.alee.extended.tree.WebCheckBoxTree.getNodes(WebCheckBoxTree.java:441)
    at com.myapp.Indexer$2.checkStateChanged(Indexer.java:489)
    at com.alee.extended.tree.DefaultTreeCheckingModel.fireCheckStateChanged(DefaultTreeCheckingModel.java:683)
    at com.alee.extended.tree.DefaultTreeCheckingModel.setChecked(DefaultTreeCheckingModel.java:167)
    at com.alee.extended.tree.WebCheckBoxTree.setChecked(WebCheckBoxTree.java:467)
    at com.myapp.Indexer$22.actionPerformed(Indexer.java:3448)
    at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
    at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
    at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
    at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
    at java.desktop/javax.swing.AbstractButton.doClick(AbstractButton.java:369)
    at java.desktop/javax.swing.AbstractButton.doClick(AbstractButton.java:349)
    at com.myapp.Indexer$8$1.run(Indexer.java:1799)

It only happens with default model (WebTreeModel) used by WebLaF's checkbox tree:

WebCheckBoxTree<DefaultMutableTreeNode> searchTree = new WebCheckBoxTree<>(searchRoot);

It doesn't occur with DefaultTreeModel:

WebCheckBoxTree<DefaultMutableTreeNode> searchTree = new WebCheckBoxTree<>(new DefaultTreeModel(searchRoot));

Initial search for this exception didn't give any results, but I'm pretty sure it might occur in some rare cases or I'm missing something. This will need more testing/debugging.

mgarin avatar Jun 19 '20 16:06 mgarin

for some reason, im facing this now even using new DefaultTreeModel(), no clue what is happening here. the exception is little bit changed

javax.swing.tree.MutableTreeNode.getIndex(javax.swing.tree.TreeNode)" because "parent" is null
java.lang.NullPointerException: Cannot invoke "javax.swing.tree.MutableTreeNode.getIndex(javax.swing.tree.TreeNode)" because "parent" is null
at com.alee.extended.tree.NodesPositionComparator.compare(NodesPositionComparator.java:90)
at com.alee.extended.tree.NodesPositionComparator.compare(NodesPositionComparator.java:36)
at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
at java.base/java.util.TimSort.sort(TimSort.java:220)
at java.base/java.util.Arrays.sort(Arrays.java:1306)
at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
at java.base/java.util.Collections.sort(Collections.java:179)
at com.alee.extended.tree.DefaultTreeCheckingModel.getNodes(DefaultTreeCheckingModel.java:137)
at com.alee.extended.tree.WebCheckBoxTree.getNodes(WebCheckBoxTree.java:454)
at com.alee.extended.tree.WebCheckBoxTree.getNodes(WebCheckBoxTree.java:441)
at com.myapp.Indexer$2.checkStateChanged(Indexer.java:422)
at com.alee.extended.tree.DefaultTreeCheckingModel.fireCheckStateChanged(DefaultTreeCheckingModel.java:683)
at com.alee.extended.tree.DefaultTreeCheckingModel.setChecked(DefaultTreeCheckingModel.java:167)
at com.alee.extended.tree.WebCheckBoxTree.setChecked(WebCheckBoxTree.java:467)
at com.myapp.Indexer$22.actionPerformed(Indexer.java:3376)
at java.desktop/javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:1967)
at java.desktop/javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2308)
at java.desktop/javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:405)
at java.desktop/javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:262)
at java.desktop/javax.swing.AbstractButton.doClick(AbstractButton.java:369)
at java.desktop/javax.swing.AbstractButton.doClick(AbstractButton.java:349)
at com.myapp.Indexer$8$1.run(Indexer.java:1728)

if this is not enough, i will try to make a sample test case (the code is complex so it will take time to simluate this case)

Abu-Abdullah avatar Oct 19 '20 12:10 Abu-Abdullah

So all you do to get this is still simply calling searchTree.getNodes(CheckState.checked);, correct?

mgarin avatar Oct 19 '20 14:10 mgarin

I might actually have a clue about when this happens and why I'm not able to reproduce it. Does your tree show it's root node or is it hidden? and does it have a visible check box as well?

mgarin avatar Oct 19 '20 14:10 mgarin

So all you do to get this is still simply calling searchTree.getNodes(CheckState.checked);, correct?

yes, the error appears at this line. the logic is:

  • i invoke searchRoot.removeAllChildren() (after deleting one record) and recreate the searchRoot again with its new childs
  • i invoke again searchTree.setChecked(searchTree.getRootNode(), true) to select all the nodes by default. this by itself trigger CheckStateChangeListener in which i have the line that causes the issue searchTree.getNodes(CheckState.checked)

Abu-Abdullah avatar Oct 19 '20 14:10 Abu-Abdullah

I might actually have a clue about when this happens and why I'm not able to reproduce it. Does your tree show it's root node or is it hidden? and does it have a visible check box as well?

root node is displayed all the time and it has a visible check box

Abu-Abdullah avatar Oct 19 '20 14:10 Abu-Abdullah