Eclipse Search

Loading

Jan 28, 2009

Top 10 mistakes in Eclipse Plug-in Development

Having trained a lot of new comers to the Eclipse plug-in development, I've seen certain common mistakes repeated all the time. I've tried to compile a top 10 list of such common mistakes, so next time you hit them, you will know that you are not alone :-)

Update: Thanks to Hiroki Kondo(kompiro) a Japanese version of this entry is available here.

(10) Not reading the JavaDoc
This is nothing specific about Eclipse Plug-in development. Its more common among the Java programmers, or probably a common thing among all the programmers - not reading the documentation. How many of you know that there are classes that shouldn't be inherited or the interfaces that are not supposed to be implemented by you? Well API tooling will help you, but there are lot of other corner cases which you won't find unless you read the JavaDoc. I myself do this mistake all the time. Honestly for a long while I didn't know that a command's handler is supposed to return only null (which is the result of the execution)- When did you know this?
In case you didn't know, JDT provides you a JavaDoc view which shows up the Java doc with the formatting.
JavaDoc view
(9) Forgetting to add a default constructor
You had that nice wizard class which works fine when you create it yourself and put it in a WizardDialog. But you can't make it work with the INewWizard. After a "little" debugging you realize that you didn't have a default constructor for the Wizard class! Yes, its not just the Wizard class, but most of the other classes that you specify in your plugin.xml for that "class" attribute, should have a default constructor, as it will instantiated thru reflection.
(8) Not decomposing into different plugins
Another common thing among the newbies. They have a tendency to put everything into a single plug-in. Splitting your code base across different plug-in improves the modularity and maintainability. You should at least consider splitting the core and ui part, so that testing the core part becomes easy.
(7) Using "internal" code
I've seen this as an unavoidable thing in many cases. You see some functionality in the internal code that you would require, so make use of those internal classes. There are thousands of internal classes, but believe me, the one that used will be refactored and changed in the next release, so you will have a hard time upgrading to a newer release. It has happened to me more than once. Why *that* class of all the classes? sigh!
If you find any internal code generic and useful, raise a bug to make it a part of API. Instead of using the internal classes, you can copy the code into your code base and make use of it.
(6) Directly setting the classpath
Every plugin project is a Java Project, but that doesn't mean that you can simply update the Java classpath with the jar files that you require. Because your plug-in's classpath at runtime will be different. If you had to add a jar to the classpath, you should consider adding it thru the 'Add' button in Classpath section of the Runtime tab.
updating plugin classpath 
(5) Ignoring build.properties
Most common mistake among the newbies. Add an icon/resource under a new folder; test the plug-in, which works fine; export it and deploy it elsewhere; it stops working. Reason? The build.properties didn't have an entry for the folder/file that you added, so the exported plug-in doesn't have that resource. So, remember, whenever you add a folder/individual resource, make sure you update the build.properties file as well.
build.properties
(4) Empty dispose method
Remember the the golden rule, "When you create, you dispose". SWT resources like images and fonts should be always disposed of when you are done with them. I've seen many people not doing this at all. Another important issue is when you are overriding the dispose method, you should always call the super.dispose() to ensure the resources created by the super class are properly disposed. Also, if you have attached any listeners like IPartListener or IResourceChangeListener, during the life cycle of your class, you should consider removing those listeners in the dispose method.
(3) Not honoring monitor.isCanceled()
Your Job does a lengthy operation and the user might want to cancel it. It can be done by pressing cancel in the ProgressMonitor dialog or in the Wizard or thru the Progress View. What ever way he does, the IProgressMonitor supplied to you will have the cancel flag set to true. Its your responsibility to periodically check the isCancelled() and abort the operation. When the user presses 'Cancel' and if nothing happens, believe me, its a very bad user experience.
Cancelling a job
(2) Blindly contributing to everywhere
People tend to add their contribution virtually everywhere thinking their plug-in is the important one to the user. But hard fact is it will be annoying for the user. So:
  • Stop adding your view to every perspective that you know
  • Do not extend org.eclipse.ui.startup unless its really, really, necessary
  • Do not make your action set to be visible in all the perspectives
  • Try not to create a modal dialog
  • When you adding menu items thru objectContributions, try to add it to the specific class, rather than simply Object
