Sometimes when changing the root of one of the panels, I get a NullPointerException or IndexOutOfBoundsException.
The exception is thrown from the FileControlModel.update() method. It seems to be a concurrent access problem. The class FileControlModel has 3 attributes that are related to each other and are used as shared resources: contents, sortedDetails, actualContents. The class is not thread safe and chances are that somehow the
update() and getContent() step on each others foot.
There is a test in JCommanderUITest.fileControlModelUpdateException that sometimes reproduces the problem.
The stacktrace is:
org.eclipse.swt.SWTException: Failed to execute runnable (java.lang.NullPointerException)
at org.eclipse.swt.SWT.error(SWT.java:3884)
at org.eclipse.swt.SWT.error(SWT.java:3799)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:137)
at org.eclipse.swt.widgets.Display.runAsyncMessages(Display.java:3855)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3476)
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2405)
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2369)
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2221)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:500)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:493)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.jcommander.ui.app.PlatformRunnable$JCMDApplicationEntryPoint.startup(PlatformRunnable.java:114)
at org.jcommander.ui.app.singleton.SingletonAppLauncher.startingFirstInstance(SingletonAppLauncher.java:76)
at org.jcommander.ui.app.PlatformRunnable.start(PlatformRunnable.java:51)
at org.eclipse.swtbot.eclipse.core.UITestApplication.start(UITestApplication.java:56)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:194)
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:368)
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:559)
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:514)
at org.eclipse.equinox.launcher.Main.run(Main.java:1311)
at org.eclipse.equinox.launcher.Main.main(Main.java:1287)
Caused by: java.lang.NullPointerException
at org.jcommander.ui.filepanel.comparators.TableComparator.compare(TableComparator.java:36)
at org.jcommander.ui.filepanel.controls.FileTableControl.getSorted(FileTableControl.java:406)
at org.jcommander.ui.filepanel.model.FileControlModel.update(FileControlModel.java:609)
at org.jcommander.ui.filepanel.controls.FileTableControl$9.run(FileTableControl.java:616)
at org.eclipse.ui.internal.UILockListener.doPendingWork(UILockListener.java:155)
at org.eclipse.ui.internal.UISynchronizer$3.run(UISynchronizer.java:158)
at org.eclipse.swt.widgets.RunnableLock.run(RunnableLock.java:35)
at org.eclipse.swt.widgets.Synchronizer.runAsyncMessages(Synchronizer.java:134)
... 26 more
I have renamed method getContent( ) to readContentFromFS() because the name was misleading.
The FileControlModel class is not thread safe. I have checked the call hierarchy for its methods and I have concluded that all methods, except readContentFromFS(), are called from within the UI thread so it should be no problem with them. The only problem was the interaction between readContentFromFS() and update() methods. I have changed the code in update() not to rely on the fact that actualContents stays unchanged until the end of the method execution. This should fix the bug.
Robert, can you please have a look and confirm that my assumption regarding the call hierarchy is correct?