| Summary: | InvalidThreadAccess when update model with entity open in Java editor | ||
|---|---|---|---|
| Product: | [WebTools] Dali JPA Tools | Reporter: | Tom Mutdosch <mutdosch> |
| Component: | General | Assignee: | Brian Vosburgh <brian.vosburgh> |
| Status: | RESOLVED FIXED | QA Contact: | |
| Severity: | normal | ||
| Priority: | P3 | CC: | cmjaun |
| Version: | 1.0 | ||
| Target Milestone: | --- | ||
| Hardware: | PC | ||
| OS: | Windows XP | ||
| Whiteboard: | |||
|
Description
Tom Mutdosch
Brian, can you take a look at this. Just a bit more background - we are using the IDataModel framework from our own wizard, and in our operation we are modifying the JPA model objects (such as adding INamedQuery's to the IEntity, etc). This operation runs in the background (not in the UI thread). We often run our operation when the Entity java file is not even open - maybe there's a way for the AnnotationEditFormatter to not call all of the UI listeners if not running in the UI thread. Here's another truncated stacktrace that shows the same scenario when we make a call to: (INamedQuery)query).setName( "foo"); org.eclipse.swt.SWTException: Invalid thread access at org.eclipse.swt.SWT.error(SWT.java:3547) at org.eclipse.swt.SWT.error(SWT.java:3465) at org.eclipse.swt.SWT.error(SWT.java:3436) at org.eclipse.swt.widgets.Widget.error(Widget.java:432) at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:326) at org.eclipse.swt.custom.StyledText.getLinePixel(StyledText.java:3649) at org.eclipse.swt.custom.StyledText.handleTextChanging(StyledText.java:5330) . . . at org.eclipse.jpt.core.internal.JpaEObject.eNotify(JpaEObject.java:73) at org.eclipse.jpt.core.internal.content.java.mappings.JavaAbstractQuery.setName(JavaAbstractQuery.java:244) . . . org.eclipse.wst.common.frameworks.internal.datamodel.DataModelPausibleOperationImpl$1.run(DataModelPausibleOperationImpl.java:376) at org.eclipse.core.internal.resources.Workspace.run(Workspace.java:1797) Hi there, Do you know how difficult this one will be to fix? Currently we have added a bunch of Display.syncExec blocks to wrap all of our various Dali model access in our code. This probably isn't the best solution especially since we are running as a non-UI operation, but I don't know a better way at the moment. I added API to IJpaProject that will allow clients to set a ThreadLocal CommandExecutor: IJpaProject#setThreadLocalModifySharedDocumentCommandExecutor(CommandExecutor commandExecutor). When updating a model in a non-UI thread you will need to set this CommandExecutor to one that will execute the command on the UI thread: project.setThreadLocalModifySharedDocumentCommandExecutor(SynchronousUiCommandExecutor.instance()). Then any model object in the project can be modified and, if its currently visible in an editor, it will notify its listeners on the UI thread. Hi Brian, This mechanism seems to work fine, thanks. After my code sets the Executor and updates the Dali model, afterwards is it my responsibility to again call setThreadLocalModifySharedDocumentCommandExecutor() and set it back to the original executor? Hi, Tom. Glad to hear this works for you. In response to Comment 5: No, you do not need to reset the executor. It is stored in a ThreadLocal, affects only the code running in the Thread that set it originally, and will be garbage-collected when the Thread is finished and garbage-collected. Very cool - thanks! |