This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 430401 - [WorkbenchParts] [Compatibility] Part-specific ISelectionService.addSelectionListener(String, ISelectionListener) no longer provides documented behavior
Summary: [WorkbenchParts] [Compatibility] Part-specific ISelectionService.addSelection...
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.3   Edit
Hardware: Macintosh Mac OS X
: P3 major (vote)
Target Milestone: 4.4 M7   Edit
Assignee: Wojciech Sudol CLA
QA Contact: Wojciech Sudol CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-03-14 11:13 EDT by Scott Barrett CLA
Modified: 2014-04-29 04:39 EDT (History)
3 users (show)

See Also:


Attachments
Auto selection view (20.47 KB, multipart/x-zip)
2014-04-03 16:12 EDT, Paul Webster CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Scott Barrett CLA 2014-03-14 11:13:30 EDT
The javadoc for ISelectionService.registerSelectionListener(String partId, ISelectionListener listener) and ISelectionService.registerPostSelectionListener(String partId, ISelectionListener listener) both state:

"Adds a part-specific selection listener which is notified when selection changes in the part with the given id. This is independent of part activation - the part need not be active for notification to be sent."

The notifications are no longer independent of part activation.  Notifications are not sent to the listener until the part registered against is activated.
Comment 1 Paul Webster CLA 2014-03-14 11:15:51 EDT
You mean for org.eclipse.ui.ISelectionService.addSelectionListener(ISelectionListener) ?

PW
Comment 2 Paul Webster CLA 2014-03-14 11:16:10 EDT
Could you also confirm the version?  4.3? 4.4?

PW
Comment 3 Scott Barrett CLA 2014-03-14 11:24:26 EDT
(In reply to Paul Webster from comment #2)
>You mean for org.eclipse.ui.ISelectionService.addSelectionListener(ISelectionListener) ?

Sorry, I don't know where that "registerSelectionListener" business came from!

The problem is with the two-arg org.eclipse.ui.ISelectionService.addSelectionListener(String, ISelectionListener) and the corresponding addPostSelectionListener.

> Could you also confirm the version?  4.3? 4.4?

Version 4.3.
Comment 4 Paul Webster CLA 2014-03-28 10:20:24 EDT
Scott, could you please provide an example of a view that fires selection changes when not active?  Would the Outline view work?

In general it's supposed to go through the org.eclipse.ui.internal.PageSelectionService which creates a org.eclipse.ui.internal.PagePartSelectionTracker.PagePartSelectionTracker(IWorkbenchPage, String).  That adds itself as a listener to the part site selection provider.

PW
Comment 5 Scott Barrett CLA 2014-03-28 20:12:25 EDT
Here'e my situation and what I'm experiencing:

I have a ThumbnailView class that extends ViewPart and implements ISelectionProvider.  It displays a set of buttons with image thumbnails.

I listen to the ThumbnailView for selection changes as follows:

PlatformUI.getWorkbench ()
          .getActiveWorkbenchWindow ()
          .getSelectionService ()
          .addSelectionListener (ThumbnailView.ID, this);

When a button in the ThumbnailView is clicked, it opens a different view to show the image, which causes a new view to be activated.  It then updates the selection of the ThumbnailView.  Since the new image view has been activated, the update to the selection of the ThumbnailView is not propagated to the registered selection listener until the ThumbnailView is re-activated.

While it could be argued that setting the selection before opening other views might solve the problem, the documentation for addSelectionListener indicates that the notifications should not be dependent on the activation state of the view being monitored.
Comment 6 Paul Webster CLA 2014-04-03 16:12:25 EDT
Created attachment 241586 [details]
Auto selection view

Wojtek, I can reproduce with this view.  Start a new eclipse, open the "Selection view" and select Parent 1.

It should alternate between Parent 1 and Parent 2 in the view, and print it out on the console.

If you make the Package Explorer active, it should continue to work, but while the view updates the selection notifications stop.

PW
Comment 8 Paul Webster CLA 2014-04-15 12:31:58 EDT
On shutdown I sometimes get an NPE.  Wojtek, could you please investigate?

!ENTRY org.eclipse.ui.workbench 4 2 2014-04-15 12:30:58.713
!MESSAGE Problems occurred when invoking code from plug-in: "org.eclipse.ui.workbench".
!STACK 0
java.lang.NullPointerException
	at org.eclipse.e4.ui.internal.workbench.SelectionServiceImpl.removeSelectionListener(SelectionServiceImpl.java:66)
	at org.eclipse.ui.internal.e4.compatibility.SelectionService.removeSelectionListener(SelectionService.java:354)
	at org.eclipse.ui.internal.WorkbenchPage.removeSelectionListener(WorkbenchPage.java:3209)
	at org.eclipse.cdt.debug.internal.ui.EvaluationContextManager.pageClosed(EvaluationContextManager.java:113)
	at org.eclipse.ui.internal.PageListenerList$2.run(PageListenerList.java:85)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.core.runtime.Platform.run(Platform.java:867)
	at org.eclipse.ui.internal.PageListenerList.fireEvent(PageListenerList.java:53)
	at org.eclipse.ui.internal.PageListenerList.firePageClosed(PageListenerList.java:82)
	at org.eclipse.ui.internal.WorkbenchWindow.firePageClosed(WorkbenchWindow.java:1307)
	at org.eclipse.ui.internal.WorkbenchWindow.busyClose(WorkbenchWindow.java:1496)
	at org.eclipse.ui.internal.WorkbenchWindow.access$15(WorkbenchWindow.java:1454)
	at org.eclipse.ui.internal.WorkbenchWindow$10.run(WorkbenchWindow.java:1519)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.ui.internal.WorkbenchWindow.close(WorkbenchWindow.java:1516)
	at org.eclipse.ui.internal.Workbench$14.run(Workbench.java:1154)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.ui.internal.Workbench.busyClose(Workbench.java:1136)
	at org.eclipse.ui.internal.Workbench.access$20(Workbench.java:1078)
	at org.eclipse.ui.internal.Workbench$19.run(Workbench.java:1393)
	at org.eclipse.swt.custom.BusyIndicator.showWhile(BusyIndicator.java:70)
	at org.eclipse.ui.internal.Workbench.close(Workbench.java:1390)
	at org.eclipse.ui.internal.Workbench.close(Workbench.java:1363)
	at org.eclipse.ui.internal.handlers.QuitHandler.execute(QuitHandler.java:37)
	at org.eclipse.ui.internal.handlers.HandlerProxy.execute(HandlerProxy.java:294)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.execute(E4HandlerProxy.java:90)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:55)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:247)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:229)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:132)
	at org.eclipse.e4.core.commands.internal.HandlerServiceHandler.execute(HandlerServiceHandler.java:149)
	at org.eclipse.core.commands.Command.executeWithChecks(Command.java:499)
	at org.eclipse.core.commands.ParameterizedCommand.executeWithChecks(ParameterizedCommand.java:508)
	at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.executeHandler(HandlerServiceImpl.java:210)
	at org.eclipse.ui.internal.handlers.LegacyHandlerService.executeCommand(LegacyHandlerService.java:335)
	at org.eclipse.ui.internal.actions.CommandAction.runWithEvent(CommandAction.java:159)
	at org.eclipse.jface.action.ActionContributionItem.handleWidgetSelection(ActionContributionItem.java:595)
	at org.eclipse.jface.action.ActionContributionItem.access$2(ActionContributionItem.java:511)
	at org.eclipse.jface.action.ActionContributionItem$5.handleEvent(ActionContributionItem.java:420)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.sendEvent(Display.java:4458)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1388)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:3806)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3416)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1152)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:1033)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:148)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:635)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:578)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:150)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:135)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:134)
	at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:104)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:379)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:233)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:606)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:648)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:603)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1465)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1438)