(1) Executing a long running operation in Display thread
Do I need to tell about this? Not just newbies, even experienced ones tend to do this mistake. In my present job, I have to use an internal RCP application on a regular basis, does this mistake for almost all the operations. The end result is a non-responding UI and a very frustrated user :-(  Once I pointed out a piece of code and asked a developer why he was doing such a big calculation on a Display thread, he was very surprised. He said that he is neither doing a Display.asyncExec() nor a UIJob, so the code will not run in the display thread. Here is a thumb rule. The operation that you do inside the SWT listener methods will be run in the display thread. There are more than few people who don't realize this and think that only the that gets executed in Display.asyncExec or Display.syncExec are the ones that run in the UI thread. So don't do long calculations or contact a server across the network in those listeners. If you have to run such a lengthy operation, spawn off a separate job and return quickly, so the UI remains responsive.
What are the other mistakes that you frequently come across?

Jan 17, 2009

[Off Topic] Moving to Google's Feedburner

 

This blogs RSS feed is available through FeedBurner. Now that its acquired by Google, they are moving their services to Google platform. The good news for me in that is I've one less password to remember :-) Today I've migrated this blogs feed to the Google services and it went fine and hope works for everyone. I've not seen the stats in the recent while, but looks like the subscribers count is steadily increasing. From a humble 20, its now gone above 500 !

 

image

Google Analytics says that planeteclipse.org and eclipsezone.com are the top referrers. So few posts make their way into these sites, are the major source of my subscribers. The more interesting part comes about the way people subscribe to this blog.

image

Looks like Google Reader+iGoogle takes a lions share and the next is email subscribers. When I added the email subscription option, I thought at most 10 people would sign up thru that service. The count stands above 60!

I started this blog with the intention of delivering tips and tricks of Eclipse Plugin development that I've learnt, and will continue doing that. Meanwhile excuse me for the occasional, pointless posts like this one :-)

Jan 11, 2009

Commands Part 4: Misc items ...

How do I know about execution of a command?

You can use the IExecutionListener:

ICommandService service = (ICommandService) serviceLocator.getService(ICommandService.class);
service.addExecutionListener(new IExecutionListener() {

    public void notHandled(String commandId, NotHandledException exception) {
    }

    public void postExecuteFailure(String commandId, ExecutionException exception) {
    }

    public void postExecuteSuccess(String commandId, Object returnValue) {
    }

    public void preExecute(String commandId, ExecutionEvent event) {
    }
});

The IExecutionListener is merely an observer of the command execution so it can neither veto on it nor make any changes to the event.

How do I get the active Window/Shell in my handler code?

Use HandlerUtil. Its a handy class which gives you access to most common variables like active window, active shell, context ids, active part, current selection,  etc.

Shell shell = HandlerUtil.getActiveShell(event);
ISelection selection = HandlerUtil.getCurrentSelection(event);

All of the get* methods will have a get*Checked variants. The first ones will return you null if the variable is not available. The checked ones will throw you an exception if the variable is null. If you have your own variable, you can use the getVariable() method to get it.

Can I programmatically execute a Command?

Yes. But don't simple call command.execute(), use the IHandlerService to execute a command:

IHandlerService handlerService = (IHandlerService) serviceLocator.getService(IHandlerService.class);
handlerService.executeCommand(commandId, null);

Can I programmatically create and manipulate a Command?

Yes! You can use ICommandService to create a new command and then associate a handler thru IHandlerService:

ICommandService commandService = (ICommandService) serviceLocator.getService(ICommandService.class);
Command command = commandService.getCommand("my.new.undefined.command");
command.define("New Command", "This is created Programatically!", 
    commandService.getCategory("org.eclipse.ui.category.window"));

IHandlerService handlerService = (IHandlerService) serviceLocator.getService(IHandlerService.class);
handlerService.activateHandler(command.getId(), new AbstractHandler() {

    public Object execute(ExecutionEvent event) throws ExecutionException {
        System.out.println("Command executed !");
        return null;
    }
});

 

See also:

Part 1: Actions Vs Commands
Part 2: Selection and Enablement of Handlers
Part 3: Parameters for Commands
Part 5: ISourceProvider & dynamically updating Commands
Part 6: 'toggle' & 'radio' style menu contribution

Jan 9, 2009

Adding an input prompt to SWT Text

Adding an Input Prompt to a text control is most common in web applications. Today I happened to see a JavaScript that handles this elegantly. The script itself is just 18 lines and using it requires just 1 line of code. What would be the effort required to create something in SWT? hmmm not very different:

public static void addPrompt(final Text text, final String defaultText) {
    text.addFocusListener(new FocusListener() {

        public void focusGained(FocusEvent e) {
            if(text.getText().equals(defaultText)) {
                text.setText("");
                text.setForeground(null);
            }
        }

        public void focusLost(FocusEvent e) {
            if(text.getText().equals("")) {
                text.setText(defaultText);
                text.setForeground(text.getDisplay().getSystemColor(SWT.COLOR_GRAY));
            }
        }
    });
}

 

To use:

InputPrompter.addPrompt(text, "Click Me!");

The result

Input Prompt SWT

Input Prompt SWT

The same trick can be applied to Combo boxes as well.

Jan 7, 2009

Commands Part 3: Parameters for Commands

Think of a command which opens a file in an editor. You can't possibly create an extensive list of "Open File - somefile.txt", "Open File - someotherfile.txt", etc. Rather you want a generic command like "Open File" with the actual file as a parameter. In this tip, lets see how to create such a command.
The extension point for the command and the parameter:
<command name="Open File"
      defaultHandler="com.eclipse_tips.commads.OpenFileHandler"
      id="com.eclipse-tips.commands.openFileCommand">
   <commandParameter
         id="com.eclipse-tips.commands.filePathParameter"
         name="File Path">
   </commandParameter>
</command>

The handler code looks like:
public Object execute(ExecutionEvent event) throws ExecutionException {   
    String filePathParam = event.getParameter("com.eclipse-tips.commands.filePathParameter");
    IPath filePath = new Path(filePathParam);
    IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
    IWorkbenchPage activePage = ...// get the activePage
    try {
        IDE.openEditor(activePage, file);
    } catch (PartInitException e) {
        ;// display error message
    }
    return null;
}

As you can see, the ExecutionEvent will have all the parameters, which can be accessed thru their ids. Once you get the parameter string, you can use it in your own way. But exactly do we pass different parameters to that command? When you put the command in a toolbar/menu you can specify the parameter:
<menuContribution
      locationURI="toolbar:org.eclipse.ui.main.toolbar">
   <toolbar
         id="com.eclipse-tips.commands.toolbar1">
      <command
            commandId="com.eclipse-tips.commands.someCommand"
            id="com.eclipse-tips.commands.someCommandInToolBar">
      </command>
      <command style="push"
            commandId="com.eclipse-tips.commands.openFileCommand"
            label="Opens somefile">            
         <parameter
               name="com.eclipse-tips.commands.filePathParameter"
               value="MyProject/somefile.txt">
         </parameter>
      </command>
      <command style="push"
            commandId="com.eclipse-tips.commands.openFileCommand"
            label="Opens some other file">
         <parameter
               name="com.eclipse-tips.commands.filePathParameter"
               value="MyProject/someotherfile.txt">
         </parameter>
      </command>
   </toolbar>
</menuContribution>

The above example is a naive one. Lets see the real world example: "Show View" command. The command is generic and can show any view. The view id is given to the command as a parameter:
<command
        name="%command.showView.name"
        description="%command.showView.description"
        categoryId="org.eclipse.ui.category.views"
        id="org.eclipse.ui.views.showView"
        defaultHandler="org.eclipse.ui.handlers.ShowViewHandler">
   <commandParameter
            id="org.eclipse.ui.views.showView.viewId"
            name="%command.showView.viewIdParameter"
            values="org.eclipse.ui.internal.registry.ViewParameterValues" />
  <commandParameter
        id="org.eclipse.ui.views.showView.makeFast"
        name="%command.showView.makeFastParameter"
        optional="true">
  </commandParameter>

The list of all possible values of the parameter is given by the class ViewParameterValues. The class would iterate thru the view registry and return it. This information is used in defining the key bindings:

Key bindings for parameterized command

If we define our own parameter values, we can also get our command in the key bindings page:
image

Defining the parameters is all about returning a map of display names & the ids:
public class FileParameters implements IParameterValues {
    public Map getParameterValues() {
        Map params = new HashMap();
        params.put("Some File", "MyProject/somefile.txt");
        params.put("Some Other File", "MyProject/someotherfile.txt");
        return params;
    }

}
The name would be displayed in the key bindings page and the id would be used to invoke the command when the key sequence is pressed.

See also:
Part 1: Actions Vs Commands
Part 2: Selection and Enablement of Handlers
Part 4: Misc items ...
Part 5: ISourceProvider & dynamically updating Commands
Part 6: 'toggle' & 'radio' style menu contribution

Jan 5, 2009

Commands Part 2: Selection and Enablement of IHandlers

In the last tip, we saw that a Handler can be declared separately from a Command. This enables for multiple handler declarations for the same command. We can also customize when a handler is active and visible, thru plugin.xml itself. A handler that doesn't have any of these conditions is called as "default handler". When no other handler is associated with a command in a particular context, then the default handler will be the handler that gets executed. Remember, at any given point of time, there is at most only one handler is associated with a command. Lets have a look into how a particular handler is selected for a given context.
A handler can be specified with activeWhen condition using the expression language. Say for our command, we have two different handlers. One should be active when the current selection is an IFile and the other should be active when the current selection is IFolder. The expression for these would look like:

<handler
      class="com.eclipse_tips.commads.SomeCommandHandler1"
      commandId="com.eclipse-tips.commands.someCommand">
   <activeWhen>
      <with
            variable="selection">
         <iterate
               operator="or">
            <instanceof
                  value="org.eclipse.core.resources.IFile">
            </instanceof>
         </iterate>
      </with>
   </activeWhen>
</handler>
<handler
      class="com.eclipse_tips.commads.SomeCommandHandler2"
      commandId="com.eclipse-tips.commands.someCommand">
   <activeWhen>
      <with
            variable="selection">
         <iterate
               operator="or">
            <instanceof
                  value="org.eclipse.core.resources.IFolder">
            </instanceof>
         </iterate>
      </with>
   </activeWhen>
</handler> 


I'll save the explanation for the expression language for a separate tip, but for now a short one line desc: the first handler will be enabled when the selection current contains at least one IFile and the second handler will be enabled when the selection contains at least one IFolder. This raises to two questions.
1) What if the selection is just an IProject?
In this case, as none of the handlers are eligible, the command is disabled. This is where the default handler, if you have provided one, would be associated with the command (and the command will be enabled).
2) What if the selection contains both IFile and IFolder?
Now both the handlers are equally qualified to handle the command. But since the framework cannot pick one randomly the command is simply disabled. Even if you have provided a default handler, it won't be associated with the command, because the other two handlers are more specific than the default one.
How is the "specificness" of a handler is defined? It depends on the conditions that you give in the activeWhen expression. The order is defined in the ISources class. You can go thru the complete set there, to get a glimpse of the most commonly used ones, the order from least specific to most specific is like this:
  • Active Context (activeContexts)
  • Active Actions Sets (activeActionSets)
  • Active Shell (activeShell)
  • Active Workbench Window (activeWorkbenchWindow)
  • Active Editor Id (activeEditorId)
  • Active Part Id (activePartId)
  • Current Selection (selection)
