Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
Bug 355210 - EHandlerService's canExecute(*) should not propagate exceptions upwards if an error occurs during enablement evaluation
Summary: EHandlerService's canExecute(*) should not propagate exceptions upwards if an...
Status: VERIFIED FIXED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: UI (show other bugs)
Version: 4.1   Edit
Hardware: All All
: P3 normal (vote)
Target Milestone: 4.2 M2   Edit
Assignee: Remy Suen CLA
QA Contact: Paul Webster CLA
URL:
Whiteboard:
Keywords:
Depends on:
Blocks: 354967
  Show dependency tree
 
Reported: 2011-08-19 08:28 EDT by Remy Suen CLA
Modified: 2011-09-13 08:35 EDT (History)
1 user (show)

See Also:


Attachments
EHandlerService patch v1 (2.37 KB, patch)
2011-08-24 09:39 EDT, Remy Suen CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Remy Suen CLA 2011-08-19 08:28:51 EDT
In 3.x, we have code like this in the Command class:

try {
  return handler.isEnabled();
} catch (Exception e) {
  if (DEBUG_HANDLERS) {
    // since this has the ability to generate megs of logs, only
    // provide information if tracing
    Tracing.printTrace("HANDLERS", "Handler " + handler  + " for "  //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
        + id + " threw unexpected exception"); //$NON-NLS-1$ 
    e.printStackTrace(System.out);
  }
}

In 4.x, we don't have this protection in HandlerServiceImpl. If the handler's @CanExecute method has problems, an InjectionException ends up being thrown up to the caller of canExecute(*). We should instead return 'false' and then a) log the error or b) only log the error if we have tracing on (like in 3.x above). The absence of this exception protection causes problems when we're trying to evaluate the enablement and visibility of multiple contribution items as one exception will completely shutdown the evaluation of the other contribution items. What do you think, Paul?

org.eclipse.e4.core.di.InjectionException: java.lang.NullPointerException
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:63)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invokeUsingClass(InjectorImpl.java:228)
	at org.eclipse.e4.core.internal.di.InjectorImpl.invoke(InjectorImpl.java:209)
	at org.eclipse.e4.core.contexts.ContextInjectionFactory.invoke(ContextInjectionFactory.java:123)
	at org.eclipse.e4.core.commands.internal.HandlerServiceImpl.canExecute(HandlerServiceImpl.java:102)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.updateElementVisibility(MenuManagerRendererFilter.java:344)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.showMenu(MenuManagerRendererFilter.java:271)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.handleShow(MenuManagerRendererFilter.java:225)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.safeHandleEvent(MenuManagerRendererFilter.java:207)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.access$1(MenuManagerRendererFilter.java:143)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter$SafeWrapper.run(MenuManagerRendererFilter.java:130)
	at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42)
	at org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRendererFilter.handleEvent(MenuManagerRendererFilter.java:140)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1262)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1052)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1058)
	at org.eclipse.swt.widgets.Control.WM_INITMENUPOPUP(Control.java:4881)
	at org.eclipse.swt.widgets.Control.windowProc(Control.java:4557)
	at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341)
	at org.eclipse.swt.widgets.Decorations.windowProc(Decorations.java:1610)
	at org.eclipse.swt.widgets.Shell.windowProc(Shell.java:2069)
	at org.eclipse.swt.widgets.Display.windowProc(Display.java:4972)
	at org.eclipse.swt.internal.win32.OS.TrackPopupMenu(Native Method)
	at org.eclipse.swt.widgets.Menu._setVisible(Menu.java:256)
	at org.eclipse.swt.widgets.Display.runPopups(Display.java:4206)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3748)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:969)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:885)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:90)
	at org.eclipse.ui.internal.Workbench$3.run(Workbench.java:539)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:519)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:123)
	at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
	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:344)
	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:79)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:618)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:622)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:577)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1410)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1386)
Caused by: java.lang.NullPointerException
	at org.eclipse.emf.facet.widgets.nattable.internal.handlers.RemoveLineHandler.isEnabled(RemoveLineHandler.java:52)
	at org.eclipse.ui.internal.handlers.HandlerProxy.isEnabled(HandlerProxy.java:320)
	at org.eclipse.ui.internal.handlers.E4HandlerProxy.canExecute(E4HandlerProxy.java:53)
	at sun.reflect.GeneratedMethodAccessor16.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:618)
	at org.eclipse.e4.core.internal.di.MethodRequestor.execute(MethodRequestor.java:56)
	... 49 more
Comment 1 Paul Webster CLA 2011-08-19 12:19:19 EDT
(In reply to comment #0)
> In 4.x, we don't have this protection in HandlerServiceImpl. If the handler's
> @CanExecute method has problems, an InjectionException ends up being thrown up
> to the caller of canExecute(*). We should instead return 'false' and then a)
> log the error or b) only log the error if we have tracing on (like in 3.x
> above). 

I agree, we need to put that protection back there.  I think we also need to use a debug option to protect against the printing out, otherwise a single bad plugin could fill up logs (if a toolitem ends up calling a bogus @CanExecute)

PW
Comment 2 Remy Suen CLA 2011-08-19 14:07:58 EDT
(In reply to comment #1)
> I think we also need to
> use a debug option to protect against the printing out, otherwise a single bad
> plugin could fill up logs (if a toolitem ends up calling a bogus @CanExecute)

Excellent point.
Comment 3 Remy Suen CLA 2011-08-19 16:05:54 EDT
Wanted to use Logger for tracing purposes but looks like it seems all its trace calls end up being printed to the console.
Comment 4 Remy Suen CLA 2011-08-24 09:39:31 EDT
Created attachment 202084 [details]
EHandlerService patch v1
Comment 6 Remy Suen CLA 2011-09-13 08:35:41 EDT
Verified by source inspection on I20110912-0200.