Comment 9 Wojciech Sudol CLA 2014-04-15 14:48:23 EDT
Unfortunately I haven't updated all fields in the class correctly. I apologize for that and will be careful next time.
Review URL: https://git.eclipse.org/r/25076
However, the NPE is thrown because the SelectionServiceImpl.getServiceAggregator() returns null, so I am not sure if the patch will fix this. I am not able reproduce the problem in my environment.
Comment 10 Paul Webster CLA 2014-04-15 15:55:19 EDT
(In reply to Wojciech Sudol from comment #9)
> However, the NPE is thrown because the
> SelectionServiceImpl.getServiceAggregator() returns null, so I am not sure
> if the patch will fix this. I am not able reproduce the problem in my
> environment.

	at org.eclipse.cdt.debug.internal.ui.EvaluationContextManager.pageClosed(EvaluationContextManager.java:113)

You have to have CDT installed, create a C++ project and debug it once so that the CDT Debug page is in the Debug view.

PW
Comment 12 Wojciech Sudol CLA 2014-04-15 18:46:03 EDT
In the compatibility SelectionService the ESelectionService generic listener is in practice never removed from the ESelectionService. In contrast, the targeted listener, which I added, is added and removed dynamically and can cause the NPE, because there is no verification in the SelectionServiceImpl whether getServiceAggregator() returns not null value. Moreover the SelectionService.setSelectionService(*) is not called when ESelectionService is removed from context (I am not sure if it is expected behaviour).
Comment 13 Wojciech Sudol CLA 2014-04-16 07:49:45 EDT
I pushed to the gerrit a minimal change that fixes this particular NPE problem.
Review URL: https://git.eclipse.org/r/25121
However there is still a risk of getting NPE in some places, e.g. SelectionService.getSelection().
Furthermore, the selection related classes are disposed in the following order:
1. SelectionAggregator
2. SelectionServiceImpl
3. SelectionService
That means that if e.g. SelectionServiceImpl.removeSelectionListener(*) is called after SelectionAggregator is disposed, an NPE will be thrown.
I assume that this scenario should not happen because of some assumptions regarding disposing order etc. Am I correct, or we need to add missing null checks?
Comment 15 Wojciech Sudol CLA 2014-04-29 04:39:56 EDT
Verified in I20140428-2000.