If a handler has activeWhen defined with active context and the other one with current selection, the second one will be selected as the selection is more specific than the active context. The activeWhen for all the handlers are evaluated and the one that returns true for the most specific condition is selected. When two handlers return true for the available most specific condition (like the selection having both IFile & IFolder in our case), no handler will be associated with the command.
All these things are done without even loading your handler in the memory. Even without loading your plugin! 
In the previous tip, we saw how a handler is selected with the activeWhen expression, when more than one handler is declared. Now assuming a handler is selected, whether to enable the command or not, is determined by the enabledWhen expression.
In our previous example, we saw the handler that is active when the selection at least contained one IFile. Now lets we want to enable it only when the total count of the selection is 2. We can specify it as:

<handler
      class="com.eclipse_tips.commads.SomeCommandHandler1"
      commandId="com.eclipse-tips.commands.someCommand">
   <activeWhen>
      <with
            variable="selection">
         <iterate
               operator="or">
            <instanceof
                  value="org.eclipse.core.resources.IFile">
            </instanceof>
         </iterate>
      </with>
   </activeWhen>
   <enabledWhen>
      <with
            variable="selection">
         <count
               value="2">
         </count>
      </with>
   </enabledWhen>
</handler>

 
So the handler will be active and associated with the command, if the selection contains at least one IFile. Still the command will be enabled only if selection has exactly 2 elements. activeWhen and enabledWhen are similar - with respective to the expression language and lazy loading of the plugin until the command is executed. But there is small difference - your handler might be loaded iff the enabledWhen expression returns true and your plugin is already loaded. The enablement algo works this way:
  • No enabledWhen specified, plugin is not loaded - command is enabled
  • No enabledWhen specified, but plugin is loaded - consult handler.isEnabled() and set command accordingly
  • enabledWhen specified, returns false, command is disabled (no matter plugin is loaded or not)
  • enabledWhen specified, returns true, plugin is not loaded - command is enabled
  • enabledWhen specified, returns true, plugin is loaded - consult handler.isEnabled() and set command accordingly
