0

NullpointerException after calling fireEvent(...) in TreeModel

asked 2011-07-06 17:32:29 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

Hello everyone,

I am currently trying to rename a Treeitem in my Tree component, like this:

treeitem.setLabel("foo");
Tree tree = treeitem.getTree();
if (tree != null) {
	TreeModel model = tree.getModel();
	if (model instanceof AdvancedTreeModel) {
		AdvancedTreeModel amodel = (AdvancedTreeModel) model;
		TreeNode node = renamedFolder.getNode();
		amodel.refreshNode(node);
	}
}

The AdvancedTreeModel looks like this:

public class AdvancedTreeModel extends DefaultTreeModel {
	private static final long	serialVersionUID	= 129891927119818367L;

	/**
	 * Refreshes the given node
	 * 
	 * @param node
	 *            The node to refresh
	 */
	public void refreshNode(TreeNode node) {
		if (node != null) {
			TreeNode parent = node.getParent();
			if (parent != null) {
				int index = parent.getIndex(node);
				if (index >= 0) {
					// This causes the NullPointerException!
					fireEvent(parent, index, index, TreeDataEvent.CONTENTS_CHANGED);
				}
			}
		}
	}
}

Unfortunately, this gives me a NullPointerException:

org.zkoss.zk.ui.UiException: Not a child: <Treeitem null>
	at org.zkoss.zul.Tree.addItemToSelection(Tree.java:845)
	at org.zkoss.zul.Tree$Renderer.render(Tree.java:1684)
	at org.zkoss.zul.Tree$Renderer.access$800(Tree.java:1664)
	at org.zkoss.zul.Tree.renderChangedItem(Tree.java:1851)
	at org.zkoss.zul.Tree.onTreeDataContentChange(Tree.java:1405)
	at org.zkoss.zul.Tree.onTreeDataChange(Tree.java:1337)
	at org.zkoss.zul.Tree.access$400(Tree.java:95)
	at org.zkoss.zul.Tree$4.onChange(Tree.java:1463)
	at org.zkoss.zul.AbstractTreeModel.fireEvent(AbstractTreeModel.java:77)
	at com.smampi.web.view.client.mailaccount.tree.AdvancedTreeModel.refreshNode(AdvancedTreeModel.java:93)

What am I doing wrong?

