ooomailer 1.0 – More Flexible Out-of-office Replies

October 2nd, 2011 by Martin No comments »

In my day job I have to deal with a huge amount of e-mails each day – most of them are not urgent, but some are. When I go for vacation or on a business trip, I need to let people know I am not available and won’t respond until I get back (and provide an alternate contact for urgent matters). These days pretty much every mail server has a “vacation message” feature, that allows you to do exactly that – supports sending automated responses to all e-mails coming to your inbox, letting others know you won’t be able to read the message before a given date. However the implementation of that feature varies from server to server.

I have several e-mail accounts on several mail servers and I found myself in a situation when I needed more flexibility in the way I set up my vacation message. Being involved in several open source projects and subscribed to many open mailing lists, I needed to make sure I don’t spam those lists or users of those lists (who may not know me) with my vacation auto-replies. Even people I do want to notify don’t need to get my auto-reply to every message that reaches me – notification once in several days is good enough. And I needed to customize the vacation message for internal recipients (e.g. providing links to internal resources) and have it slightly more detailed than the auto-replies that go to external people.

So, a couple of months back, the weekend before my summer vacation I sat down and implemented a simple utility that provides me with this flexibility. Since then I used it several times, fixed a few issues, and Alexis (a colleague of mine) contributed some more improvements. At this point I am pretty confident the tool works smoothly, so decided to release version 1.0. Give it a try if you are in a similar situation – the tool and the source code are available at http://hg.alutam.com/ooomailer.

Jersey 1.9.1 Released

September 16th, 2011 by Martin No comments »

Over the past two weeks, I’ve been working with Pavel on finalizing and staging the bits for the hands-on-lab on OAuth, we are going to do at this year’s JavaOne. As part of that, I had to make a few more clean-ups in the Jersey OAuth client library, so we decided to make a branch for 1.9.1 and make those clean-ups along with some other small fixes there. Now, 2 weeks after 1.9, we released it. This is the release we’ll be using for JavaOne and although the release cycle was so short, it does have two nice additions worth highlighting.

  • Un-/marshalling collection types
    Until 1.9.1, JAXB un-/marshalling in Jersey worked only for Collection and List interfaces. I.e. if your resource method returned (or took as a parameter) Collection<Foo> or List<Foo> (where Foo was a JAXB bean), de-/serialization from/to XML/JSON would work, but if it returned LinkedList<Foo> or Set<Foo> or any other Collection subtype, it would not work. This is fixed in 1.9.1 and you can now return and retrieve any well-known interfaces that extend Collection (such as Set, Queue, etc.) and their implementations which have default public constructor.
  • PostReplaceFilter improvements
    PostReplaceFilter can be used to support clients which can’t send the full range of HTTP methods. It enables converting POST requests to other methods such as PUT or DELETE. If a POST request comes with a different method specified in X-HTTP-Method-Override header, the filter will replace POST in the request with that specified method. This has been in Jersey for a while, but only supported method overriding using the X-HTTP-Method-Override header. In 1.9.1 you can now use “_method” query parameter as well, and when overriding POST to GET the filter will convert all the form parameters to query parameters. Whether both header and query parameter are looked at by the filter (or only the header or only the query parameter) is configurable. Thanks to gk5885Fredy Nagy and Florian Hars for sharing their views and patches.
You can see the full list of changes in our changelog. For more info on Jersey see http://jersey.java.net.

Jersey and Cross-Site Request Forgery (CSRF)

September 14th, 2011 by Martin 5 comments »

About two weeks back we released Jersey 1.9. See Jakub’s blog for more info on what’s new. One thing Jakub didn’t mention is that Jersey 1.9 also includes a new server side filter for Cross Site Request Forgery prevention. I won’t go into the details on what CSRF is – please refer to the OWASP CSRF page for that. Unfortunately, the generally recommended prevention is to generate per-request or per-session tokens on the server side, which client then has to include in its subsequent requests. This is quite easy to implement and there are servlet filters for doing that, however it does require a session state to be maintained and thus is not very RESTful. I was trying to implement something that would not require a session. After some searching I found the following two papers which both suggest there is a solution which works, and is not based on sessions:

The main idea is to check the presence of a custom header (agreed-upon between the server and a client – e.g. X-CSRF or X-Requested-By) in all state-changing requests coming from the client. The value of the header does not really matter. It works, because the browser would not send custom headers unless the web page makes a request using XMLHttpRequest, which only allows requests to the same site.

So, in Jersey 1.9 we added a server-side filter which does exactly that. You can find it here: server-side CsrfProtectionFilter.java

And, to make it easy to build clients, a corresponding client filter (that attaches the custom header to all potentially state-changing requests) is there as well: client-side CsrfProtectionFilter.

This can be further extended based on the feedback – we may add a check for the Referrer header and eventually even implement the session-based solution as an available configuration option. Just let us know, if you have an opinion.

Reading Password-Protected ZIP Files in Java

October 31st, 2009 by Martin 54 comments »

On a recent “fun” project, I needed my application to be able to access password-protected zip files of a particular format. It was one of these features I thought will take me no time to implement. Anyway, to my surprise, neither JDK supports password-protected ZIP files, nor I was able to find a suitable Java open source library I could use for that purpose. So, I ended up writing the utility class on my own. I wrote an implementation of java.io.InputStream that filters the ZIP file data and turns a password-protected ZIP into an unprotected one on the fly – so the stream can be nicely chained with java.util.zip.ZipInputStream. Although the class is specifically targeted at the particular type of ZIP files I had to deal with (see the limitations below), maybe other people have to deal with the same type of files, or this class can provide a good start for others to turn it into a utility that would work with any type of ZIP (maybe I will do it myself some day – for now I don’t have time).
To implement this class I used the ZIP File Format Specification as the source of information. I also used the 7-zip project (C++) as a reference during the debugging to verify my understanding of the ZIP spec. and the CRC algorithm.
So, here is the class:

import java.io.IOException;
import java.io.InputStream;

public class ZipDecryptInputStream extends InputStream {
    private static final int[] CRC_TABLE = new int[256];
    // compute the table
    // (could also have it pre-computed - see http://snippets.dzone.com/tag/crc32)
    static {
        for (int i = 0; i < 256; i++) {
            int r = i;
            for (int j = 0; j < 8; j++) {
                if ((r & 1) == 1) {
                    r = (r >>> 1) ^ 0xedb88320;
                } else {
                    r >>>= 1;
                }
            }
            CRC_TABLE[i] = r;
        }
    }

    private static final int DECRYPT_HEADER_SIZE = 12;
    private static final int[] LFH_SIGNATURE = {0x50, 0x4b, 0x03, 0x04};

    private final InputStream delegate;
    private final String password;
    private final int keys[] = new int[3];

    private State state = State.SIGNATURE;
    private int skipBytes;
    private int compressedSize;
    private int value;
    private int valuePos;
    private int valueInc;

    public ZipDecryptInputStream(InputStream stream, String password) {
        this.delegate = stream;
        this.password = password;
    }

