Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » JFace » Realm object problem while trying to create WritableList from two threads
Realm object problem while trying to create WritableList from two threads [message #510101] Tue, 26 January 2010 14:39 Go to next message
Eclipse UserFriend
Originally posted by: fxulusoy.yahoo.com

I am using table view to show some model elements and I am using EMF
databinding. This is my input setting method for table view. (My
application is a RAP application.)

private void setInput() {
List<? extends UnicaseModelElement> taskItems = null;

if (getCurrProject() != null) {
taskItems = getCurrProject().getAllModelElementsbyClass(
TaskPackage.eINSTANCE.getCheckable(),
new BasicEList<UnicaseModelElement>());
}

WritableList emfList = new WritableList(Realm.getDefault(),
taskItems, UnicaseModelElement.class);

tableViewer.setInput(emfList);
tableViewer.refresh();
}

Data that I show in the view is actually stored in the server and I have
local copy. I have extra thread which is polling the server to get
updates. When the updater thread gets changes from server, it calls a
listener methods to apply changes on the view. Like that:

public void notify(Notification notification, Project project,
ModelElement modelElement) {
setInput();
}

By the way, I am new in EMF and EMF-databinding. From my point of
understanding, accesing from different threads causes problem because
observables can only be accessed from one realm. My updater has no
relation with IObservable so it doesn't have realm.

After some tries I always get these exceptions:
org.eclipse.core.runtime.AssertionFailedException: assertion failed:
This operation must be run within the observable's realm

or

....Realm can't be null...


How can I handle this problem?


Thanks.
Re: Realm object problem while trying to create WritableList from two threads [message #510281 is a reply to message #510101] Wed, 27 January 2010 00:28 Go to previous messageGo to next message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
Use Realm.asyncExec(Runnable):

writableList.getRealm().asyncExec(new Runnable() {
public void run() {
// apply list changes here
}
});

If you're getting the error "Realm can't be null" it's because there is
no default realm set on the thread you're creating the WritableList
from--you can either embed your main block in a
Realm.runWithDefault(Realm, Runnable) and create the WritableList inside
the runnable, or you can just explicitly pass the realm to the WritableList.

Hope this helps,

Matthew

Fatih Ulusoy wrote:
> I am using table view to show some model elements and I am using EMF
> databinding. This is my input setting method for table view. (My
> application is a RAP application.)
>
> private void setInput() {
> List<? extends UnicaseModelElement> taskItems = null;
>
> if (getCurrProject() != null) {
> taskItems = getCurrProject().getAllModelElementsbyClass(
> TaskPackage.eINSTANCE.getCheckable(),
> new BasicEList<UnicaseModelElement>());
> }
>
> WritableList emfList = new
> WritableList(Realm.getDefault(), taskItems,
> UnicaseModelElement.class);
>
> tableViewer.setInput(emfList);
> tableViewer.refresh();
> }
>
> Data that I show in the view is actually stored in the server and I have
> local copy. I have extra thread which is polling the server to get
> updates. When the updater thread gets changes from server, it calls a
> listener methods to apply changes on the view. Like that:
>
> public void notify(Notification notification, Project project,
> ModelElement modelElement) {
> setInput();
> }
>
> By the way, I am new in EMF and EMF-databinding. From my point of
> understanding, accesing from different threads causes problem because
> observables can only be accessed from one realm. My updater has no
> relation with IObservable so it doesn't have realm.
>
> After some tries I always get these exceptions:
> org.eclipse.core.runtime.AssertionFailedException: assertion failed:
> This operation must be run within the observable's realm
>
> or
>
> ...Realm can't be null...
>
>
> How can I handle this problem?
>
>
> Thanks.
Re: Realm object problem while trying to create WritableList from two threads [message #510332 is a reply to message #510281] Wed, 27 January 2010 10:00 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: fxulusoy.yahoo.com

Hi Matthew,

I had tried that before. It didn't help. I tried it again after your
e-mail. It works partially. I don't get exceptions related with realm
but I get swt exception when I was refreshing the table.

Here is my changed code:

final WritableList list = (WritableList) (tableViewer.getInput());
if (list != null) {
list.getRealm().asyncExec(new Runnable() {
public void run() {
list.retainAll(new
BasicEList<UnicaseModelElement>());
list.addAll(taskItems);
}
});
} else {
WritableList emfList = new WritableList(Realm.getDefault(),
taskItems, UnicaseModelElement.class);
tableViewer.setInput(emfList);
}

tableViewer.refresh();


When I remove the refreshing into run method, this time the view is not
refreshed. But, the input was set correctly. If I make any user
interaction on the view like clicking somewhere on the view. Then, I can
see the changes on the view.

This is the exception that I get.

org.eclipse.swt.SWTException: Invalid thread access
at org.eclipse.swt.SWT.error(SWT.java:2687)
at org.eclipse.swt.SWT.error(SWT.java:2607)
at org.eclipse.swt.SWT.error(SWT.java:2578)
at org.eclipse.swt.widgets.Widget.error(Widget.java:892)
at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:825)
at org.eclipse.swt.widgets.Table.deselectAll(Table.java:1487)
at
org.eclipse.jface.viewers.TableViewer.doDeselectAll(TableVie wer.java:270)
at
org.eclipse.jface.viewers.AbstractTableViewer.setSelectionTo Widget(AbstractTableViewer.java:867)
at
org.eclipse.jface.viewers.StructuredViewer.setSelectionToWid get(StructuredViewer.java:1685)
at
org.eclipse.jface.viewers.StructuredViewer.preservingSelecti on(StructuredViewer.java:1375)
at
org.eclipse.jface.viewers.StructuredViewer.preservingSelecti on(StructuredViewer.java:1331)
at
org.eclipse.jface.viewers.StructuredViewer.refresh(Structure dViewer.java:1431)
at org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer. java:539)
at
org.eclipse.jface.viewers.StructuredViewer.refresh(Structure dViewer.java:1390)
at org.unicase.ui.web.tabs.TaskItemsTab.setInput(TaskItemsTab.j ava:156)
at org.unicase.ui.web.tabs.TaskItemsTab.updateInput(TaskItemsTa b.java:440)
at org.unicase.ui.web.tabs.TaskItemsTab.notify(TaskItemsTab.jav a:421)
at org.unicase.metamodel.impl.ProjectImpl$2.run(ProjectImpl.jav a:411)
at
org.unicase.metamodel.impl.ProjectImpl.notifyProjectChangeOb servers(ProjectImpl.java:353)
at
org.unicase.metamodel.impl.ProjectImpl.handleEMFNotification (ProjectImpl.java:414)
at
org.unicase.metamodel.util.ProjectChangeNotifier.fireNotific ation(ProjectChangeNotifier.java:121)
at
org.unicase.metamodel.util.ProjectChangeNotifier.notifyChang ed(ProjectChangeNotifier.java:90)
at
org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify (BasicNotifierImpl.java:280)
at
org.eclipse.emf.common.notify.impl.NotificationImpl.dispatch (NotificationImpl.java:1033)
at
org.eclipse.emf.common.notify.impl.NotificationImpl.dispatch (NotificationImpl.java:1038)
at
org.eclipse.emf.common.notify.impl.NotifyingListImpl.addAllU nique(NotifyingListImpl.java:468)
at
org.eclipse.emf.common.notify.impl.NotifyingListImpl.addAllU nique(NotifyingListImpl.java:406)
at org.eclipse.emf.common.util.AbstractEList.addAll(AbstractELi st.java:374)
at
org.unicase.emfstore.esmodel.versioning.operations.impl.Mult iReferenceOperationImpl.apply(MultiReferenceOperationImpl.ja va:334)
at
org.unicase.workspace.impl.ProjectSpaceImpl.applyOperations( ProjectSpaceImpl.java:2324)
at
org.unicase.workspace.impl.ProjectSpaceImpl.update(ProjectSp aceImpl.java:1350)
at
org.unicase.web.updater.UpdateProjectHandler$2.doExecute(Upd ateProjectHandler.java:162)
at
org.eclipse.emf.transaction.RecordingCommand.execute(Recordi ngCommand.java:135)
at
org.eclipse.emf.common.command.BasicCommandStack.execute(Bas icCommandStack.java:84)
at
org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.basicExecute(AbstractTransactionalCommandStack.java:2 41)
at
org.eclipse.emf.transaction.impl.TransactionalCommandStackIm pl.doExecute(TransactionalCommandStackImpl.java:63)
at
org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.execute(AbstractTransactionalCommandStack.java:165)
at
org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.execute(AbstractTransactionalCommandStack.java:219)
at
org.unicase.web.updater.UpdateProjectHandler.update(UpdatePr ojectHandler.java:156)
at
org.unicase.web.updater.UpdateProjectHandler.run(UpdateProje ctHandler.java:112)
at java.lang.Thread.run(Unknown Source)


Matthew Hall wrote:
> Use Realm.asyncExec(Runnable):
>
> writableList.getRealm().asyncExec(new Runnable() {
> public void run() {
> // apply list changes here
> }
> });
>
> If you're getting the error "Realm can't be null" it's because there is
> no default realm set on the thread you're creating the WritableList
> from--you can either embed your main block in a
> Realm.runWithDefault(Realm, Runnable) and create the WritableList inside
> the runnable, or you can just explicitly pass the realm to the
> WritableList.
>
> Hope this helps,
>
> Matthew
>
> Fatih Ulusoy wrote:
>> I am using table view to show some model elements and I am using EMF
>> databinding. This is my input setting method for table view. (My
>> application is a RAP application.)
>>
>> private void setInput() { List<? extends
>> UnicaseModelElement> taskItems = null;
>>
>> if (getCurrProject() != null) {
>> taskItems = getCurrProject().getAllModelElementsbyClass(
>> TaskPackage.eINSTANCE.getCheckable(),
>> new BasicEList<UnicaseModelElement>());
>> }
>> WritableList emfList = new
>> WritableList(Realm.getDefault(), taskItems,
>> UnicaseModelElement.class);
>>
>> tableViewer.setInput(emfList);
>> tableViewer.refresh();
>> }
>>
>> Data that I show in the view is actually stored in the server and I
>> have local copy. I have extra thread which is polling the server to
>> get updates. When the updater thread gets changes from server, it
>> calls a listener methods to apply changes on the view. Like that:
>>
>> public void notify(Notification notification, Project project,
>> ModelElement modelElement) {
>> setInput();
>> }
>>
>> By the way, I am new in EMF and EMF-databinding. From my point of
>> understanding, accesing from different threads causes problem because
>> observables can only be accessed from one realm. My updater has no
>> relation with IObservable so it doesn't have realm.
>>
>> After some tries I always get these exceptions:
>> org.eclipse.core.runtime.AssertionFailedException: assertion failed:
>> This operation must be run within the observable's realm
>>
>> or
>>
>> ...Realm can't be null...
>>
>>
>> How can I handle this problem?
>>
>>
>> Thanks.
Re: Realm object problem while trying to create WritableList from two threads [message #510599 is a reply to message #510332] Wed, 27 January 2010 22:34 Go to previous messageGo to next message
Eclipse UserFriend
Originally posted by: fxulusoy.yahoo.com

Hi Matthew,

I have solved the problem. The solution is here:
http://wiki.eclipse.org/index.php/5._Display.#Multithreaded_ Programming

Thank you very much Matthew.

Best Regards.


Fatih Ulusoy wrote:
> Hi Matthew,
>
> I had tried that before. It didn't help. I tried it again after your
> e-mail. It works partially. I don't get exceptions related with realm
> but I get swt exception when I was refreshing the table.
>
> Here is my changed code:
>
> final WritableList list = (WritableList) (tableViewer.getInput());
> if (list != null) {
> list.getRealm().asyncExec(new Runnable() {
> public void run() {
> list.retainAll(new
> BasicEList<UnicaseModelElement>());
> list.addAll(taskItems);
> }
> });
> } else {
> WritableList emfList = new
> WritableList(Realm.getDefault(),
> taskItems, UnicaseModelElement.class);
> tableViewer.setInput(emfList);
> }
>
> tableViewer.refresh();
>
>
> When I remove the refreshing into run method, this time the view is not
> refreshed. But, the input was set correctly. If I make any user
> interaction on the view like clicking somewhere on the view. Then, I can
> see the changes on the view.
>
> This is the exception that I get.
>
> org.eclipse.swt.SWTException: Invalid thread access
> at org.eclipse.swt.SWT.error(SWT.java:2687)
> at org.eclipse.swt.SWT.error(SWT.java:2607)
> at org.eclipse.swt.SWT.error(SWT.java:2578)
> at org.eclipse.swt.widgets.Widget.error(Widget.java:892)
> at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:825)
> at org.eclipse.swt.widgets.Table.deselectAll(Table.java:1487)
> at
> org.eclipse.jface.viewers.TableViewer.doDeselectAll(TableVie wer.java:270)
> at
> org.eclipse.jface.viewers.AbstractTableViewer.setSelectionTo Widget(AbstractTableViewer.java:867)
>
> at
> org.eclipse.jface.viewers.StructuredViewer.setSelectionToWid get(StructuredViewer.java:1685)
>
> at
> org.eclipse.jface.viewers.StructuredViewer.preservingSelecti on(StructuredViewer.java:1375)
>
> at
> org.eclipse.jface.viewers.StructuredViewer.preservingSelecti on(StructuredViewer.java:1331)
>
> at
> org.eclipse.jface.viewers.StructuredViewer.refresh(Structure dViewer.java:1431)
>
> at
> org.eclipse.jface.viewers.ColumnViewer.refresh(ColumnViewer. java:539)
> at
> org.eclipse.jface.viewers.StructuredViewer.refresh(Structure dViewer.java:1390)
>
> at org.unicase.ui.web.tabs.TaskItemsTab.setInput(TaskItemsTab.j ava:156)
> at
> org.unicase.ui.web.tabs.TaskItemsTab.updateInput(TaskItemsTa b.java:440)
> at org.unicase.ui.web.tabs.TaskItemsTab.notify(TaskItemsTab.jav a:421)
> at org.unicase.metamodel.impl.ProjectImpl$2.run(ProjectImpl.jav a:411)
> at
> org.unicase.metamodel.impl.ProjectImpl.notifyProjectChangeOb servers(ProjectImpl.java:353)
>
> at
> org.unicase.metamodel.impl.ProjectImpl.handleEMFNotification (ProjectImpl.java:414)
>
> at
> org.unicase.metamodel.util.ProjectChangeNotifier.fireNotific ation(ProjectChangeNotifier.java:121)
>
> at
> org.unicase.metamodel.util.ProjectChangeNotifier.notifyChang ed(ProjectChangeNotifier.java:90)
>
> at
> org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify (BasicNotifierImpl.java:280)
>
> at
> org.eclipse.emf.common.notify.impl.NotificationImpl.dispatch (NotificationImpl.java:1033)
>
> at
> org.eclipse.emf.common.notify.impl.NotificationImpl.dispatch (NotificationImpl.java:1038)
>
> at
> org.eclipse.emf.common.notify.impl.NotifyingListImpl.addAllU nique(NotifyingListImpl.java:468)
>
> at
> org.eclipse.emf.common.notify.impl.NotifyingListImpl.addAllU nique(NotifyingListImpl.java:406)
>
> at
> org.eclipse.emf.common.util.AbstractEList.addAll(AbstractELi st.java:374)
> at
> org.unicase.emfstore.esmodel.versioning.operations.impl.Mult iReferenceOperationImpl.apply(MultiReferenceOperationImpl.ja va:334)
>
> at
> org.unicase.workspace.impl.ProjectSpaceImpl.applyOperations( ProjectSpaceImpl.java:2324)
>
> at
> org.unicase.workspace.impl.ProjectSpaceImpl.update(ProjectSp aceImpl.java:1350)
>
> at
> org.unicase.web.updater.UpdateProjectHandler$2.doExecute(Upd ateProjectHandler.java:162)
>
> at
> org.eclipse.emf.transaction.RecordingCommand.execute(Recordi ngCommand.java:135)
>
> at
> org.eclipse.emf.common.command.BasicCommandStack.execute(Bas icCommandStack.java:84)
>
> at
> org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.basicExecute(AbstractTransactionalCommandStack.java:2 41)
>
> at
> org.eclipse.emf.transaction.impl.TransactionalCommandStackIm pl.doExecute(TransactionalCommandStackImpl.java:63)
>
> at
> org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.execute(AbstractTransactionalCommandStack.java:165)
>
> at
> org.eclipse.emf.transaction.impl.AbstractTransactionalComman dStack.execute(AbstractTransactionalCommandStack.java:219)
>
> at
> org.unicase.web.updater.UpdateProjectHandler.update(UpdatePr ojectHandler.java:156)
>
> at
> org.unicase.web.updater.UpdateProjectHandler.run(UpdateProje ctHandler.java:112)
>
> at java.lang.Thread.run(Unknown Source)
>
>
> Matthew Hall wrote:
>> Use Realm.asyncExec(Runnable):
>>
>> writableList.getRealm().asyncExec(new Runnable() {
>> public void run() {
>> // apply list changes here
>> }
>> });
>>
>> If you're getting the error "Realm can't be null" it's because there
>> is no default realm set on the thread you're creating the WritableList
>> from--you can either embed your main block in a
>> Realm.runWithDefault(Realm, Runnable) and create the WritableList
>> inside the runnable, or you can just explicitly pass the realm to the
>> WritableList.
>>
>> Hope this helps,
>>
>> Matthew
>>
>> Fatih Ulusoy wrote:
>>> I am using table view to show some model elements and I am using EMF
>>> databinding. This is my input setting method for table view. (My
>>> application is a RAP application.)
>>>
>>> private void setInput() { List<? extends
>>> UnicaseModelElement> taskItems = null;
>>>
>>> if (getCurrProject() != null) {
>>> taskItems = getCurrProject().getAllModelElementsbyClass(
>>> TaskPackage.eINSTANCE.getCheckable(),
>>> new BasicEList<UnicaseModelElement>());
>>> }
>>> WritableList emfList = new
>>> WritableList(Realm.getDefault(), taskItems,
>>> UnicaseModelElement.class);
>>>
>>> tableViewer.setInput(emfList);
>>> tableViewer.refresh();
>>> }
>>>
>>> Data that I show in the view is actually stored in the server and I
>>> have local copy. I have extra thread which is polling the server to
>>> get updates. When the updater thread gets changes from server, it
>>> calls a listener methods to apply changes on the view. Like that:
>>>
>>> public void notify(Notification notification, Project project,
>>> ModelElement modelElement) {
>>> setInput();
>>> }
>>>
>>> By the way, I am new in EMF and EMF-databinding. From my point of
>>> understanding, accesing from different threads causes problem because
>>> observables can only be accessed from one realm. My updater has no
>>> relation with IObservable so it doesn't have realm.
>>>
>>> After some tries I always get these exceptions:
>>> org.eclipse.core.runtime.AssertionFailedException: assertion failed:
>>> This operation must be run within the observable's realm
>>>
>>> or
>>>
>>> ...Realm can't be null...
>>>
>>>
>>> How can I handle this problem?
>>>
>>>
>>> Thanks.
Re: Realm object problem while trying to create WritableList from two threads [message #510630 is a reply to message #510599] Thu, 28 January 2010 06:02 Go to previous message
Matthew Hall is currently offline Matthew HallFriend
Messages: 368
Registered: July 2009
Senior Member
Fatih Ulusoy wrote:
> I have solved the problem. The solution is here:
> http://wiki.eclipse.org/index.php/5._Display.#Multithreaded_ Programming

Part of the problem is that your viewer input observable needs to belong
to the display realm.

The idiomatic way to address multi-threading problems like this in data
binding is to create an observable list in the worker thread, and
another in the display thread, and then bind the two lists to eachother
to bridge between threads. This is exactly the problem that realms were
introduced to solve:

IObservableList workerList = new WritableList(workerRealm);
IObservableList displayList = new WritableList(displayRealm);
bindingContext.bindList(displayList, workerList);

Now you can make changes to workerList and the changes will be
automatically synchronized to the viewer on the display thread.

Matthew
Previous Topic:cut-n-paste from TreeViewer??? or something similar???
Next Topic:Why must press "Enter" for ComboBoxCellEditor?
Goto Forum:
  


Current Time: Thu Apr 25 01:01:58 GMT 2024

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

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

Back to the top