Skip to main content

Using an external library w/ JavaFX app

Posted by robogeek on December 4, 2008 at 5:27 PM PST

I've been toying with doing a blog or podcast aggregator with JavaFX. I have a feeling that the strengths of JavaFX, animation, graphics, media, etc, could be put to good use in such an app. Additionally most podcasters put little player widgets on their site, and JavaFX could offer an alternative to the flash based player widgets. While that's the vision I'm chasing I'm nowhere near there, just yet.

I wanted to demonstrate first a few core bits.

I have a fair bit of experience writing feed aggregators in Groovy using the ROME library so of course for this JavaFX based tool I again turned to ROME. Maybe all feeds lead to ROME?

Because JavaFX fits into the Java ecosystem this means your rich media whizzbang RIA app can directly make use of the full breadth of Java libraries which are out there. ROME being just one of them. Take that Flash. ;-)

Referencing the ROME library is done in the familiar way


import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.feed.synd.SyndEntryImpl;
import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndEnclosure;

Then to read in a feed into your program:-


var inputter : SyndFeedInput = new SyndFeedInput();
var theurl : URL = null;
var feed : SyndFeed = null;
...
public function setFeed(url : String) : Void {
setFeed(new URL(url));
}

public function setFeed(url : URL) : Void {
theurl = url;
feed = inputter.build(new XmlReader(theurl));
...
}

Other than the slightly different syntax this isn't terribly different than how code would be written in the Java version.

One unpleasant fact is that a) RSS/Atom feeds tend to contain HTML, b) JavaFX doesn't have a direct way to display HTML. There is a Text widget but it doesn't have a mode to display HTML. One could incorporate a Swing JTextArea configuring it for HTML but then the app would not be portable to a mobile device. Sooooo.... I suppose the last option is to strip out HTML codes before displaying it in the app. I haven't implemented this in my app yet as it's suboptimal but it's really the only choice.

The last thing I want to discuss here is a pragmatic about displaying the content of a feed. I'm still learning this language but the following appears to be the most convenient way of displaying the items in a feed in an app.


var items = Group {
content: bind
for (entry in feed.entries) {
Text {
x: 10
y: (indexof entry) * 20;
content: bind entry.title
}
}
}

Unfortunately the ROME SyndFeed object is not conveniently implemented this way and a little bit of conversion is required.

Given a suitable definition of an Entry object


public var entries : Entry[];

Then use this method for conversion


function setupEntries() : Void {
var list : Entry[];
var i : Integer = 0;
for (entryy in feed.getEntries()) {
var entry : SyndEntry = entryy as SyndEntry;
var newentry : Entry = Entry {
author: entry.getAuthor(),
link: entry.getLink(),
description: entry.getDescription().getValue(),
enclosures: convertEnclosureList(entry.getEnclosures()),
title: entry.getTitle(),
date: entry.getPublishedDate().toString(),
entry: entry
};
insert newentry into list;
}
entries = list;
}

function convertEnclosureList(list : List) : Enclosure[] {
var newlist : Enclosure[];
for (item in list) {
var encl : SyndEnclosure = item as SyndEnclosure;
insert Enclosure {
type: encl.getType(),
sURL: encl.getUrl(),
encl: encl
} into newlist;
}
return newlist;
}

Related Topics >>

Comments

David, remember to pay close attention to threading. All jfx scripts are run inside the EDT, this means that inputter.build(new XmlReader(theurl)) will be called inside the EDT (!!)