    @Override
    public int read() throws IOException {
        int result = delegate.read();
        if (skipBytes == 0) {
            switch (state) {
                case SIGNATURE:
                    if (result != LFH_SIGNATURE[valuePos]) {
                        state = State.TAIL;
                    } else {
                        valuePos++;
                        if (valuePos >= LFH_SIGNATURE.length) {
                            skipBytes = 2;
                            state = State.FLAGS;
                        }
                    }
                    break;
                case FLAGS:
                    if ((result & 1) == 0) {
                        throw new IllegalStateException("ZIP not password protected.");
                    }
                    if ((result & 64) == 64) {
                        throw new IllegalStateException("Strong encryption used.");
                    }
                    if ((result & 8) == 8) {
                        throw new IllegalStateException("Unsupported ZIP format.");
                    }
                    result -= 1;
                    compressedSize = 0;
                    valuePos = 0;
                    valueInc = DECRYPT_HEADER_SIZE;
                    state = State.COMPRESSED_SIZE;
                    skipBytes = 11;
                    break;
                case COMPRESSED_SIZE:
                    compressedSize += result << (8 * valuePos);
                    result -= valueInc;
                    if (result < 0) {
                        valueInc = 1;
                        result += 256;
                    } else {
                        valueInc = 0;
                    }
                    valuePos++;
                    if (valuePos > 3) {
                        valuePos = 0;
                        value = 0;
                        state = State.FN_LENGTH;
                        skipBytes = 4;
                    }
                    break;
                case FN_LENGTH:
                case EF_LENGTH:
                    value += result << 8 * valuePos;
                    if (valuePos == 1) {
                        valuePos = 0;
                        if (state == State.FN_LENGTH) {
                            state = State.EF_LENGTH;
                        } else {
                            state = State.HEADER;
                            skipBytes = value;
                        }
                    } else {
                        valuePos = 1;
                    }
                    break;
                case HEADER:
                    initKeys(password);
                    for (int i = 0; i < DECRYPT_HEADER_SIZE; i++) {
                        updateKeys((byte) (result ^ decryptByte()));
                        result = delegate.read();
                    }
                    compressedSize -= DECRYPT_HEADER_SIZE;
                    state = State.DATA;
                    // intentionally no break
                case DATA:
                    result = (result ^ decryptByte()) & 0xff;
                    updateKeys((byte) result);
                    compressedSize--;
                    if (compressedSize == 0) {
                        valuePos = 0;
                        state = State.SIGNATURE;
                    }
                    break;
                case TAIL:
                    // do nothing
            }
        } else {
            skipBytes--;
        }
        return result;
    }

    @Override
    public void close() throws IOException {
        delegate.close();
        super.close();
    }

    private void initKeys(String password) {
        keys[0] = 305419896;
        keys[1] = 591751049;
        keys[2] = 878082192;
        for (int i = 0; i < password.length(); i++) {
            updateKeys((byte) (password.charAt(i) & 0xff));
        }
    }

    private void updateKeys(byte charAt) {
        keys[0] = crc32(keys[0], charAt);
        keys[1] += keys[0] & 0xff;
        keys[1] = keys[1] * 134775813 + 1;
        keys[2] = crc32(keys[2], (byte) (keys[1] >> 24));
    }

    private byte decryptByte() {
        int temp = keys[2] | 2;
        return (byte) ((temp * (temp ^ 1)) >>> 8);
    }

    private int crc32(int oldCrc, byte charAt) {
        return ((oldCrc >>> 8) ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]);
    }

    private static enum State {
        SIGNATURE, FLAGS, COMPRESSED_SIZE, FN_LENGTH, EF_LENGTH, HEADER, DATA, TAIL
    }
}

These are the limitations:

  • Only the “Traditional PKWARE Encryption” is supported (spec. section VII)
  • Files that have the “compressed length” information at the end of the data section (rather than at the beginning) are not supported (see “general purpose bit flag”, bit 3 in section V, subsection J in the spec.)

And this is how you can use it in your code:

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

// usage: java Main [filename] [password]
public class Main {
    public static void main(String[] args) throws IOException {
        // password-protected zip file I need to read
        FileInputStream fis = new FileInputStream(args[0]);
        // wrap it in the decrypt stream
        ZipDecryptInputStream zdis = new ZipDecryptInputStream(fis, args[1]);
        // wrap the decrypt stream by the ZIP input stream
        ZipInputStream zis = new ZipInputStream(zdis);

        // read all the zip entries and save them as files
        ZipEntry ze;
        while ((ze = zis.getNextEntry()) != null) {
            FileOutputStream fos = new FileOutputStream(ze.getName());
            int b;
            while ((b = zis.read()) != -1) {
                fos.write(b);
            }
            fos.close();
            zis.closeEntry();
        }
        zis.close();
    }
}

Jersey Hands-On Lab

September 16th, 2009 by Martin No comments »

