Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Eclipse Projects » Plugin Development Environment (PDE) » NotHandledException with dynamic menu in Juno(<dynamic> tag / CompoundContributionItem / IContributionItem)
icon8.gif  NotHandledException with dynamic menu in Juno [message #901877] Tue, 14 August 2012 17:14 Go to next message
Bastian Krol is currently offline Bastian Krol
Messages: 2
Registered: August 2012
Junior Member
Hi,

I'm the maintainer of the the StartExplorer plug-in. One of its features is broken in Juno. The feature uses the <dynamic> tag to add actions to context menus programatically at runtime. This feature works fine in all Eclipse 3.x versions (up to Indigo) but does not work in the current Juno release (Build id: 20120614-1722).

The commands are added to the menu, but when the user clicks one of them, Eclipse can not find the handler. It silently fails to execute the command and an exception is logged (see below).

The extension point in question in plugin.xml:
  <extension point="org.eclipse.ui.menus">
    <menuContribution
      locationURI="popup:org.eclipse.ui.popup.any?after=additions">
      <menu
        label="Dynamic Command Contributions"
        id="command.contributions.menu">
        <visibleWhen>
          <with variable="activeMenuSelection">
            <iterate>
              <adapt type="org.eclipse.core.resources.IResource" />
            </iterate>
          </with>
        </visibleWhen>
        <dynamic
          class="command.contributions.ContributedCommandMenuProvider"
          id="command.contributions.ContributedCommandMenuProvider">
        </dynamic>
      </menu>
    </menuContribution>
  </extension>


ContributedCommandMenuProvider is the class that creates the commands and handlers on the fly, it extends org.eclipse.ui.actions.CompoundContributionItem.

Here is an excerpt:

	@Override
	protected IContributionItem[] getContributionItems() {
		this.doCleanup();
		return new IContributionItem[] { this.createContributionItem() };
	}

	private IContributionItem createContributionItem() {
		this.command = this.createCommand();
		CommandContributionItemParameter commandContributionItemParameter = new CommandContributionItemParameter( //
				this.getServiceLocator(), // IServiceLocator serviceLocator,
				this.command.getId(), // String id,
				this.command.getId(), // String commandId,
				CommandContributionItem.STYLE_PUSH // int style)
		);
		commandContributionItemParameter.label = "Contributed Command";
		CommandContributionItem contributionItem = new CommandContributionItem(
				commandContributionItemParameter);
		return contributionItem;
	}

	private Command createCommand() {
		ICommandService commandService = this
				.getCommandService(getServiceLocator());
		String commandId = "command.contributions.commandId";
		Command command = commandService.getCommand(commandId);
		String commandName = "command.contributions.name";
		String commandDescription = "Contributed Command";
		command.define(commandName, commandDescription,
				this.getLazyInitCategory(commandService));
		IHandler handler = new CommandContributionHandler();
		command.setHandler(handler);
		return command;
	}


I also attached the source code of a reduced mini-plug-in to this post that can be used to reproduce the problem. It only adds one command to the menu with the mechanism shown above. The code shown above is also from the reduced example.

When I debug this, I can make the following observations by setting a breakpoint in LegacyHandlerService, line 492 (final Object rc = hs.executeHandler(command, staticContext)): The org.eclipse.core.commands.ParameterizedCommand command has an instance variable of type org.eclipse.core.commands.Command (also named command) which in turn has an private transient IHandler handler. This handler refers to the handler I used when creating the command, so it is clearly there. However, the new Juno code does not use it but uses the method lookUpHandler(IEclipseContext context, String commandId) in HandlerServiceImpl which returns null.

I think this might be a bug in Juno, but before posting a Bugzilla ticket I wanted to ask here if anybody has any clue what goes wrong here. Maybe I just need to adapt my code to the Juno codebase? If so, any pointers in the right direction would be appreciated.

For the plug-in, if you are interested, see http : // basti1302.github.com/startexplorer/

Here is the exception in the log file:

!ENTRY org.eclipse.ui 4 4 2012-08-14 22:19:19.157
!MESSAGE Failed to execute item command.contributions.commandId
!STACK 0
org.eclipse.core.commands.NotHandledException: There is no handler to execute for command command.contributions.commandId
	at org.eclipse.ui.internal.handlers.LegacyHandlerService.executeCommand(LegacyHandlerService.java:494)
	at org.eclipse.ui.menus.CommandContributionItem.handleWidgetSelection(CommandContributionItem.java:824)
	at org.eclipse.ui.menus.CommandContributionItem.access$19(CommandContributionItem.java:810)
	at org.eclipse.ui.menus.CommandContributionItem$5.handleEvent(CommandContributionItem.java:800)
	at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
	at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053)
	at org.eclipse.swt.widgets.Display.runDeferredEvents(Display.java:4169)
	at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3758)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1022)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:916)
	at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
	at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:585)
	at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
	at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:540)
	at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
	at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
	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:353)
	at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
	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:601)
	at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
	at org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
	at org.eclipse.equinox.launcher.Main.run(Main.java:1438)
	at org.eclipse.equinox.launcher.Main.main(Main.java:1414)
icon14.gif  Re: NotHandledException with dynamic menu in Juno [message #902087 is a reply to message #901877] Wed, 15 August 2012 15:11 Go to previous message
Bastian Krol is currently offline Bastian Krol
Messages: 2
Registered: August 2012
Junior Member
I have found a solution now:

	private Command createCommand() {
		ICommandService commandService = this
				.getCommandService(getServiceLocator());
		String commandId = "command.contributions.commandId";
		Command command = commandService.getCommand(commandId);
		String commandName = "command.contributions.name";
		String commandDescription = "Contributed Command";
		command.define(commandName, commandDescription,
				this.getLazyInitCategory(commandService));
		IHandler handler = new CommandContributionHandler();
		IHandlerService handlerService = (IHandlerService) getHandlerService(getServiceLocator());

		// Works in Indigo but not in Juno:
		// command.setHandler(handler);

		// Works in Juno and in Indigo
		IHandlerActivation handlerActivation = getPluginContext().handlerActivation;
		if (handlerActivation != null) {
			handlerService.deactivateHandler(handlerActivation);
		}
		handlerActivation = handlerService.activateHandler(commandId, handler);
		getPluginContext().handlerActivation = handlerActivation;

		return command;
	}


(Remark: PluginContext is just a singleton attached to the Activator and it is a container which's purpose is to hold some state. The class which contains the createCommand method shown here can not hold state because a new instance is created every time the menu is to be generated.)

The important change is that I now use the IHandlerService to activate the handler instead of attaching the handler "manually" to the command by calling command.setHandler. I also removed the command.setHandler call, it is no longer neccessary. It is very possible that this always would have been the proper way to do this, but the setting the handler directly always worked up until Indigo.

I'm not sure if this is to be considered a bug in Juno, as far as I can see the claim is that through the compatibility layer everything that worked in 3.x should also work in 4.2.

Any opinions? Is it worth a bug ticket?
Previous Topic:How to make a type work for the run mode?
Next Topic:How to get tests visible to the launcher?
Goto Forum:
  


Current Time: Tue Jul 22 07:26:47 EDT 2014

Powered by FUDForum. Page generated in 0.01710 seconds