Ubuntu 9.10 & Eclipse 3.5

I recently upgraded Ubuntu to its latest version (9.10, Karmic Koala) and it works great so far. Except for Eclipse.

I ran Eclipse 3.5 (Galileo), and apparently SWT in that version does something wrong in communicating with GTK. The end result is that buttons don’t react to mouse clicks anymore. Rather annoying. Luckily, there is a solution available. Alternatively, you can use the latest Eclipse 3.6 (Helios) milestone.

But that wasn’t the end of it. Eclipse would now perform extremely slowly on a variety of tasks. It turns out that this is caused by Eclipse now running on the GCJ Virtual Machine. I simply uninstalled everything with “gcj” in its name using Synaptic and all was well again.

JavaFX for GNU/Linux has arrived

Finally, the time has come: JavaFX is now supported on both GNU/Linux and Solaris.

It’s not really advertised, though, so h Here’s how to get it:

  • Go to the JavaFX website.
  • Click the Download now button. Yes, the one that reads JavaFX 1.1 SDK.
  • Click the JavaFX 1.1.1 1.2 SDK option, and click Download.
  • You’ll be prompted to download javafx_sdk-1_2-linux-i586.sh. Save it somewhere convenient.
  • Make the downloaded file executable with chmod + x
  • Run the shell script with ./javafx_sdk-1_2-linux-i586.sh
  • Page through the annoying legal stuff by pressing Space repeatedly. At the end, type yes.
  • You now have a javafx-sdk1.2 directory that you can play with.

Enjoy!

Oh, and in case you have some JavaFX code from pre-1.2 versions, here’s how to migrate it.

Update: There is also a new Eclipse plugin. Binaries only, the source will have to wait until it gets transferred to eclipse.org.

JavaFX plugin for Eclipse patched

A while ago I wrote about how the JavaFX Eclipse plugin has some shortcomings. Luckily, the plugin is released under an Open Source license (BSD). Therefore, the source is available, and anyone can fix problems and supply patches.

So I decided to do just that, and checked out the code from the Subversion repository. I followed the steps described in the Wiki to get the project compiled.

The first thing I ran into, is that the default target didn’t exist. That was easy enough to fix.

Next, it bothered me that I needed to provide several properties on the command line. For instance I needed to specify -DeclipseDir=/opt/eclipse every time. So I patched the build to get this location from the environment variable ECLIPSE_HOME which I set in my .profile.

The same goes for the location of the JavaFX SDK. I introduced a JAVAFX_HOME environment variable to store that location. With these three modifications I could finally issue a build with just a simple ant.

With the build working it was time to tackle one of the problems I encountered during my usage of the plug-in. I figured it would be easy to fix the issue where compilation errors use up three lines in the Problems view, so that’s where I started. Based on information in the book Eclipse, Building Commercial-Quality Plug-ins, I knew I had to look for IMarker. There was only one such place in the code, so the problem was easily fixed. Progress at last!

I took a look at the other issues that were reported against the plug-in. There might be easier ones than the ones I experienced 😉 Indeed, someone noticed that the JavaFX perspective missed an icon. At first I couldn’t reproduce it, but that was because I was starting the plug-in from Eclipse. The official distribution did show the problem. Luckily, the bug reporter also found the cause: the icon used wasn’t part of the jar. A simple addition to build.properties fixed that.

Five patches already! I was feeling pretty good about myself 🙂

Next, someone wanted help with import statements. That was a lot trickier, but probably also a lot more valuable. Having looked at the IMarker code before, I naturally wanted to add a marker resolution.

This turned out to be a lot more work than I anticipated, but I managed to get something working. There were some glitches, and it probably needed a lot more testing for corner cases, but I could add a missing import statement based on the class name. Because I felt that this code wasn’t ready for prime time yet, I didn’t supply a patch, though.

This patching frenzy took place during the holidays. I got no response from Sun during that time, but I guess that was to be expected, given the time of year. So I decided to wait until some time into the new year to see what would happen.

Monday January 5 went by without news, but this morning I started to receive a stream of email notifications about issue tracker updates. Several of my patches were being accepted, and then I even received notification that I was given commit access! Such are the wonders of Open Source…

JavaFX plugin for Eclipse