Earlier this year, me and Naresh created an introductory level Jersey hands-on lab for JavaOne ’09. As I realized just recently, the hands-on labs had been made available for download to all SDN members (free registration) shortly after JavaOne. It may be another useful resource for you to get started with Jersey. The lab provides detailed step-by-step instructions on how to set up your environment and then guides you through 3 exercises:

  1. Hello world! – leading you through your first JAX-RS/Jersey application, explaining the JAX-RS basics
  2. Advanced JAX-RS/Jersey Features – showing how to develop a little more complex web application using JAX-RS/Jersey features such as path parameters, multiple representations for a resource, writing your own MessageBodyReader/Writer, Jersey MVC and some more
  3. Using Jersey Client API – showing how to access web resources using the Client API provided by Jersey

You can download the Hands-On Lab as well as get more info here. I’ve also added this link to our Jersey Wiki. After you download the lab, just unzip the file and open index.html in restwebservice directory. The zip also contains solution directories for all three exercises. I hope the lab will be of help. Let me know in case you have any questions or feedback on it.

JavaFX Password Field

September 12th, 2009 by Martin 12 comments »

As I mentioned in My First Experience with JavaFX blog, there is no password field in JavaFX, so I had to google for some workarounds. Although I found a few, none of them worked flawlessly, so last night I decided to spend some time trying to come up with a password field that would really work as expected. And, I think I managed to come up with an elegant and simple solution. No hacking in form of covering the text area with additional components or adding effects that blur the text box (including the caret and component borders). It looks and behaves exactly as you would expect of a password field. Click on the following picture to try it out:

Or click the following button for standalone mode:

And here is how it is implemented:

import javafx.scene.control.TextBox;
import javafx.util.Math;

/** * @author Martin Matula */
public class PasswordBox extends TextBox {
    public-read var password = "";

    override function replaceSelection(arg) {
        var pos1 = Math.min(dot, mark);
        var pos2 = Math.max(dot, mark);
        password = "{password.substring(0, pos1)}{arg}{password.substring(pos2)}";
        super.replaceSelection(getStars(arg.length()));
    }

    override function deleteNextChar() {
        if ((mark == dot) and (dot < password.length())) {
            password = "{password.substring(0, dot)}{password.substring(dot + 1)}";
        }
        super.deleteNextChar();
    }

    override function deletePreviousChar() {
        if ((mark == dot) and (dot > 0)) {
            password = "{password.substring(0, dot - 1)}{password.substring(dot)}";
        }
        super.deletePreviousChar();
    }

    function getStars(len: Integer): String {
        var result: String = "";
        for (i in [1..len]) {
            result = "{result}*";
        }
        result;
    }
}

Quite simple, isn’t it? Here is how it is used in the Main class:

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;

var password: PasswordBox;

var stage: Stage = Stage {
    title: "PasswordBox Demo"
    width: 200
    height: 100
    scene: Scene {
        content: [
            password = PasswordBox {
                translateX: 10
                translateY: 10
                columns: 20
            },
            Text {
                x: 10
                y: 50
                content: bind password.password
            }
        ]
    }
}

I guess there is still a room for improving the API – the real password is stored in the password property, while the text property became useless and should never be set by a client. If you want to populate the field with a remembered password, you need to do it by calling replaceSelection("password") on the password field after it’s initialization (rather than setting the text or the password properties). Anyway, I wanted to keep the code simple so that you can easily see the basic idea behind it.

More Struggling with JavaFX

September 9th, 2009 by Martin 4 comments »

In my first blog on JavaFX I mentioned polishing the details takes a lot of time and I thought it is due to the lack of experience. As I am spending more time trying to develop a real-life desktop application, I am becoming more doubtful about this. Too often I have to spend too much time trying to make the UI behave the way I want and sometimes I just have to give up and change my mind about the desired design to avoid wasting even more time. It is hard to provide concrete examples and ask for help as my application’s UI is quite complex. But recently I could isolate a simple case that I can use to demonstrate what I am talking about.
Look at the following simple code:

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;

