Thursday, December 24, 2009

Nightmare before Christmas: How to use JFace + SWT standalone

I could've as easily called this Eclipse plugins from HELL, but being Christmas and all I thought I would go for the Christmas thing, which gives me the opportunity to wish Merry Xmas to all the geeks who happen to be reading this lame-ass blog over the holidays instead of watching Star Trek as per tradition.

Being mainly a .NET guy, I am not too familiar with the eclipse platform, but I desperately needed to put together a quick UI and decided to go with JFace and SWT after @tarelli suggested so (he's the JAVA guy). Unfortunately, at the time I didn't realize he was talking about an Eclipse plugin project and not about using JFace and SWT in a standalone Java app.

So I went on and got started with some nice tutorials specific to running JFace + SWT standalone, and some more gentle introductions.

Time to get my hands dirty, so I started a new Java project, and dropped in some of the code from the tutorials. In order to get it build I needed to import JFace and SWT plugins as external jars, which I could not find anywhere in my plugins folder (I am on Galileo C:\eclipse 3.5\plugins). I needed to somehow get the damn plugins, but could not quite figure out how to get only those I needed from Help --> Install Software Updates, so I ended up pulling down anything to do with Eclipse SDK. To my delight the SWT and JFace plugins were there (in the plugins folder) after the lengthy process of downloading tons of stuff I didn't need.

After a bit of mocking about (blindly trying to import anything with jface or swt in it) I managed to understand which jars I needed to import to get the damn thing to build (org.eclipse.jface_3.5.1.M20090826-0800.jar and org.eclipse.swt.win32.win32.x86_3.5.1.v3555a.jar) I started mocking about with the code and spent a good while playing around with ContentProviders, ListViewers and so forth. Everything was building nicely, but as soon as I tried to run it as java application got the cold shower:

Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/core/runtime/IProgressMonitor
    at demo.ui.test.EntryPoint.main(
Caused by: java.lang.ClassNotFoundException: org.eclipse.core.runtime.IProgressMonitor

Apparently some type was missing somewhere. I've seen a lot of sh*t working on Visual Studio and all, but errors don't get much more cryptic than this.

After a good while, after unfruitfully trying to offline troubleshoot the heck out of my project (offline troubleshooting is just madness but I was waiting the phone company to turn on my broadband in the new apt i moved to recently), I reverted to @tarelli, the eclipse guru who got me into this mess, and begged for help: he promptly told me that I was in a bit of a feckin' mess, and if I wanted to get out of it alive I would've had to create a Plugin Project "with a view" and take it from there. I tried, and he was right, but I did not want a plugin and all the overhead that comes with it, so I kept pulling my hair for several hours with no luck, then went to bed. I felt rightly and truely screwed, if you want.

Luckily the day after the phone company turned on my broadband and I could stop passively obsessing about the problem and started aggressively abusing google in search of a solution to the problem.

After a not too long research (God bless THE INTERNET), turns out that if you want to use JFace + SWT outside a plugin based project you need some other jars. Basically if you're using JFace and SWT in a plugin project runtime dependencies are managed for you through the manifest file (I seem to understand) but if you go for the rogue option of having SWT running standalone then you need to know you need that stuff.

In the specific case of the IProgressMonitor thingy, adding a reference to the org.eclipse.equinox.common jar did the trick. After that I got the same error on a different class, EventManager, and after a couple of blind trials I got it working by importing the org.eclipse.core.commands jar. Obviously, not a mention of this in the tutorials, as I seem to understand there was a bit of refactoring on those packages after those tutorials were drafted (looks like this problem is around since eclipse 3.2 --> read this bug report for further info).

What can I say? If you're coming from .NET sometimes Java == Pain.


que0x said...

Maven baby! if you gonna use Java just learn Maven(I'm also a .NET guy)

Johnny Idol said...

yeah - not to talk about SWT multi-threading ... I'll check Maven out, thanks.

BlingBoyBart said...

I love Maven too, (warts 'n all), and share que0x's sentiments. As a former Access/VB developer, I stepped off just as .Net was emerging, so I cannot bash it fairly. (I'm working on it!)

My gut feeling is that .Net does pretty much everything, out-of-the-box -- it just works. BUT, when it doesn't -- you have to wait for Microsoft to fix it.

With Java, there is no box -- just a pile of tinkertoys dumped before you, in a heap on the floor. When something works, chances are that you had to either hack or learn something, to make it work. Talk about feelings of accomplishment!

Despite all the frustrations I've had, working with Java, it's been incredibly rewarding, overall. I'm a tinkerer, by nature, and have never been content to heed labels like "NO USER-SERVICABLE PARTS" and "DANGER: ELECTROCUTION RISK" so Java development seems to suit my temperament.

Thanks for sharing your insight re: working with JFace in a more current context -- sounds like I've been stumbling through the same old, stale tutorials! :)