Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » Databinding - AssertionFailedException on disposing TreeViewer: Getter called on disposed observable
Databinding - AssertionFailedException on disposing TreeViewer: Getter called on disposed observable [message #1013954] Sun, 24 February 2013 20:26 Go to next message
Max Hohenegger is currently offline Max HoheneggerFriend
Messages: 9
Registered: April 2012
Junior Member

I'm getting an AssertionFailedException when a FilteredTree in my Eclipse 4 RCP application is disposed.
I can reproduce this every time with the following steps:
- start application
- add entry to the IObservableList that is the input for the TreeViewer
- close application
The stack trace is below.

I have found several bug reports and posts with similar problems, including in this forum, however; no solution:
http://www.eclipse.org/forums/index.php/m/956361/
https://bugs.eclipse.org/bugs/show_bug.cgi?id=278550
java-forums.org/swt-jface/46332-sorting-edited-entry-treeviewer.html

I have created a minimal example based on the databinding tutorial by Lars Vogel:
www.vogella.com/articles/EclipseDataBinding/article.html
Additionaly, create some entries:
		persons = new ArrayList<>();		
		observableList = Properties.selfList(Person.class).observe(persons);
		Person homer = new Person();
		homer.setName("Homer Simpson");
		observableList.add(homer);


Feed it to the viewer, and refresh if changed.
		observableList .addListChangeListener(new IListChangeListener() {
			@Override
			public void handleListChange(ListChangeEvent event) {
				viewer.getViewer().refresh();
			}
		});
		viewer.getViewer().setInput(entries);


The stack trace:
org.eclipse.core.runtime.AssertionFailedException: assertion failed: Getter called on disposed observable org.eclipse.core.internal.databinding.property.list.SimplePropertyObservableList@15ae9009
	at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110)
	at org.eclipse.core.databinding.observable.ObservableTracker.getterCalled(ObservableTracker.java:252)
	at org.eclipse.core.internal.databinding.property.list.SimplePropertyObservableList.getterCalled(SimplePropertyObservableList.java:112)
	at org.eclipse.core.internal.databinding.property.list.SimplePropertyObservableList.hashCode(SimplePropertyObservableList.java:583)
	at java.util.HashMap.hash(Unknown Source)
	at java.util.HashMap.removeEntryForKey(Unknown Source)
	at java.util.HashMap.remove(Unknown Source)
	at org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider$TreeNode.dispose(ObservableCollectionTreeContentProvider.java:491)
	at org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider$TreeNode.access$0(ObservableCollectionTreeContentProvider.java:489)
	at org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider.inputChanged(ObservableCollectionTreeContentProvider.java:137)
	at org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider$Impl.inputChanged(ObservableListTreeContentProvider.java:55)
	at org.eclipse.jface.databinding.viewers.ObservableListTreeContentProvider.inputChanged(ObservableListTreeContentProvider.java:203)
	at org.eclipse.jface.viewers.ContentViewer.handleDispose(ContentViewer.java:171)
	at org.eclipse.jface.viewers.StructuredViewer.handleDispose(StructuredViewer.java:2328)
	at org.eclipse.jface.viewers.ContentViewer$2.widgetDisposed(ContentViewer.java:214)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:123)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1058)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:808)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Composite.releaseChildren(Composite.java:873)
	at org.eclipse.swt.widgets.Widget.release(Widget.java:811)
	at org.eclipse.swt.widgets.Widget.dispose(Widget.java:446)
	at org.eclipse.e4.ui.workbench.renderers.swt.SWTPartRenderer.disposeWidget(SWTPartRenderer.java:137)
	at org.eclipse.e4.ui.workbench.renderers.swt.ContributedPartRenderer.disposeWidget(ContributedPartRenderer.java:285)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:847)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:808)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:801)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:808)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:808)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.safeRemoveGui(PartRenderingEngine.java:808)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.access$3(PartRenderingEngine.java:775)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$8.run(PartRenderingEngine.java:770)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.removeGui(PartRenderingEngine.java:755)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.cleanUp(WBWRenderer.java:609)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer.access$5(WBWRenderer.java:598)
	at org.eclipse.e4.ui.workbench.renderers.swt.WBWRenderer$11.shellClosed(WBWRenderer.java:576)
	at org.eclipse.swt.widgets.TypedListener.handleEvent(TypedListener.java:98)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062)
	at org.eclipse.swt.widgets.Decorations.closeWidget(Decorations.java:309)
	at org.eclipse.swt.widgets.Decorations.WM_CLOSE(Decorations.java:1694)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4530)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1627)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2069)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4976)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2541)
	at org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:498)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4623)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1627)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2069)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4976)
	at org.eclipse.swt.internal.win32.OS.DefWindowProcW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DefWindowProc(OS.java:2541)
	at org.eclipse.swt.widgets.Shell.callWindowProc(Shell.java:498)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4623)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1627)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2069)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4976)
	at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
	at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2546)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3756)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1029)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:923)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
	at org.eclipse.e4.ui.internal.workbench.swt.E4Application.start(E4Application.java:150)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
	at java.lang.reflect.Method.invoke(Unknown Source)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1414)



After debugging this issue for a while I came up with a workaround, which I want to get rid of for obvious reasons.
Since the issue is the hashCode()-method in SimplePropertyObservableList I had to override it by creating my own Properties:
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.core.databinding.property.list.IListProperty;
import org.eclipse.core.internal.databinding.property.list.SelfListProperty;
import org.eclipse.core.internal.databinding.property.list.SimplePropertyObservableList;

