Top 10 Mistakes in Eclipse Plugin Development
Join the DZone community and get the full member experience.Join For Free
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 :-)
(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.
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.
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.
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.
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.
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
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?
Opinions expressed by DZone contributors are their own.