FX Experience Has Gone Read-Only

I've been maintaining FX Experience for a really long time now, and I love hearing from people who enjoy my weekly links roundup. One thing I've noticed recently is that maintaining two sites (FX Experience and JonathanGiles.net) takes more time than ideal, and splits the audience up. Therefore, FX Experience will become read-only for new blog posts, but weekly posts will continue to be published on JonathanGiles.net. If you follow @FXExperience on Twitter, I suggest you also follow @JonathanGiles. This is not the end - just a consolidation of my online presence to make my life a little easier!

tl;dr: Follow me on Twitter and check for the latest news on JonathanGiles.net.

Another link I found the other day to a blog posting by Vaibhav Choudhary on using the JavaFX 1.2 Charting APIs.
JavaFX Bubble Chart

He then followed up with a blog populating a chart from a web service call. The important pieces are the following code blocks. The first here is what generates the Pie Chart data slices after the web service call succeeded:

function generateChartData(tg:TagInformation, done:Boolean):PieChart.Data[] {
    for (i in [0..<sizeof tg.tag]) {
        PieChart.Data {
            action: function() {
                showShopping = true;
            }
            label: tg.tag[i]
            value: tg.tagCount[i]
        }
    }
}

This function generateChartData simply returns a sequence of PieChart.Data instances. “for loop” expressions in JavaFX yield a sequence, one item for each iteration of the loop. So the generated sequence will be one PieChart.Data for each result in the tg.tag sequence.

This next block of code uses the HttpRequest class to fetch and parse the RSS feed from Del.icio.us. The only thing here that I might have done differently, is to have used the RSS APIs introduced in JavaFX 1.2 rather than hand rolling my own parsing code and using HttpRequest. First the code from the blog doing it the “long” way:

public class TagInformation {
    public var tag: String[]=[];
    public var tagCount: Integer[]=[];
    public var username: String = "javafx";  // for this sample it's javafx
    public-read var done = false;
    var url = bind "http://feeds.delicious.com/v2/rss/tags/{username}?count=4";
    var p: PullParser;
    var h: HttpRequest;
    init {
            h = HttpRequest {
                location: url
                onException: function(exception: Exception) {
                    exception.printStackTrace();
                }
                onInput: function(input) {
                    p = PullParser {
                        input: input
                        onEvent: function(event) {
                            if ((event.type == PullParser.END_ELEMENT)) {
                                if (event.qname.name == "title" and
                                    event.level == 3) {
                                   insert event.text into tag;
                                }
                                if(event.qname.name == "description" and
                                    event.level == 3){
                                   insert Integer.parseInt(event.text)
                                   into tagCount;
                                }
                            }
                        }
                    };
                    p.parse();
                    p.input.close();
                }
                onDone: function() {
                    Main.showtag = false;
                    done = true;
                }
            };
            h.start();
        }
    }

And now here is how I would have done it using the JavaFX 1.2 APIs. In JavaFX 1.2 we released some ATOM and RSS support. These classes are in the javafx.data.feed package.

public class TagInformation {
    public var tag: String[]=[];
    public var tagCount: Integer[]=[];
    public var username: String = "javafx";  // for this sample it's javafx
    public-read var done = false;
    var url = bind "http://feeds.delicious.com/v2/rss/tags/{username}?count=4";
    init {
		RssTask {
	        location: "http://feeds.delicious.com/v2/rss/tags/javafx?count=4"
	        interval: 1h
	        onItem: function(item) {
	            insert item.title into tag;
	            insert Integer.parseInt(item.description) into tagCount;
	        }
	        onDone: function() { done = true }
	    }.start();
    }
}

The only thing here that I found somewhat irritating and will get put on the bug list for the next release is that you must specify an interval for the RssTask, even if you won’t be polling. Expect this to change to some reasonable polling value as the default. Maybe 1 hour (as in this example) isn’t a bad default. 1 minute is a bit more extreme, but for the feed-junkies out there maybe that’s a better default.

As you can see, the code is much simpler using the feed APIs. I guess that’s a good thing ;-). The RSS/ATOM feed APIs use the same basic programming model as HttpRequest — both extend from Task. Task’s have API for monitoring progress, canceling, starting, handling error condition, etc in a unified model. All asynchronous operations in JavaFX should extend from Task either directly or indirectly.