Tuesday, November 03, 2009

e4 and injectable command execution

I'm fond of most of the Command Framework in Eclipse 3.x (I have to maintain it after all :-) The notion of an abstract command (as opposed to the Command class) has 2 interesting responsibilities:
  1. Am I enabled?
  2. Do something.
In 3.x, commands delegate them to the command's currently active handler. Two aspects of the 3.x implementation aren't quite right in my opinion.

Responsibility #1 is implemented as state (isEnabled()) on the Command itself. Because a command is a global singleton (it's supposed to represent the operation) this has the unintended side effect that a command is enabled or disabled globally for the application. The active handler determines the state, but based on whatever information it wants (which may or may not be the same information it will execute against).

Responsibility #2 is implemented in the handler's execute method. It can then use the execution event to get the IEvaluationContext and extract information out of it. This mostly works well, and you end up treating the IEvaluationContext as a map.

In e4 we're looking IEclipseContext "Contexts: the service broker" which provides a localized view into the application state (i.e. what you can see from your view or editor makes sense). Information relevant to the state of the application is stored in your context in 2 forms. Some information is identified by class (ECommandService.class.getName(), EventAdmin.class.getName()) and some information is identified by name (selection, activePart).

Now the fun part. In e4 a handler for a command can define 2 methods:
  • canExecute(*) - This will be called by the framework before trying to execute a command
  • execute(*) - This will be called by the framework when appropriate (can you guess what it does? :-)
But in e4 you don't need to extract your variables from your context, you can ask for them directly:

public boolean canExecute(
@Named("selection") IStructuredSelection selection);
public void execute(
@Named("selection") IStructuredSelection selection,
Shell shell);

When the framework needs to call either method, it will inject the needed information from the appropriate IEclipseContext. It uses the @Named annotation if it is present, or the type of the parameter (for example, Shell.class.getName()) if @Named is not.

In e4 1.0 we're adopting the JSR 330 annotations for injection (plus a few extras that we need). This is still a work in progress, but it's moving right along. If you are interested, now is the time to get involved - http://wiki.eclipse.org/E4.

There's a lot more to this story, so stay tuned for the next update.

PW

Tuesday, October 06, 2009

Continuous integration of Platform UI tests

With the work I was doing for e4 builds I've had the opportunity to set up a PDE build and test environment. So I thought I would setup the Platform UI automated tests to run in a continuous build cycle on a machine in the lab.

I think it's interesting because:
  1. The tests need to run against the latest I build for that week
  2. I need to patch 2 features to install my plugins from HEAD. I just followed Andrew's instructions.
  3. I wanted to use p2 to configure the tests, not the Automated Test Framework
As there's no real packaging or reuse involved, I just set up 3 features to drive the build. My 2 patch features, which include all of the Platform UI plugins that need to be replaced in org.eclipse.rcp and org.eclipse.platform. And my test feature, which includes the 2 patch feature, all of the Platform UI test plugins that contain my automated tests, and the automated test framework plugins:
  • org.eclipse.core.tests.harness
  • org.eclipse.test.performance
  • org.eclipse.test
  • org.eclipse.ant.optional.junit
Setting up PDE build involves copying the headless build templates (build.properties, customTargets.xml) and setting the parameters to match your build environment. Then creating a map project that's pointing to the correct features/plugins, and away you go.

For continuous builds you tend to want to build from HEAD. The best way (especially if you have a real map that's is regularly tagged for something else) is to set to properties:

forceContextQualifier=v${buildId}
fetchTag=HEAD

That way you don't end up with a lot of plugins that look like com.example.plugin_HEAD :-)

I also want to generate a p2 repo so I can consume my build easily. That's the standard set of p2 properties at the bottom of the build.properties file.

Once that's up (and a few tweaks to the customTargets.xml to use the latest I-build I will provide) and then you can build with the org.eclipse.ant.core.antRunner application.

Now I want to use p2 to run my automated tests. First I had to use XSLT to fix the content.xml and relax the feature patch version ranges (feature patches will target a very specific feature qualifier combination). There's a potential p2 fix in the works, but simple XSL will do for now.

I'm running the automated tests in my postBuild, with modified code I swiped from the Eclipse SDK automated test framework. The difference is that instead of having to generate a test.properties with the correct test plugin to test plugin version mapping and trying to unzip the build plugins into the eclipse test instance, the setup to run the tests now involve:
  1. unzip the eclipse test instance
  2. Call the director to install the plugin under test, the support plugins, and the patch features
  3. call the plugin's test.xml
It manages all of the version numbers and dependencies for free, so your list of IUs looks like:

-installIUs ${testPlugin}, org.eclipse.test, org.eclipse.ant.optional.junit, org.eclipse.ui.test.platform.patch.feature.group, org.eclipse.ui.test.rcp.patch.feature.group

And now I have my headless automated test environment :-) The relevant build files and map files can all be found in CVS.

  • :pserver:anonymous@dev.eclipse.org:/cvsroot/eclipse
  • platform-incubator/ui/org.eclipse.ui.automated.build/org.eclipse.ui.releng