Being an happy Eclipse user, I’ve always felt sort of a second-rate citizen in the JavaFX world. I get it that Sun wants to promote their own IDE. But let’s face it, there are a lot of us Eclipseans (is that even a word?) out there. Today, my luck has changed with the release of the JavaFX Plugin for Eclipse. Thanks to Jim Weaver for pointing that out to me. BTW, anybody interested in JavaFX should subscribe to his blog.

The first thing I notice, is that, again, there is no support for GNU/Linux. Well, I’m getting used to that by now. I downloaded the Mac version, and it seems to work on my Ubuntu box. So I naturally took it for a spin right away. Here are my first impressions.

Wizards

The plugin doesn’t provide a New Project wizard. Instead, you need to create a new Java project, and then add the JavaFX nature to it. A bit odd, but OK.

I follow the documentation and add a new script using the New Script wizard. Easy as pie. Then I’m supposed to drag a Stage onto the script. The Insert Template: Stage dialog doesn’t work: it just keeps popping back up over and over again. It doesn’t show any errors, but it also doesn’t insert any code. Maybe this is because I’m running on an unsupported platform, I don’t know.

Editor

Anyway, who needs these UI builders anyway 😉 Let’s type in some code myself. The plugin provides basic syntax highlighting, which is good. Other than that, it doesn’t seem to provide much value. Error markers in the gutter don’t show the error messages when you hover over them, as the JDT does. The error messages in the Problems view take up three lines, so that I can see only a few of them at once.

Problems view

Speaking of errors, whenever I insert some non-ASCII symbol, like the é in my name, the plugin reports a mysterious error: Sorry, but the character ''. Right.

Also, there is no Code Completion (or I haven’t been able to find it). For someone just learning the language, as I am, this is a serious drawback. And some Quick Fixes are sorely missed as well.

Running a program

Running a program works using the expected Run As > JavaFX Application menu. The Run Configurations dialog looks like it is not a result of a collaboration between developers and designers:
Run Configurations

What is cool, is the Profile drop down list. It allows you to select the platform on which to run. You can emulate a mobile device, or run on the desktop as an application, as an applet, or with Web Start.

What is not so cool, is that you cannot select a working directory. This means you cannot test real-life deployments all that well. Nor can you specify Virtual Machine arguments. So for memory intensive applications, you’d have to revert to the command line or some build script.

Conclusion

I’m very happy that Sun is finally welcoming Eclipse users into the JavaFX world. But it seems that this plugin is indeed an early release, as there are many rough edges and missing features. Having said that, something is better than nothing. And the BSD license is certainly appreciated.

Running a JavaFX script from an OSGi bundle

Two technologies that have been on my radar for a while are JavaFX, Sun’s entry in the RIA race, and OSGi, the Dynamic Module System for Java. In this tutorial, I will combine the two by running a JavaFX script from an OSGi bundle. You will need Eclipse and Java 6. [That’s right: a JavaFX tutorial that doesn’t want you to use NetBeans!]

Although JavaFX is still in the beta stage (despite being announced at JavaOne last year), and is very much in flux, it makes for an interesting UI technology. I wouldn’t want to write production ready applications in it yet, but maybe that will change in the not-too-distant future.

OSGi, on the other hand, is very much a mature technology. It is widely used, for instance for the plug-ins that make up Eclipse. In fact, Eclipse Equinox is now the reference implementation for OSGi. BTW, the OSGi term for plug-in is bundle, and I will use the two interchangeably.

Wrapping the JavaFX libraries in an OSGI bundle

Everything in OSGi happens inside a bundle, so the first step to running a JavaFX script from an OSGi bundle, is to create a bundle that holds the JavaFX jars. You will need to download the latest JavaFX distribution and unzip it somewhere.

Then, in Eclipse, select File|New|Project..., so that the New Project wizard appears. In the first step, select from the Plug-in Development category the Plug-in from existing JAR archives, and click Next. In the second step, click the Add External button and add all the jars from the JavaFX distribution’s lib directory. In the third step, enter JavaFX for the Project name, and click an OSGi framework under Target platform. Select standard for the OSGi framework, and click Finish. After a while, the plug-in project appears.

     

