PDA

View Full Version : treegrid NPE



meliniak
6 Dec 2010, 8:32 AM
I came across an error that seems to be hard to overcome. I'm using 2.2.1 version.

I'm using TreeGrid in my app. On selecting any of the rows, appropriate ModelData instance is bound to the form. After changing one of the fields in the form, following exception occurs:


java.lang.NullPointerException: null
at com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer.getId(TreeGridCellRenderer.java:55)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGridCellRenderer.render(TreeGridCellRenderer.java:37)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGridView.getRenderedValue(TreeGridView.java:328)
at com.extjs.gxt.ui.client.widget.grid.BufferView.doRender(BufferView.java:238)
at com.extjs.gxt.ui.client.widget.grid.BufferView.doRender(BufferView.java:194)
at com.extjs.gxt.ui.client.widget.grid.GridView.renderRows(GridView.java:1787)
at com.extjs.gxt.ui.client.widget.grid.GridView.insertRows(GridView.java:1364)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGridView.insertRows(TreeGridView.java:416)
at com.extjs.gxt.ui.client.widget.grid.GridView.refreshRow(GridView.java:1723)
at com.extjs.gxt.ui.client.widget.grid.GridView.onUpdate(GridView.java:1667)
at com.extjs.gxt.ui.client.widget.grid.GridView$6.storeUpdate(GridView.java:1327)
at com.extjs.gxt.ui.client.store.StoreListener.handleEvent(StoreListener.java:36)
at com.extjs.gxt.ui.client.store.StoreListener.handleEvent(StoreListener.java:1)
at com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:178)
at com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:86)
at com.extjs.gxt.ui.client.store.Store.update(Store.java:571)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGrid.onUpdate(TreeGrid.java:831)
at com.extjs.gxt.ui.client.widget.treegrid.TreeGrid$2.storeUpdate(TreeGrid.java:177)
at com.extjs.gxt.ui.client.store.StoreListener.handleEvent(StoreListener.java:36)
at com.extjs.gxt.ui.client.store.StoreListener.handleEvent(StoreListener.java:1)
at com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:178)
at com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:86)
at com.extjs.gxt.ui.client.store.Store.update(Store.java:571)
at com.extjs.gxt.ui.client.store.Store.onModelChange(Store.java:641)
at com.extjs.gxt.ui.client.store.TreeStore.onModelChange(TreeStore.java:808)
at com.extjs.gxt.ui.client.store.Store$1.modelChanged(Store.java:540)
at com.extjs.gxt.ui.client.data.ChangeEventSupport.notify(ChangeEventSupport.java:38)
at com.extjs.gxt.ui.client.data.BaseModel.notify(BaseModel.java:114)
at com.extjs.gxt.ui.client.data.BaseModel.notifyPropertyChanged(BaseModel.java:162)
at com.mycrmlite.client.BeanModel_com_mycrmlite_client_ContactEntryEntity.set(BeanModel_com_mycrmlite_client_ContactEntryEntity.java:205)
at com.extjs.gxt.ui.client.binding.FieldBinding.updateModel(FieldBinding.java:222)
at com.extjs.gxt.ui.client.binding.FieldBinding.onFieldChange(FieldBinding.java:242)
at com.extjs.gxt.ui.client.binding.FieldBinding$1.handleEvent(FieldBinding.java:54)
at com.extjs.gxt.ui.client.binding.FieldBinding$1.handleEvent(FieldBinding.java:1)
at com.extjs.gxt.ui.client.event.BaseObservable.callListener(BaseObservable.java:178)
at com.extjs.gxt.ui.client.event.BaseObservable.fireEvent(BaseObservable.java:86)
at com.extjs.gxt.ui.client.widget.Component.fireEvent(Component.java:455)
at com.extjs.gxt.ui.client.widget.form.Field.fireChangeEvent(Field.java:1050)
at com.extjs.gxt.ui.client.widget.form.Field.onBlur(Field.java:1091)
at com.extjs.gxt.ui.client.widget.form.TextField.onBlur(TextField.java:448)
at com.extjs.gxt.ui.client.widget.form.Field.onComponentEvent(Field.java:638)
at com.extjs.gxt.ui.client.widget.form.TextField.onComponentEvent(TextField.java:278)
at com.extjs.gxt.ui.client.widget.Component.onBrowserEvent(Component.java:883)
at com.google.gwt.user.client.DOM.dispatchEventImpl(DOM.java:1308)
at com.google.gwt.user.client.DOM.dispatchEvent(DOM.java:1264)
at sun.reflect.GeneratedMethodAccessor164.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:157)
at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:326)
at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:207)
at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:126)
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.core.client.impl.Impl.apply(Impl.java)
at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:214)
at sun.reflect.GeneratedMethodAccessor159.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:157)
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)

It seems that when the field is updated, the event is fired to update the row in the TreeGrid. This might be a bug?

Following method in TreeGrid results in NPE:


protected TreeNode findNode(M m) {
if (m == null || useKeyProvider == null) return null;
return nodes.get(useKeyProvider ? generateModelId(m) : cache.get(m));
}

useKeyProvider is set to false, so cache.get(m) is called, which in turn returns null. My guess is that the cache (Map<M, String> cache) is not updated with the changed ModelData. Does it sound reasonable?

Do you guys can point out ideas how to track down the source of the problem? Beside obvious test case preparing? :)

sven
6 Dec 2010, 8:34 AM
Do you guys can point out ideas how to track down the source of the problem? Beside obvious test case preparing?


Thats the best and fastest way. I never saw this exception in any application i have, nor did i see a report like this.


My guess is that the cache (Map<M, String> cache) is not updated with the changed ModelData.
The instance does not change with a FieldBinding updates the model, so this should not be a problem. Is it possible that you overrode the equals method and you change a field that is used in the equals check?

meliniak
7 Dec 2010, 2:34 AM
What a guess :) Indeed, correct. Removing the overridden equals method fixed the thing. Thanks for your help and quick reply, it saved me a lot of time.

sven
7 Dec 2010, 2:36 AM
If you need this equal method override, you can try to use a ModelKeyProvider that returns a "id" for example. This way the TreeGrid should still work.

For GXT3 we are planning internal changes so it will also work in other cases.

meliniak
7 Dec 2010, 3:05 AM
This might be a useful hint, thanks again.