There are a lot of opportunities for improvement in this environment (continually updating the build target from http://download.eclipse.org/eclipse/updates/3.6-I-builds for example) but this is enough to get me started.

PW

Tuesday, August 18, 2009

Eclipse again

This last year has been very busy, working to finish Eclipse 3.5 and getting the Eclipse e4 Tech Preview into shape. Over the next few months, I hope to expound on some of the new techniques that can be used with Commands, Handlers, and Menu contributions as of 3.5

But really, I'll post something this time :-)

PW

Monday, October 30, 2006

Place command in menus in eclipse 3.2

In eclipse 3.2, there is good support for keybindings, commands, and handlers. There are some snippets available at Platform Command Framework.

But it's not obvious how to link your command+handler implementation to a menu or toolbar item. The <action/> elements have a definitionId attribute that can link the action to a command, but that allows the action's IActionDelegate to be linked to the keybinding (through the command). It turns the action's IActionDelegate into a handler for keybinding purposes through the use of an ActionHandler proxy class.

But what if you would prefer to implement your commands and handlers, and then just have the command called from your menus the same way it is through keybindings.

As it turns out, there is public API that will allow you to create a GenericCommandActionDelegate. I have an example available on the Platform Command Framework page.

The implementation takes advantage of the fact that the action element is created through IConfigurationElement#createExecutableExtension(*), which means that your action delegate can implement IExecutableExtension and receive extra configuration information from the plugin.xml.

It's not a perfect solution for 3.2 (there would need to be more work to support something like checked state or radio buttons), but it will allow you to focus on creating command and handlers, and then using the action based extensions to execute your commands.

The same strategy could be used for 3.1 as well, although some modifications would have to be made. In 3.1, you have to build your own ExecutionEvent and call the Command#execute*(*) method yourself.

PW

Thursday, June 22, 2006

What can the Command framework do for you?

In 3.2 much more of the eclipse action infrastructure has moved onto the command framework. It is based on 4 extension points.

org.eclipse.ui.commands and the ICommandService create the abstract user command (like COPY). org.eclipse.ui.handlers and the IHandlerService allow plugins and interested parts to provide an implementation for the COPY command.

org.eclipse.ui.bindings can map key sequences to commands, and IBindingService can programmatically review those keybindings. org.eclipse.ui.contexts and the IContextService can activate contexts, which can be used to scope the keybindings.

The IBindingService can be used to programmatically add new keybindings ... but not easily. There was some example code and discussion on the newsgroup:

Re: Action accelerators

In 3.2 there is still no replacement for placing the command in a menu or toolbar. <actions/> (which should always be linked to commands, BTW) are still used, and the work is done in 4 extension points. org.eclipse.ui.actionSets, org.eclipse.ui.editorActions, org.eclipse.ui.viewActions, and org.eclipse.ui.popupMenus.

Providing this replacement will be part of the command framework work for 3.3.

I'm still wondering if this information should be captured on a wiki for updating (until it can make it into the 3.3 documentation), or just left floating around the newsgroups ...

Later,
PW

Saturday, June 03, 2006

Eclipse, you say? Very interesting.

It's been just over a year since I joined the Eclipse team. I've been hearing about these blog postings that other Eclipse committers and Eclipse Foundation members maintain, and thought I would add my 2 cents into the pot.

But later, this first post was very tiring :-)

PW