A system tray icon for monitoring Hudson with Eclipse RCP
Our team needed a system tray icon that indicates the status of the most recent build in Hudson. I decided to write a small application with Eclipse RCP which took me about a day.
Why Eclipse RCP? First, I didn't want to get involved with .NET. I only have the slimmest .NET knowledge and I didn't want to loose time by my lack of experience. Secondly, some of us have a Mac :-)
Thirdly, system tray icons can be added from the JVM. Java 6 supports it as does Eclipse Europa (3.3). I did a quick poll in our team and the majority wanted to avoid installing Java 6 on their machines. And some of us have a Mac :-)
So I ended creating my first application ever with Eclipse RCP. To get started I got the latest Eclipse release and followed the instructions to create a new RCP project here. Next I copied the system-tray-related code I found here.
That got me started. The first thing I did was obtaining some interesting icons to indicate a success and failed build. I found them here.
Plugin development (Eclipse considers an RCP application as a kind of plugin) in Eclipse is very intuitive, the Eclipse GUI makes things easy enough, like launching the application from Eclipse. Obviously debugging the application is very easy as well.
Based on the generated classes I've added all my logic to the ApplicationWorkbenchWindowAdvisor class. The first annoyance I ran into is Eclipse's threading model. Hudson has an RSS feed that contains the status of the latest build. I wanted to start a new thread to regularly check the RSS feed for updates.
But you cannot start a new thread and call Eclipse GUI components from it. Instead you have to call the org.eclipse.swt.widgets.Display#asyncExec(Runnable) method to execute code in a separate thread. But that's not all. I first implemented my Runnable class like this:
Runnable checkFeed = new Runnable() {
public void run() {
while (true) {
// check the feed
try {
Thread.sleep(30 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
window.getShell().getDisplay().asyncExec(checkFeed);
This however did not work out since the endless while loop blocks all GUI activity, including the popup menu when right-clicking on the system tray icon.
I had to stop blocking this thread, so I implemented the Runnable class as follows:
private long lastFeedCheck = 0;
private void launchFeedCheckingThread() {
Runnable checkFeed = new Runnable() {
public void run() {
long now = System.currentTimeMillis();
if (now - lastFeedCheck < 30000) {
// sleep a little while to avoid being a CPU hog
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
// re-schedule this Runnable instance
if (!window.getShell().getDisplay().isDisposed()) {
window.getShell().getDisplay().asyncExec(this);
}
return;
}
try {
// check the feed
} finally {
// update the timestamp variable to delay the
// next feed check with 30 seconds
lastFeedCheck = System.currentTimeMillis();
// re-schedule this Runnable instance
if (!window.getShell().getDisplay().isDisposed()) {
window.getShell().getDisplay().asyncExec(this);
}
}
}
}
// launch the feed checking thread for the first time
window.getShell().getDisplay().asyncExec(checkFeed);
}
This effectively frees up the thread with GUI activity responding promptly. While the RCP application behaved nicely when launched from Eclipse I ran into trouble when exporting the stand-alone application.
In Eclipse, exporting an RCP application is pretty straightforward. First, you have to create a 'Product Configuration' file (New -> Other -> Product Configuration). Here you can provide deployment options, like adding additional Eclipse plugins.
This worked fine until I added two libraries to the application: rome.jar and jdom.jar. I'm using them to read the Hudson RSS feed. I first added them as a project library in Eclipse as you would do in a regular Java project.
This however is not enough to have them exported. I tried adding them to the build.properties file under the Extra Classpath Entries section. This solved the error that previously occurred while exporting.
But the JARs still weren't included in the exported application. Unable to find another work-around I decompressed the content of both JARs in the root of the RCP project and included them for export in the build.properties file (see screen shot). This effectively included the required classed in the exported application :-)
Overall my first project in Eclipse RCP was a breeze. The Eclipse API is somewhat crowded but still intuitive to program with. The fact that the Eclipse classes have the source code attached makes things easier as well.
If you want to monitor you own Hudson server from your system tray check out the source code (Eclipse 3.3 plugin edition required) and Windows binaries.
Happy coding!
| Attachment | Size |
|---|---|
| HudsonTray-win32.zip | 12.11 MB |
| HudsonTray-source.zip | 685.13 KB |
| ApplicationWorkbenchWindowAdvisor.java | 6.93 KB |
- Login or register to post comments
- 5245 reads
- Flag as offensive
- Email this Story
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)







Comments
Paul Dinesh replied on Wed, 2008/01/23 - 10:45pm
Hi, I am not able to download the resources(attachments)...
Any Help on that??
Thanks,
paul
Steven Devijver replied on Thu, 2008/01/24 - 4:45am
Mike Evans replied on Fri, 2008/01/25 - 12:01pm
Cole Markham replied on Fri, 2008/01/25 - 12:40pm
Steven,
Nice work. Like MikeE said, the Job API is really nice for running a background task. Once you get your results you'll have to then use Display.asyncExec to update the UI.
Job feedCheckJob = new Job(){// Check the feed
if(hasUpdates){
Display.getDefault().asyncExec(new Runnable(){
// Update display
});
}
this.schedule(3000); // Schedule to run again after a three second delay
}
feedCheckJob.schedule(); // Submit the job to be run now
I've run into that problem with the jars as well. What you need to do is add them to the the plugin manifest. Just open the editor for the META-INF/Manfiest.mf file that should have been created with your plugin. Then switch to the "Runtime" tab. In the bottom right there is a pane for adding jars; select the ones you need there. Then be sure you add the jars to the binary build like you did before. That should do the trick. You no longer need to specify the jars in the normal Java build path like you did before. I think it uses the Java build path (if it is there) when you run the application from Eclipse, which is why that worked. When you export the application it doesn't include that information, so it relies on what is in the bundle manifest.
Hope that helps.
Cole
Steven Devijver replied on Sat, 2008/01/26 - 6:35am
Kohsuke Kawaguchi replied on Thu, 2008/01/31 - 3:49am
in response to: sdevijver
Hi, I wonder if you'd be interested in hosting the source code in the Hudson project, so that other people can potentially join the development of this tool. If you'd be intereste, please write to me at kk AT kohsuke DOT org.
Toby Weston replied on Sat, 2008/09/13 - 10:33am
Hi, Great article, did you have sucess running on Mac with this? I'm having problems with notifications (balloon help) with something similar.
The SWT snippet (http://dev.eclipse.org/viewcvs/index.cgi/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet225.java?view=co) just plain don't work for me on Mac, any ideas?