So far we saw commands, handlers and their enablements. But what about generalizing a command? That can be done by adding parameters for a command. And that would be the next tip in this series.

Update (31-Mar-2009): Thanks to Hiroki Kondo, a Japanese version of this blog entry is available here.


See also:
Part 1: Actions Vs Commands
Part 3: Parameters for Commands
Part 4: Misc items ...
Part 5: ISourceProvider & dynamically updating Commands
Part 6: 'toggle' & 'radio' style menu contribution

Jan 2, 2009

Commands Part 1: Actions Vs Commands

As you would have seen, there are two different ways to contributing to the Workbench: Actions and Commands. Although Commands are newer and advanced, I've always preferred using Actions, simply because of my comfort level in using them. Now that I've started fixing some bugs in the Command framework, I'm forced to look into the details. The more deeper I look into the Commands, the more I'm loving it. So I decided to write a series of on the Commands and this is the first one in the series. Many of the information presented here is obtained by looking some old bugs, wiki and digging into CVS history. If I'm missing anything or wrong about something let me know.

Lets start with Actions. We are able to contribute to the menus, toolbars, pull down menu, etc. We are able to specify the UI details like label or tooltip in the plugin.xml itself, which helps in lazy loading. So whats wrong with them?
  • The UI and handling are always tied. There is no way you can separate each other
  • While Actions can be contributed to different parts of the workbench (popup menu/tool bar), all of them were different extension points and so you end up duplicating the XML in multiple places. The worst of it is that not all the extension points expect the same configuration.
  • Specifying Actions in multiple places is a maintenance nightmare. If you have to change the icon of an action, you need to change in all the places.
  • Another issue with duplicating Actions in plugin.xml is that multiple instance of the same Actions will be created in the memory