var rec1: Rectangle;
var stage: Stage = Stage {
    title: "Rectangles"
    width: 200
    height: 200
    scene: Scene {
        content: [
            VBox {
                spacing: 0
                content: [
                    rec1 = Rectangle {
                        fill: Color.BLACK
                        width: bind stage.scene.width
                        height: 50
                    }
                    Rectangle {
                        fill: Color.GRAY
                        width: bind stage.scene.width
                        height: bind stage.scene.height - rec1.height
                    }
                ]
            }
        ]
    }
}

It creates a window containing two rectangles that fully cover the scene:
Rectangles screenshot
All works great at this point.
Now, let’s see what happens when I set the stroke to Color.BLACK:

                    Rectangle {
                        fill: Color.GRAY
                        stroke: Color.BLACK
                        width: bind stage.scene.width
                        height: bind stage.scene.height - rec1.height
                    }

Running this I am getting the following result:
Rectangles screenshot
As you can see, besides the fact that the rectangle now has the black border, it also jumped both horizontally and vertically and uncovered a strip of white background color. Going back and forth trying to find a workaround can be time consuming – I did not find a good way of debugging this kind of issues. Now imagine the same thing happens when the UI contains many more nested components. Trying to figure out which one causes the problem and how to tweak things to get the desired result may be endless.
Anyway, I am still not giving up! Has anyone found an efficient way of debugging and resolving this type of issues quickly?

Implementing a Scroll View in JavaFX

August 30th, 2009 by Martin 6 comments »

JavaFX does not seem to have support for scroll views. So, you have to
implement it on your own. Here is how I started implementing my own scroll view supporting
vertical scrolling:

package scrollviewdemo;

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.util.Math;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Paint;

public class ScrollView extends CustomNode {
    public-init var node: Node;
    public var width: Float;
    public var height: Float;

    var group: Group;
    var gap = bind group.layoutBounds.height - height;

    def scrollBar: ScrollBar = ScrollBar {
        translateX: bind width - scrollBar.width
        min: 0
        max: bind Math.max(0, gap)
        visible: bind gap > 0
        vertical: true
        height: bind height
    }

    override function create() {
        Group {
            content: [
                Group {
                    content: [
                        group = Group {
                            translateY: bind - scrollBar.value
                            content: [node]
                        }
                    ]
                    clip: Rectangle {
                        width: bind width - {if (gap > 0) scrollBar.width else 0}
                        height: bind height
                    }
                },
                scrollBar
            ]
        }
    }
}

This is how it can be used in a simple application:

var stage: Stage = Stage {
    title: "Application title"
    width: 200
    height: 200
    scene: Scene {
        content: [
            ScrollView {
                width: bind stage.scene.width
                height: bind stage.scene.height
                node: VBox {
                    content: for (i in [0..20]) ImageView {
                        image: Image {
                            // some picture
                            url: "{__DIR__}pic.png"
                        }
                    }
                }
            }
        ]
    }
}

To support mouse scroll wheel I added the following to the ScrollView class:

    override var onMouseWheelMoved = function(event) {
        // multiplying by 4 makes the scrolling faster and still smooth
        scrollBar.value += event.wheelRotation * 4;
    }

However, as it turned out, transparent components don’t receive mouse events, so the mouse
wheel worked only when the mouse pointer was on top of a non-transparent object. So, to work
around this, I had to fill the scroll view background using an opaque rectangle. The resulting
ScrollView component looks like this:

package scrollviewdemo;

import javafx.scene.CustomNode;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.control.ScrollBar;
import javafx.util.Math;
import javafx.scene.shape.Rectangle;
import javafx.scene.paint.Paint;

public class ScrollView extends CustomNode {
    public-init var node: Node;
    public var width: Float;
    public var height: Float;
    public var fill: Paint;

    var group: Group;
    var gap = bind group.layoutBounds.height - height;

    def scrollBar: ScrollBar = ScrollBar {
        translateX: bind width - scrollBar.width
        min: 0
        max: bind Math.max(0, gap)
        visible: bind gap > 0
        vertical: true
        height: bind height
    }