(Obviously, a Treeitem reference seems to be null but which one? I checked on both (the Treeitem for the current node as well as its parent) and they're both not null..

delete flag offensive retag edit

18 Replies

Sort by ยป oldest newest

answered 2011-07-07 08:43:58 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

Noone's got an idea? :-(

link publish delete flag offensive edit

answered 2011-07-07 08:50:31 +0800

marcelodecampos gravatar image marcelodecampos
183

Are you using a renderer? Could you show it?

link publish delete flag offensive edit

answered 2011-07-07 10:27:34 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

Yes, I do. It looks like this:

@Override
public void afterCompose() {
	super.afterCompose();
	
	tree_mailaccounts.setItemRenderer(new TreeitemRenderer() {
		@Override
		public void render(Treeitem item, Object obj) throws Exception {
			item.setValue(obj);

			Treerow treerow = item.getTreerow();
			if (treerow == null) {
				treerow = new Treerow();
				treerow.setParent(item);
			}
			treerow.setHflex("min");
			item.setHflex("min");

			// Registers an "onOpen" event for this item
			setTreeitemOnOpenEventListener(item);

			// Enable drag & drop
			treerow.setDroppable("true");
			treerow.setDraggable("true");

			// Set listener for drag and drop event
			setTreeRowOnDropListener(treerow);

			// Render the label of the tree item
			try {
				renderTreeitemLabel(item);
			} catch (Exception e) {
				handleException(e, false, null, null);
			}
		}

		/*
		 * Sets an event listener for the onOpen event on treeitems
		 */
		private void setTreeitemOnOpenEventListener(Treeitem item) {
			item.addEventListener(Events.ON_OPEN,
				new TreeitemOnOpenEventListener(item));
		}
	});
}

public int renderTreeitemLabel(Treeitem item) {

	if (item == null) {
		return -1;
	}

	Object obj = item.getValue();

	int count = -1;
	
	if (obj instanceof TreeNode) {
		TreeNode node = (TreeNode) obj;
		Object data = node.getData();
		boolean connectionWorks = true;
		CachedFolder cachedFolder = null;
		
		if (data instanceof MailAccount || data instanceof CachedFolder) {
			String label = "";
			MailAccount account = null;
			if (data instanceof MailAccount) {
				account = (MailAccount) data;
				account.setTreeitem(item);
				item.setContext(mpop_tree_mail_account);

				handleTreeitemOpenStatus(item, account);

				try {
					count = account.getNumberOfUnreadMessages(true);
				} catch (Exception e) {
					count = 0;
				}

				if (count > 0) {
					label = account.toString() + " (" + count + ")";
				} else {
					label = account.toString();
				}
				connectionWorks = account.getIncomingServer().connectionWorks();
			} else if (data instanceof CachedFolder) {
				cachedFolder = (CachedFolder) data;
				cachedFolder.setTreeitem(item);

				boolean useCache = true;
				count = cachedFolder.getNumOfUnreadMessages(useCache, true);
				label = cachedFolder.getName(useCache, true);

				// Saves if the item was open or closed
				handleTreeitemOpenStatus(item, cachedFolder);

				if (cachedFolder.isInbox(useCache)) {
					item.setContext(mpop_tree_folder_inbox);
				} else {
					item.setContext(mpop_tree_folder);
				}
			}

			Treerow tr = item.getTreerow();
			Treecell cell = null;

			if (tr == null) {
				tr = new Treerow();
				tr.setParent(item);
			}

			if (tr.getChildren().size() > 0) {
				cell = (Treecell) tr.getChildren().get(0);
				cell.setLabel(label);
			} else {
				cell = new Treecell(label);
				cell.setParent(tr);
			}

			// If unread messages exist, make the tree item bold
			if (count > 0) {
				cell.setTooltiptext(count + " " + "unread messages");
				cell.setStyle("font-weight: bold");
			} else {
				cell.setTooltiptext(null);
				cell.setStyle("font-weight: normal");
			}

			if (account != null) {
				account.setTreecell(cell);
			}

			if (cachedFolder != null) {
				cachedFolder.setTreecell(cell);
				if (cachedFolder.isInbox(true)) {
					cachedFolder.setFolderType(FolderType.INBOX);
				}
				cachedFolder.refreshIcon();
			}

			if (!connectionWorks) {
				cell.setStyle("text-decoration: line-through; color: #999;");
				cell.setTooltiptext("Connection to server failed");
			}

			// Remove hand cursor
			cell.setStyle(cell.getStyle() + "; cursor: default;");
		}
	}
	return count;
}

link publish delete flag offensive edit

answered 2011-07-11 04:17:11 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

Still cannot find the cause for the NullPointerException.. :-(

link publish delete flag offensive edit

answered 2011-07-11 06:29:39 +0800

matthewgo gravatar image matthewgo
375

Hi valmar,

maybe the treeitem is not attached to tree when you fireevent ?
can you provide a sample code to reproduce the issue?

link publish delete flag offensive edit

answered 2011-07-11 06:53:19 +0800

gsim gravatar image gsim
81

It seems that one of your treeitems has a bad reference to another tree
did you check if all treeitems passed to the render method in the TreeitemRenderer are correctly associated to your tree?

From org.zkoss.zulTree:

public void addItemToSelection(Treeitem item) {
	if (item.getTree() != this)
		throw new UiException("Not a child: "+item);

link publish delete flag offensive edit

answered 2011-07-11 08:21:20 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

updated 2011-07-11 08:22:10 +0800

gsim wrote:

It seems that one of your treeitems has a bad reference to another tree
did you check if all treeitems passed to the render method in the TreeitemRenderer are correctly associated to your tree?

Hm, I added the following to the item renderer. No effect :-(
Note: The tree I am working with is the only tree in the whole application. So it's unlikely that there an item point at a different tree.

if (item.getTree() != tree_mailaccounts) {
	try {
		// Gets never called
		Messagebox.show("Error, wrong Tree!");
	} catch (InterruptedException e) {
		e.printStackTrace();
	}
}

matthewgo wrote:

maybe the treeitem is not attached to tree when you fireevent ?
can you provide a sample code to reproduce the issue?

How could I check if the item is attached to the tree or not?
Regarding the sample code: I'll see if I can setup a small test project which reproduces the issue.

link publish delete flag offensive edit

answered 2011-07-11 09:00:32 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

updated 2011-07-11 09:02:39 +0800

I tried to create a project which reproduces the issue.

Unfortunately, I don't get the exception here. Instead, simply nothing happens when you click the button on the UI.

I think something smells really fishy here. Probably I am doing something completely the wrong way. Maybe some of you sees the error?

Download: http://dl.dropbox.com/u/17844821/zeug/TreeError.zip

(The app displays a tree with two items. One of these items is called "foo". After clicking the button below the tree, this node should be renamed.)

link publish delete flag offensive edit

answered 2011-07-11 10:06:21 +0800

gsim gravatar image gsim
81

You should always work with the model when changing data of the tree.

It makes no sense to store references of a treeitem, as they will be outdated when zk performs another request and render the ui again.

Just change the node in the model calling setData. This will trigger a TreeDataEvent on the model rendering again your tree and updating the ui.

link publish delete flag offensive edit

answered 2011-07-11 12:45:58 +0800

valmar gravatar image valmar
925 2 13
http://www.timo-ernst.net

updated 2011-07-11 13:10:12 +0800

Hmm... the "demo" in TreeError.zip works now after simply calling setData(...) on the node but in my "real" project I still get the same old exception after doing the change.

org.zkoss.zk.ui.UiException: Not a child: <Treeitem null>
	at org.zkoss.zul.Tree.addItemToSelection(Tree.java:845)
	at org.zkoss.zul.Tree$Renderer.render(Tree.java:1684)
	at org.zkoss.zul.Tree$Renderer.access$800(Tree.java:1664)
	at org.zkoss.zul.Tree.renderChangedItem(Tree.java:1851)
	at org.zkoss.zul.Tree.onTreeDataContentChange(Tree.java:1405)
	at org.zkoss.zul.Tree.onTreeDataChange(Tree.java:1337)
	at org.zkoss.zul.Tree.access$400(Tree.java:95)
	at org.zkoss.zul.Tree$4.onChange(Tree.java:1463)
	at org.zkoss.zul.AbstractTreeModel.fireEvent(AbstractTreeModel.java:77)
	at org.zkoss.zul.DefaultTreeNode.setData(DefaultTreeNode.java:119)

So, I guess the mistake is somewhere in my code but I just cannot find it..


Gsim, One thing I noticed about the code you posted:

public void addItemToSelection(Treeitem item) {
	if (item.getTree() != this)
		throw new UiException("Not a child: "+item);

The exception says: Not a child: <Treeitem null>

What exactly is the term "null" refering to at this point?
The item itself cannot be null. So, what's null then?

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2011-07-06 17:32:29 +0800

Seen: 750 times

Last updated: Feb 14 '12

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More