0

I have a PropertyTester that is called via a visibleWhen on the main toolbar, and on application start throws the following exception:

java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
at java.util.ArrayList$Itr.next(ArrayList.java:851)
at org.eclipse.e4.ui.workbench.renderers.swt.ToolBarContributionRecord.updateVisibility(ToolBarContributionRecord.java:70)
at org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer$5.changed(ToolBarManagerRenderer.java:479)
at org.eclipse.e4.core.internal.contexts.TrackableComputationExt.update(TrackableComputationExt.java:114)
at org.eclipse.e4.core.internal.contexts.EclipseContext.runAndTrack(EclipseContext.java:324)
at org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer.processAddition(ToolBarManagerRenderer.java:471)
at org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer.generateContributions(ToolBarManagerRenderer.java:447)
at org.eclipse.e4.ui.workbench.renderers.swt.ToolBarManagerRenderer.processContribution(ToolBarManagerRenderer.java:413)

I really think E4 should be able to cope with a tool item "suddenly" disappearing. Moreover since the property tester in question ALWAYS returns false, the tool item was not even visible to begin with.

I can trace the exception to the following line (bear in mind that the property tester that causes the exception is not even present in the stack trace):

PlatformUI.getWorkbench().getActiveWorkbenchWindow()

If I add the line in the test(...) method of the PropertyTester the exception occurs. If I remove it it does not. So a minimal example to show the bug is:

public final class MyPropertyTester extends PropertyTester {

    @Override
    public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
        PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        return false;
    }
}

I'm absolutely stumped why this exception occurs and how I could possible prevent it from happening. getActiveWorkbenchWindow() never returns null or throws an exception. IWorkbench#isStarting does not return true either, even though my guess would be that there is still some kind of initialization running when the error occurs.

(Note: other than being really ugly, the exception does not affect how the application works.)

How can I prevent this exception?

Stefan S.
  • 3,950
  • 5
  • 25
  • 77
  • Will be `ConcurrentModificationException` also thrown if `PlatformUI.getWorkbench().getActiveWorkbenchWindow();` is wrapped with [`syncExec()` or `asyncExec()`](http://www.vogella.com/tutorials/EclipseJobs/article.html#using-syncexec-and-asyncexec)? – howlger Nov 23 '17 at 08:56
  • @howlger With `syncExec()` it gets still thrown. With `asyncExec()` everything works because the code gets executed only after the workbench was initialized, but that's not really helpful for a `PropertyTester`. – Stefan S. Nov 23 '17 at 09:05
  • Code that is intended to be executed in the UI thread does not make sense in a `PropertyTester`. Do not mix model and UI. – howlger Nov 23 '17 at 09:23
  • @howlger But how do I enable commands base on the UI state? In this example I want to enable a tool item based on the field of an `IEditorInput`. – Stefan S. Nov 23 '17 at 09:29
  • Why not just using `org.eclipse.ui.ide.editorInputTester` for that (see [code](http://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/bundles/org.eclipse.ui.ide/src/org/eclipse/ui/internal/ide/handlers/EditorInputPropertyTester.java) - [extension](http://git.eclipse.org/c/platform/eclipse.platform.ui.git/tree/bundles/org.eclipse.ui.ide/plugin.xml#n2431))? – howlger Nov 23 '17 at 09:49
  • @howlger We have our own application based on Eclipse RCP, so we don't (and can't) use the IDE plug-ins. – Stefan S. Nov 23 '17 at 09:54
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/159659/discussion-between-howlger-and-steffi-s). – howlger Nov 23 '17 at 09:59

1 Answers1

0

Add as the first line in the PropertyTester's test method something like

if (!(receiver instanceof IEditorPart)) return false;

to avoid that code is executed that is doomed to fail and use receiver to compute the return value.

See:

howlger
  • 31,050
  • 11
  • 59
  • 99
  • I copied both the `EditorInputPropertyTester` and its registration (from the _plugin.xml_) then hooked it to my command. The property tester is not called. Maybe it's one of the features that got lost during the E4 debacle? – Stefan S. Nov 23 '17 at 10:46
  • Maybe Eclipse 4.x has been released to early caused by to too few developers for both, 3.x and 4.x. It's not the fault of e4 that the property tester is not called, but of your RCP application. – howlger Nov 23 '17 at 10:58
  • Fair enough. How do you call the property testers manually? Calling the `IEvaluationService` like in E3 does not work. (See [here](https://stackoverflow.com/questions/44039603/trigger-evaluation-of-propertytester) and [there](https://stackoverflow.com/questions/43656265/how-i-can-force-evaluation-of-property-tester-manually-in-eclipse-4)) – Stefan S. Nov 23 '17 at 11:01
  • Via the [Eclipse 4 event system](http://www.vogella.com/tutorials/Eclipse4EventSystem/article.html) and dependency injection. Two cool things worth the time to learn. ;) – howlger Nov 23 '17 at 11:26
  • Even when I call `IEventBroker#post` the `test` method is still not called (it is when `java.lang.Object` is used as type, though; but then it's called regardless and the exception of the question is thrown). – Stefan S. Nov 23 '17 at 11:53
  • If in the UI thread, use `IEventBroker#post` (asynchronously) instead of `IEventBroker#send` (synchronously) to avoid a deadlock in the UI thread (in SWT there is only one UI thread). – howlger Nov 23 '17 at 12:03
  • Eclipse itself uses the event broker to trigger property test for visibility of UI elements. It sounds you broke somewhere the decoupling concept: `IEventBroker#post` with `UIEvents.REQUEST_ENABLEMENT_UPDATE_TOPIC` triggers a reevaluation of visibility conditions containing property tester. Your question was how to avoid that your `PropertyTester` that contains the line `PlatformUI.getWorkbench().getActiveWorkbenchWindow();` causes an exception. – howlger Nov 23 '17 at 12:59
  • The solution is to compute the result value of the `PropertyTester` based on the `receiver` parameter only (a `PropertyTester` should not contain something like `PlatformUI.getWorkbench()`). Otherwise, using `PropertyTester` does not make sense and you can set the visibility directly programmatically. In the Eclipse platform, you can find many working examples of classes that extends `PropertyTester`. – howlger Nov 23 '17 at 12:59