    override function create() {
        Group {
            content: [
                Rectangle {
                    fill: bind fill
                    width: bind width - {if (gap > 0) scrollBar.width else 0}
                    height: bind height
                },
                Group {
                    content: [
                        group = Group {
                            translateY: bind - scrollBar.value
                            content: [node]
                        }
                    ]
                    clip: Rectangle {
                        width: bind width - {if (gap > 0) scrollBar.width else 0}
                        height: bind height
                    }
                },
                scrollBar
            ]
        }
    }

    override var onMouseWheelMoved = function(event) {
        // multiplying by 4 makes the scrolling faster and still smooth
        scrollBar.value += event.wheelRotation * 4;
    }
}

And the following line should be added to the Main.fx to make it work:

package scrollviewdemo;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;

var stage: Stage = Stage {
    title: "Application title"
    width: 200
    height: 200
    scene: Scene {
        content: [
            ScrollView {
                width: bind stage.scene.width
                height: bind stage.scene.height
                fill: Color.WHITE
                node: VBox {
                    content: for (i in [0..20]) ImageView {
                        image: Image {
                            // some picture
                            url: "{__DIR__}pic.png"
                        }
                    }
                }
            }
        ]
    }
}

Custom Asynchronous Tasks in JavaFX

August 26th, 2009 by Martin 2 comments »

As I mentioned in my previous blog, during my experiments with JavaFX I needed to run certain tasks on a separate thread (e.g. calls to a remote web service via Jersey Client API). One can do it in JavaFX using JavaTaskBase class, but I wanted something simpler, something similar to what FXexperience blog suggested. So, I created a custom subclass of javafx.async.Task named AsyncTask that allowed me to make asynchronous calls as follows:

    AsyncTask {
        run: function() {
            // add the code you want to run asynchronously
        }

        onDone: function() {
            // this is executed once the "run" method finishes running
        }
    }.start();

Here is the source code for the AsyncTask class together with the helper Java class it’s using. It should be self explanatory.

AsyncTask.fx
import javafx.async.Task;

public class AsyncTask extends Task, AsyncTaskHelper.Task {
    /** Function that should be run asynchronously.
     */
    public var run: function() = null;

    // the helper
    def peer = new AsyncTaskHelper(this);

    // used to start the task
    override function start() {
        started = true;
        if (onStart != null) onStart();
        peer.start();
    }

    // don't need stop - isn't implemented
    override function stop() {
        // do nothing
    }

    // called from the helper Java class from a different thread
    override function taskRun() {
        // run the code to be run asynchronously
        if (run != null) run();
        // send a notification (on the dispatch thread) the code finished running
        FX.deferAction(function() {
            done = true;
            if (onDone != null) onDone();
        });
    }
}
AsyncTaskHelper.java
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class AsyncTaskHelper implements Runnable {
    // Using a fixed threadpool to run the asynchronous task
    private static final ExecutorService QUEUE = Executors.newFixedThreadPool(10);
    // the "parent" JavaFX AsyncTask instance
    private final Task peer;

    public AsyncTaskHelper(Task peer) {
        this.peer = peer;
    }

    // called from AsyncTask.start() method - will add this task
    // to the thread pool queue
    public void start() {
        QUEUE.execute(this);
    }

    // called by the thread pool queue to start the task
    public void run() {
        peer.taskRun();
    }

    // interface to be implemented by the "parent" JavaFX AsyncTask
    public static interface Task {
        public void taskRun();
    }
}

My First Experience with JavaFX

August 21st, 2009 by Martin 3 comments »

A week ago I started to look into JavaFX, to see if I could use it for application development. Here is my experience so far…

Learning
Googling for some tutorials, I ended up taking the following two: Learning the JavaFX Script Programming Language and Building GUI Application with JavaFX. These were both extremely easy to follow and provided a good quick-start guide. Then I started reading a more complex one – Media Browser Tutorial, but since I was eager to start my own development and thought I could do it after those first two tutorials, I wasn’t patient enough to go through even the first module of this one. Although later I did download the source code to see how the tutorial deals with some more advanced stuff (like screen scrolling, which turns out to be more complicated than expected with JavaFX).