Next, open META-INF/MANIFEST.MF, select the MANIFEST.MF tab, and paste the following line into it:

Bundle-RequiredExecutionEnvironment: JavaSE-1.6

Now right-click on JRE System Library in the Package Explorer, and select Properties. For System library, select Execution environment, and from the combo box next to it, select JavaSE-1.6. Click OK.

 

Creating an OSGi bundle that will run a JavaFX script

You will now use the bundle you just created by a new bundle, the one running the JavaFX script. Again, select File|New|Project..., but this time, select Plug-in Project from the Plug-in Development category. In the next step, enter Run JavaFX for the Project Name, select the standard OSGi framework as the Target platform (same as above), and click Next. In the next step, just click Finish to create the project.

 

In the Manifest Editor, select the Dependencies tab. Click the Add button under Required Plug-ins, select JavaFX (1.0.0) from the list, and click the Save button in the toolbar.

   

Creating the JavaFX script

Create a new directory named script, and create a new file named HelloWorld.fx in it. Paste the following code into it:

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.paint.Color;
import javafx.scene.text.*;

Frame {
  title: "Hello World!"
  width: 550
  height: 200
  visible: true
  stage: Stage {
    content: Text {
      font: Font {
        name: "Sans Serif"
        style: FontStyle.BOLD
        size: 24
      }
      x: 20
      y: 40
      stroke: Color.BLUE
      fill: Color.BLUE
      content: "Hello from JavaFX Compiled Script"
    }
  }
}

   

Next, right-click the script directory, and select Build path|Use as Source Folder.

Running the script

To actually run the JavaFX script, we will use JSR-223: Scripting for the Java Platform. [That’s why I made you select JavaSE-1.6 as the bundle execution environment.]

In the Run JavaFX project, open the src directory, the run_javafx package, and then the Activator class. [A bundle’s activator allows you to do stuff when your bundle starts or stops.] In the start() method, add the following code:

final ScriptEngine engine = new ScriptEngineManager()
    .getEngineByExtension("fx");
final String scriptName = "HelloWorld.fx";
final InputStream stream = Thread.currentThread()
    .getContextClassLoader()
    .getResourceAsStream(scriptName);
engine.eval(new InputStreamReader(stream));

Use Eclipse’s Quick Fix to add the required import statements for ScriptEngine, ScriptEngineManager, InputStream, and InputStreamReader.

To run the bundle from Eclipse, select the MANIFEST.MF file, select the Overview tab, and click the Run button at the top.

In the Console, you will see the osgi> prompt, followed by a lot of error output. If you scroll through the output, you will see

org.osgi.framework.BundleException: Exception in
    run_javafx.Activator.start() of bundle Run_JavaFX.
[...]
Caused by: java.lang.NullPointerException
	at run_javafx.Activator.start(Activator.java:24)
[...]

Type exit + Enter in the Console to shut down the plug-in.

Finding the script engine

The NullPointerException comes from the ScriptEngine for JavaFX that could not be found. We can fix this as follows: create a new folder named services under META-INF, and copy the javax.script.ScriptEngineFactory file from the JavaFX project to it. See the Service Provider section in the Jar File Specification for an explanation.

 

Now when you run the plug-in, you will get

org.osgi.framework.BundleException: Exception in
    run_javafx.Activator.start() of bundle Run_JavaFX.
[...]
Caused by: javax.script.ScriptException: compilation failed
	at com.sun.tools.javafx.script.JavaFXScriptEngineImpl.parse(JavaFXScriptEngineImpl.java:254)
	at com.sun.tools.javafx.script.JavaFXScriptEngineImpl.eval(JavaFXScriptEngineImpl.java:144)
	at com.sun.tools.javafx.script.JavaFXScriptEngineImpl.eval(JavaFXScriptEngineImpl.java:135)
	at com.sun.tools.javafx.script.JavaFXScriptEngineImpl.eval(JavaFXScriptEngineImpl.java:140)
	at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:232)
	at run_javafx.Activator.start(Activator.java:24)
[...]

There is nothing wrong with the JavaFX script, though. You can test this yourself by running the command line tools (javafxc and javafx) against it.

Fixing the class path

