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?

10 comments:

  1. #7

    https://bugs.eclipse.org/bugs/show_bug.cgi?id=248137

    Tell that to the PDT guys. What a lovely attitude.

    ReplyDelete
  2. I'm not sure that the IHandler#execute thing is still right because this would mean that one gets always null in the ExecutionListener#postExecute().

    ReplyDelete
  3. Nice post !!!

    One more mistake MHO is about internal package but not as user but provider. We delivered a plugin to clients without internal packages thus all class where accessible for them ...

    Then in a new release we refactored one of this class thinking that nobody where using it !!!! Wrong !!!

    Always create internal package (and don't export them) for internal classes !!!

    ReplyDelete
  4. @Tom
    Although the JavaDoc mandates null, Commands Framework doesn't check this. In fact, few handlers do return a value, which is used elsewhere.

    I got to know this null thing by Remy's comment in some bug. I guess there is already a bug opened for changing the JavaDoc.

    ReplyDelete
  5. This is great article for every Eclipse Plugin Developers!This article is NOT FOR ONLY NEWBIES.I'm a Eclipse Plugin Developer for three years,But I don't know these things.
    I would like to translate this article to Japanese for Japanese everyone.Are you O.K. to do it?Please!

    ReplyDelete
  6. @Hiroki Kondo(kompiro),

    The top left of this page, there is a translate option. I guess that supports Japanese as well. (well, the options are not in English, so I'm not sure)

    If you didn't find that useful or want to publish the translated material elsewhere, please make sure you link to the original article.

    Thanks!

    ReplyDelete
  7. @Prakash G.R.
    Thanks!
    The translater is not good for Japanese.I read the translated your page,there are many translated mistakes in the page.So I translated your page for Japanese.
    http://d.hatena.ne.jp/kompiro/20090214/1234631568

    ReplyDelete
  8. Manuel Selva said: Always create internal package (and don't export them) for internal classes

    If packages are not exported it is impossible for others to use those internal classes due to how the OSGi class loaders work.

    The platform has a policy of exporting all packages and marking internal ones using x-internal and x-friends.

    Not exporting your packages is a way to absolutely make sure nobody uses your internals, but it may be draconian if there exist good reasons for someone to do so.


    @Prakash, Nice article, (6) is a good one.

    ReplyDelete
  9. Excellent blog. Is it server sided? I am confused

    ReplyDelete