Lets see how the Commands Framework eliminates all this. Commands are defined by the org.eclipse.ui.commands extension point. A typical command would look like:

<command
         id="com.eclipse-tips.commands.someCommand"
         name="Some Command">
</command>


Yeah thats it. That defines a Command! If you want to place this in a tool bar, you have to use the extension point org.eclipse.ui.menus:

<menuContribution
      locationURI="toolbar:org.eclipse.ui.main.toolbar">
   <toolbar
         id="com.eclipse-tips.commands.toolbar1">
      <command
            commandId="com.eclipse-tips.commands.someCommand"
            id="com.eclipse-tips.commands.someCommandInToolBar">
      </command>
   </toolbar>
</menuContribution>

 
Now that takes of the placement in the UI. But what about the code that gets executed? That goes into a another extension point, org.eclipse.ui.handlers:

<handler
         class="com.eclipse_tips.commads.SomeCommandHandler"
         commandId="com.eclipse-tips.commands.someCommand">
</handler>


One last piece is to add an icon to the Command
No price for guessing that you need to use another extension point, org.eclipse.ui.commandImages:

<image
         commandId="com.eclipse-tips.commands.someCommand"
         icon="icons/sample.gif">
</image>


All set. Lets see the Command in action:
image
As you see, in the actions we would just use only one extension point, instead of the four which we have used now. Does it sounds like a round about way or doing things? Probably once we get to know about multiple handlers for a Command and context based association & enablement of the handlers etc, we will see the beauty of the framework. That would be the next in this series.

Update (31-Mar-2009): Thanks to Hiroki Kondo, a Japanese version of this blog entry is available here.

Update (29-Sep-2009): Thanks to Peng Zhang, a Chinese version of this blog entry is available here.


See also:
Part 2: Selection and Enablement of Handlers
Part 3: Parameters for Commands
Part 4: Misc items ...
Part 5: ISourceProvider & dynamically updating Commands
Part 6: 'toggle' & 'radio' style menu contribution