public class MyProperties extends Properties {
	public static IListProperty selfList(Object elementType) {
		return new SelfListProperty(elementType) {
			
			@Override
			public IObservableList observe(Object source) {
				return observe(Realm.getDefault(), source);
			}
			
			@Override
			public IObservableList observe(Realm realm, Object source) {
				return new SimplePropertyObservableList(realm, source, this) {
					public int hashCode() {
                                                // check if observable is disposed
						if (isDisposed()) {
							return -1;
						}
						return super.hashCode();
					}
				};
			}
		};
	}
}


Does anybody know if there is a better solution?
Thanks in advance!

[Updated on: Sun, 24 February 2013 20:51]

Report message to a moderator

Re: Databinding - AssertionFailedException on disposing TreeViewer: Getter called on disposed observ [message #1015837 is a reply to message #1013954] Sun, 03 March 2013 14:49 Go to previous messageGo to next message
Max Hohenegger is currently offline Max HoheneggerFriend
Messages: 9
Registered: April 2012
Junior Member

I have found that the same issue exists with EMFProperties.

Apparently calling refresh() [1] on TreeViewer is the cause of this problem.
Using refresh(Object)[2] instead will resolve this, but it is not always practical.

Is this a bug, or am I doing something wrong?

[1] org.eclipse.jface.viewers.StructuredViewer.refresh()
[2] org.eclipse.jface.viewers.ColumnViewer.refresh(Object)
Re: Databinding - AssertionFailedException on disposing TreeViewer: Getter called on disposed observ [message #1015853 is a reply to message #1015837] Sun, 03 March 2013 18:57 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas SchindlFriend
Messages: 6264
Registered: July 2009
Senior Member
Sounds like a bug.

Tom

Am 03.03.13 15:49, schrieb Max Hohenegger:
> I have found that the same issue exists with EMFProperties.
>
> Apparently calling refresh() [1] on TreeViewer is the cause of this
> problem.
> Using refresh(Object)[2] instead will resolve this, but it is not always
> practical.
>
> Is this a bug, or am I doing something wrong?
>
> [1] org.eclipse.jface.viewers.StructuredViewer.refresh()
> [2] org.eclipse.jface.viewers.ColumnViewer.refresh(Object)
Re: Databinding - AssertionFailedException on disposing TreeViewer: Getter called on disposed observ [message #1716010 is a reply to message #1015853] Mon, 30 November 2015 13:45 Go to previous message
Erdal Karaca is currently offline Erdal KaracaFriend
Messages: 822
Registered: July 2009
Senior Member
Just hit on this one again, though this time I analyzed the scenario...

It seems to be related to the pattern how observables are created using an IObservableFactory. The bug appears when an observable factory decides to return the provided parameter as-is if it is already an observable.

WritableList input = new WritableList();

new IObservableFactory() {
 IObservable createObservable(Object target) {
  return target == input ? (IObservable) target : null;
 }
}


Now, when the content provder is disposed, it will first remove the elements/nodes and then its children.

org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider.TreeNode.dispose()
		private void dispose() {
			if (element != null) {
				elementNodes.remove(element);
			}
			if (children != null && !children.isDisposed()) {
				for (Iterator iterator = children.iterator(); iterator
						.hasNext();) {
					TreeNode child = getExistingNode(iterator.next());
					if (child != null)
						child.removeParent(element);
				}
				if (listener != null)
					removeCollectionChangeListener(children, listener);
				children.dispose();
				children = null;
			}
			element = null;
			parent = null;
			if (parentSet != null) {
				parentSet.clear();
				parentSet = null;
			}
		}


As the observable factory returned the element/target as-is, it became both a node and its direct children which ends in the node being disposed twice and hence the exception/assertion error:

org.eclipse.jface.internal.databinding.viewers.ObservableCollectionTreeContentProvider.TreeNode.initChildren()
		private void initChildren() {
			if (children == null) {
				children = (IObservableCollection) collectionFactory
						.createObservable(element);
				if (children == null) {
					listener = null;
					children = Observables.emptyObservableSet(realm);
				} else {
					Assert
							.isTrue(Util.equals(realm, children.getRealm()),
									"Children observable collection must be on the Display realm"); //$NON-NLS-1$
					listener = createCollectionChangeListener(element);
					addCollectionChangeListener(children, listener);
				}
			}
		}


To make it short: Separate model creation from databinding wrapping/creation or databinding helper classes (e.g. WritableList):

List<ModelType> input = new ArrayList<>();

new IObservableFactory() {
 IObservable createObservable(Object target) {
  return target == input ? new WritableList((List<>) target) : null;
 }
}


Or just prevent an element to be both a node and its children.

Thomas Schindl wrote on Sun, 03 March 2013 19:57
Sounds like a bug.

Tom

Am 03.03.13 15:49, schrieb Max Hohenegger:
> I have found that the same issue exists with EMFProperties.
>
> Apparently calling refresh() [1] on TreeViewer is the cause of this
> problem.
> Using refresh(Object)[2] instead will resolve this, but it is not always
> practical.
>
> Is this a bug, or am I doing something wrong?
>
> [1] org.eclipse.jface.viewers.StructuredViewer.refresh()
> [2] org.eclipse.jface.viewers.ColumnViewer.refresh(Object)
Previous Topic:ComboViewer color change issue
Next Topic:ContentProposalAdapter popup to show on top of textbox
Goto Forum:
  


Current Time: Sat Dec 10 13:13:25 GMT 2016

Powered by FUDForum. Page generated in 0.01910 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software