Development Tools
My IDE of choice is NetBeans – it has great features (…and version 6.7 looks awesome on my Mac). And it is the recommended IDE for JavaFX development – NetBeans 6.7 comes with support for JavaFX projects built in. Anyway, being used to the Java code development in NetBeans with all the bells and whistles like code hints, refactorings, etc., switching to JavaFX development felt like I am in hell. Missing support for fixing imports, broken indentation, closing bracket generation and code-completion being the most annoying things. So, be ready for the maturity of the tools not being there yet – which I guess is understandable given the level of maturity of the JavaFX platform itself.

Using JavaFX
I wanted to see if I could quickly put together an application built on top of a client library for working with on-line media (pictures, videos) I’d been working on. And the result was, I really could – I got the 80% of the initial functionality done within an hour. I did not care about the details, just wanted to get it done quickly and thought I would polish the details later – and it worked. So I was happy. Anyway, “polishing the details” took a huge amount of time and at times would make me think I would have done much better if I wrote it in Java right away. But, I got through it and now I am realizing it just takes more practice to be able to reduce the number of the painful trial and error cycles and get what I need in a reasonable time. So, I thought I would share a few things I ran into to make others prepared for some bumps and save them some time:

  • The most time-consuming thing was playing with the layout. The ability to bind property values to each other is nice. But in certain situations it does not work as expected when using it to lay out objects. Sometimes it causes StackOverflowExceptions and it is hard to see how to achieve what you need while avoiding these exceptions. Also understanding different coordinate properties of objects like x, y, translateX, translateY, layoutX, layoutY, boundsInLocal.minX/minY, boundsInParent.minX/minY takes time. So, I ended up spending a lot of energy on trying to make the components lay out properly (the tutorials usually use non-resizable main window, which makes the life much simpler), and basically the only approach that worked was trial and error – i.e. run the application, see it does not do what you need, think about what may fix it, make the change (usually wrap a few objects in another layout, or remove some grouping, etc.), run it again and see. Each of these cycles are made more painful by NetBeans, since wrapping objects in a group gets you into this broken indentation and closing bracket generation hell. I am hoping more experience will reduce the number of needed cycles (I think I can already see improvements). Given this it is also not good to try to make up your mind about the visual design of your app along the way – it is better to think it through well in advance as the cost of redoing it is too high. Again, this may improve with the amount of experience.
  • By default, the whole JavaFX program runs in one thread – the dispatch thread. For specific time-consuming operations, there is a support for running them asynchronously (e.g. for loading images from a URL you can set Image.backgroundLoading to true). Creating your own asynchronous operations is not very straightforward, but works as well – Baechul’s blog explains how. I found the FXexperience blog inspiring in that respect and wrote my own very simple implementation of an asynchronous task – will blog about it later.
  • No support for something like a scroll pane. What may look like a simple task – adding a scroll bar to your application – is not so simple with JavaFX – there is a ScrollBar control in the 1.2 version of the API, but looks like you have to place it yourself as well as implement the scrolling. I wrote a simple generic component to do this – will publish it in one of my next blogs.
  • No support for hiding passwords in text boxes. When you want your user to enter a password to a text box, it is currently impossible to have the text box show a sequence of “*” instead of the actual password. There are some suggested workarounds on the web here and here. But I did not figure out how to use the first one (is there such font with just a single glyph for all characters on all platforms?) and the second one did not work for me for some reason either. For now I am using the one suggested by Sten in his blog, but even that has issues (the password is almost readable and the box is blurred including its edges), so I am planning to spend some more time on it to see if I can come up with something better.
  • To make it possible for my application to access system resources when run from the browser (like the file system), I had to make it a “Self Signed Jar” by going into my project’s properties (in NetBeans) selecting “Application” category in the Project Properties dialog and making sure “Self Signed Jar” is checked.

Now, one may argue I could use the standard Swing components to work around some of the issues. The problem with that is that they look different from the JavaFX components, so e.g. combining the JavaFX text boxes with a Swing one would look ugly.

OK. That’s it for now. I’ll try to dive into some specific areas in my future blogs.