The problem is in the JavaFXScriptEngineImpl class. It passes the class path to the JavaFXScriptCompiler. But this class path is not the actual class path that is used by the class loader, it is taken from the java.class.path system property. You can override this by either setting the com.sun.tools.javafx.script.classpath system property, or by setting the classpath attribute on the ScriptContext.

I will take that last approach. Just before the engine.eval(...) line, add the following:

engine.getContext().setAttribute("classpath", 
    getJavafxClassPath(), ScriptContext.ENGINE_SCOPE);

Implementing the getJavafxClassPath() method is a bit tricky:

private String getJavafxClassPath() {
  String result = FX.class.getProtectionDomain()
      .getCodeSource().getLocation().toExternalForm();
  final int index = result.indexOf(":/");
  if (index >= 0) {
    result = result.substring(index + 1);
  }
  return result;
}

Now finally, when you run the plug-in, it will show the Hello world window:

Automating refactorings

I’m a big fan of both refactoring and automation. It’s no wonder, then, that the support for automated refactoring in Eclipse makes me very happy. I find that it makes me a lot more productive, and I produce better code. That’s because performing a refactoring is easy and fast enough to actually do it.

I also find that I refactor routinely. Where Martin Fowler, in his classic book Refactoring, gives the advice not to mix refactoring and adding new functionality, I do it almost mindlessly anyway. No need to run unit tests before and after the refactorings, since I know they Just Work™.

Not so with any refactorings that are not supported by the tool, though. For instance, when trying to adhere to the Law of Demeter, one would want to perform the refactoring Hide Delegate. Unfortunately, Eclipse has no support for this refactoring 😦 You can, however, simulate this refactoring using a combination of other refactorings. Let me explain that using a simple example.

We start with the following abstract code that shows the situation before we want to apply Hide Delegate:

public class Client {

  public void example() {
    final Server server = new Server();
    server.getDelegate().method();  
  }

}

public class Server {

  private final Delegate delegate = new Delegate();

  public Delegate getDelegate() {
    return delegate;
  }
  
}

public class Delegate {

  public void method() {
   // Do it...
  }
  
}

First, we perform Extract Method on server.getDelegate().method() (make the method public):

public class Client {

  public void example() {
    final Server server = new Server();
    method(server);  
  }

  public void method(final Server server) {
    server.getDelegate().method();
  }

}

Next, perform Move Method to move method() to Server:

public class Client {

  public void example() {
    final Server server = new Server();
    server.method();  
  }

}

public class Server {

 private final Delegate delegate = new Delegate();

  public Delegate getDelegate() {
    return delegate;
  }

  public void method() {
    getDelegate().method();
  }
  
}

And, voila, we have performed Hide Delegate!

The Power of Convention

I ran into some code the other day that wasn’t obvious to me right away. Why? Because it didn’t follow conventions. Let me explain.

In our system, we have what we call ‘binding objects’. These are objects that are persisted in our XML database and that we can use through Java interfaces. The code needed to access them is mostly boiler plate, so we generate it. Since the system was build on Java 1.4, we couldn’t use annotations for this. So, being an XML company, we naturally decided to describe the binding objects in XML and use XSLT to generate both the interface and the boiler plate implementation. We then add functionality by extending both of them.

Now, an often used convention in Java is to have the implementation for interface Xxx be named XxxImpl. We follow this convention often in our code, but for some reason did something else here. This cause me to look around wondering why I couldn’t find the implementation right away.

At this point, I’m sure someone will ask ‘So what?’. That’s always a good question 😉 For instance, in Eclipse, you would just select the interface and press either F4 to show the Type Hierarchy view, or Ctrl-T for a popup listing the same.

That’s true. But it requires a conscious action. Instead, if we had followed the convention, we would get this information for free. For instance, if both the interface and the implementation were in the same package, Eclipse’s Package Explorer would show them above each other. And even if they were in different packages, searching for the interface using Ctrl-Shift-T would also find the implementation. This free-riding is called a ‘widgetless feature‘. It is a Big Thing™ in user interface design.

Granted, it is a minor advantage. But this is just one example. Multiply by all the other places you can use conventions to reduce information overload, and you’ll find you’ll be more productive.

If you’re still not convinced, take advice from someone else. For instance, look at Maven: one of its central tenets is ‘convention over configuration‘.