<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JavaFX News, Demos and Insight // FX Experience &#187; Web Services</title>
	<atom:link href="http://fxexperience.com/category/web-services/feed/" rel="self" type="application/rss+xml" />
	<link>http://fxexperience.com</link>
	<description>Sharing the Experience of JavaFX</description>
	<lastBuildDate>Fri, 03 Feb 2012 22:47:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Maps in JavaFX 2.0</title>
		<link>http://fxexperience.com/2011/05/maps-in-javafx-2-0/</link>
		<comments>http://fxexperience.com/2011/05/maps-in-javafx-2-0/#comments</comments>
		<pubDate>Wed, 01 Jun 2011 02:11:10 +0000</pubDate>
		<dc:creator>Jasper Potts</dc:creator>
				<category><![CDATA[Controls]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://fxexperience.com/?p=1170</guid>
		<description><![CDATA[Something that you see more and more with client applications at the moment is embedded map components. This blog will show you how to embed Google, Yahoo or Bing maps in your JavaFX application. Download a copy of the application and try it out. The jar file is linked below, just download it and double [...]]]></description>
			<content:encoded><![CDATA[<p>Something that you see more and more with client applications at the moment is embedded map components. This blog will show you how to embed Google, Yahoo or Bing maps in your JavaFX application.</p>
<div id="attachment_1171" class="wp-caption aligncenter" style="width: 610px"><a href="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.54.48-PM.png"><img class="size-full wp-image-1171 " title="Screen shot 2011-05-27 at 6.54.48 PM" src="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.54.48-PM.png" alt="" width="600" height="497" /></a><p class="wp-caption-text">Google Maps in JavaFX 2.0</p></div>
<p>Download a copy of the application and try it out. The jar file is linked below, just download it and double click. This requires you to have the JavaFX 2.0 beta runtime installed.</p>
<p style="color: #ff5400; text-align: center;"><strong><br />
<a href="http://fxexperience.com/applications/WebMap.jar"><img style="text-align: center; padding: 0; margin: 0;" src="http://fxexperience.com/applications/jar-icon.png" alt="" /><br />
Download double clickable jar</a></strong></p>
<p><span id="more-1170"></span></p>
<h3>Using the Application</h3>
<p>The toolbar at the top of the application is all JavaFX controls, it communicates with the web map by calling JavaScript functions. Clicking on the Road,Satellite, Hybrid or Terrain sends commands to the JavaScript map library to change the map style. The Google, Yahoo and Bing buttons change the HTML page to use different map providers. As you type in the location field it navigates to the location, try &#8220;London&#8221; or &#8220;New York&#8221; for example. The zoom in/out buttons call JavaScript functions to change the map zoom level.</p>
<div id="attachment_1185" class="wp-caption aligncenter" style="width: 610px"><a href="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.55.11-PM.png"><img class="size-full wp-image-1185" title="Yahoo Maps" src="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.55.11-PM.png" alt="" width="600" height="497" /></a><p class="wp-caption-text">Yahoo Maps in JavaFX 2.0</p></div>
<div id="attachment_1186" class="wp-caption aligncenter" style="width: 610px"><a href="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.55.19-PM.png"><img class="size-full wp-image-1186" title="Bing Maps" src="http://fxexperience.com/wp-content/uploads/2011/05/Screen-shot-2011-05-27-at-6.55.19-PM.png" alt="" width="600" height="497" /></a><p class="wp-caption-text">Bing Maps in JavaFX 2.0</p></div>
<h3>How it&#8217;s Built</h3>
<p>There are three parts to the application: the HTML and JavaScript code, the JavaFX application and the css styling.</p>
<h4>The HTML Code</h4>
<pre class="brush: xml; title: ; notranslate">
&lt;html&gt;
&lt;head&gt;
&lt;meta name=&quot;viewport&quot; content=&quot;initial-scale=1.0, user-scalable=no&quot; /&gt;
&lt;style type=&quot;text/css&quot;&gt;
  html { height: 100% }
  body { height: 100%; margin: 0px; padding: 0px }
  #map_canvas { height: 100%; background-color: #666970; }
&lt;/style&gt;
&lt;script type=&quot;text/javascript&quot; src=&quot;http://maps.google.com/maps/api/js?sensor=false&quot;&gt;
&lt;/script&gt;
&lt;script type=&quot;text/javascript&quot;&gt;
  function initialize() {
    var latlng = new google.maps.LatLng(37.39822, -121.9643936);
    var myOptions = {
      zoom: 14,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.ROADMAP,
      mapTypeControl: false,
      navigationControl: false,
      streetViewControl: false,
      backgroundColor: &quot;#666970&quot;
    };

    document.geocoder = new google.maps.Geocoder();
    document.map = new google.maps.Map(document.getElementById(&quot;map_canvas&quot;),myOptions);

    document.zoomIn = function zoomIn() {
    	var zoomLevel = document.map.getZoom();
    	if (zoomLevel &lt;= 20) document.map.setZoom(zoomLevel + 1);
    }

    document.zoomOut = function zoomOut() {
    	var zoomLevel = document.map.getZoom();
    	if (zoomLevel &gt; 0) document.map.setZoom(zoomLevel - 1);
    }

    document.setMapTypeRoad = function setMapTypeRoad() {
    	document.map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
    }
    document.setMapTypeSatellite = function setMapTypeSatellite() {
    	document.map.setMapTypeId(google.maps.MapTypeId.SATELLITE);
    }
    document.setMapTypeHybrid = function setMapTypeHybrid() {
    	document.map.setMapTypeId(google.maps.MapTypeId.HYBRID);
    }
    document.setMapTypeTerrain = function setMapTypeTerrain() {
    	document.map.setMapTypeId(google.maps.MapTypeId.TERRAIN);
    }

    document.goToLocation = function goToLocation(searchString) {
        document.geocoder.geocode( {'address': searchString}, function(results, status) {
      	  if (status == google.maps.GeocoderStatus.OK) {
            document.map.setCenter(results[0].geometry.location);
          } else {
            alert(&quot;Geocode was not successful for the following reason: &quot; + status);
          }
        });
    }
  }
&lt;/script&gt;
&lt;/head&gt;
&lt;body onload=&quot;initialize()&quot;&gt;
  &lt;div id=&quot;map_canvas&quot; style=&quot;width:100%; height:100%&quot;&gt;&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>This is the code for using Google Maps API, there is similar code for Yahoo and Bing in the attached Netbeans project below. This is very basic use of the Google Maps API to create a full page map and provide some constant JavaScript functions that the JavaFX application can call. You could have called the Google API directly from JavaFX but it seemed simpler to provide a basic abstraction layer in JavaScript so the only difference the JavaFX app sees is the URL. The other two APIs Yahoo and Bing require that you register to get a API key to be able to use them. The code is provided you just need to insert you API keys into the HTML files.</p>
<h4>The JavaFX Code</h4>
<p>The most basic application without the toolbar to just show the map would be:</p>
<pre class="brush: java; title: ; notranslate">
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;

public class WebMap extends Application {

    @Override public void start(Stage stage) {
        // create web engine and view
        final WebEngine webEngine = new WebEngine(getClass().getResource(&quot;googlemap.html&quot;).toString());
        final WebView webView = new WebView(webEngine);
        // create scene
        stage.setTitle(&quot;Web Map&quot;);
        Scene scene = new Scene(webView,1000,700, Color.web(&quot;#666970&quot;));
        stage.setScene(scene);
        // show stage
        stage.setVisible(true);
    }

    static { // use system proxy settings when standalone application
        System.setProperty(&quot;java.net.useSystemProxies&quot;, &quot;true&quot;);
    }

    public static void main(String[] args){
        Application.launch(args);
    }
}
</pre>
<p>The next step is to create the toolbar, this is just a bunch of JavaFX controls in a Toolbar with actions that call the JavaScript functions in the HTML page.</p>
<pre class="brush: java; title: ; notranslate">
import ....

public class WebMap extends Application {
    private Timeline locationUpdateTimeline;

    @Override public void start(Stage stage) {
        // create web engine and view
        final WebEngine webEngine = new WebEngine(
                getClass().getResource(&quot;googlemap.html&quot;).toString());
        final WebView webView = new WebView(webEngine);
        // create map type buttons
        final ToggleGroup mapTypeGroup = new ToggleGroup();
        final ToggleButton road = new ToggleButton(&quot;Road&quot;);
        road.setSelected(true);
        road.setToggleGroup(mapTypeGroup);
        final ToggleButton satellite = new ToggleButton(&quot;Satellite&quot;);
        satellite.setToggleGroup(mapTypeGroup);
        final ToggleButton hybrid = new ToggleButton(&quot;Hybrid&quot;);
        hybrid.setToggleGroup(mapTypeGroup);
        final ToggleButton terrain = new ToggleButton(&quot;Terrain&quot;);
        terrain.setToggleGroup(mapTypeGroup);
        mapTypeGroup.selectedToggleProperty().addListener(
                            new ChangeListener&lt;Toggle&gt;() {
            public void changed(
                    ObservableValue&lt;? extends Toggle&gt; observableValue,
                    Toggle toggle, Toggle toggle1) {
                if (road.isSelected()) {
                    webEngine.executeScript(&quot;document.setMapTypeRoad()&quot;);
                } else if (satellite.isSelected()) {
                    webEngine.executeScript(&quot;document.setMapTypeSatellite()&quot;);
                } else if (hybrid.isSelected()) {
                    webEngine.executeScript(&quot;document.setMapTypeHybrid()&quot;);
                } else if (terrain.isSelected()) {
                    webEngine.executeScript(&quot;document.setMapTypeTerrain()&quot;);
                }
            }
        });
        // add map source toggles
        ToggleGroup mapSourceGroup = new ToggleGroup();
        final ToggleButton google = new ToggleButton(&quot;Google&quot;);
        google.setSelected(true);
        google.setToggleGroup(mapSourceGroup);
        final ToggleButton yahoo = new ToggleButton(&quot;Yahoo&quot;);
        yahoo.setToggleGroup(mapSourceGroup);
        final ToggleButton bing = new ToggleButton(&quot;Bing&quot;);
        bing.setToggleGroup(mapSourceGroup);
        // listen to selected source
        mapSourceGroup.selectedToggleProperty().addListener(
                            new ChangeListener&lt;Toggle&gt;() {
            public void changed(
                    ObservableValue&lt;? extends Toggle&gt; observableValue,
                    Toggle toggle, Toggle toggle1) {
                terrain.setDisable(true);
                if (google.isSelected()) {
                    terrain.setDisable(false);
                    webEngine.load(
                          getClass().getResource(&quot;googlemap.html&quot;).toString());
                } else if (yahoo.isSelected()) {
                    webEngine.load(
                          getClass().getResource(&quot;bingmap.html&quot;).toString());
                } else if (bing.isSelected()) {
                    webEngine.load(
                          getClass().getResource(&quot;yahoomap.html&quot;).toString());
                }
                mapTypeGroup.selectToggle(road);
            }
        });
        // add search
        final TextBox searchBox = new TextBox(&quot;95054&quot;);
        searchBox.setColumns(12);
        searchBox.setPromptText(&quot;Search&quot;);
        searchBox.rawTextProperty().addListener(new ChangeListener&lt;String&gt;() {
            public void changed(
                    ObservableValue&lt;? extends String&gt; observableValue,
                    String s, String s1) {
                // delay location updates to we don't go too fast file typing
                if (locationUpdateTimeline!=null) locationUpdateTimeline.stop();
                locationUpdateTimeline = new Timeline();
                locationUpdateTimeline.getKeyFrames().add(
                    new KeyFrame(new Duration(400),
                            new EventHandler&lt;ActionEvent&gt;() {
                        public void handle(ActionEvent actionEvent) {
                            webEngine.executeScript(&quot;document.goToLocation(\&quot;&quot;+
                                    searchBox.getRawText()+&quot;\&quot;)&quot;);
                        }
                    })
                );
                locationUpdateTimeline.play();
            }
        });
        Button zoomIn = new Button(&quot;Zoom In&quot;);
        zoomIn.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
            public void handle(ActionEvent actionEvent) {
                webEngine.executeScript(&quot;document.zoomIn()&quot;);
            }
        });
        Button zoomOut = new Button(&quot;Zoom Out&quot;);
        zoomOut.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
            public void handle(ActionEvent actionEvent) {
                webEngine.executeScript(&quot;document.zoomOut()&quot;);
            }
        });
        // create toolbar
        ToolBar toolBar = new ToolBar();
        toolBar.getStyleClass().add(&quot;map-toolbar&quot;);
        toolBar.getItems().addAll(
                road, satellite, hybrid, terrain,
                createSpacer(),
                google, yahoo, bing,
                createSpacer(),
                new Label(&quot;Location:&quot;), searchBox, zoomIn, zoomOut);
        // create root
        BorderPane root = new BorderPane();
        root.getStyleClass().add(&quot;map&quot;);
        root.setCenter(webView);
        root.setTop(toolBar);
        // create scene
        stage.setTitle(&quot;Web Map&quot;);
        Scene scene = new Scene(root,1000,700, Color.web(&quot;#666970&quot;));
        stage.setScene(scene);
        scene.getStylesheets().add(&quot;/webmap/WebMap.css&quot;);
        // show stage
        stage.setVisible(true);
    }

    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    }

    static { // use system proxy settings when standalone application
        System.setProperty(&quot;java.net.useSystemProxies&quot;, &quot;true&quot;);
    }

    public static void main(String[] args){
        Application.launch(args);
    }
}
</pre>
<h4>The CSS Code</h4>
<p>The last part of the application is a little css to style the toolbar and make it look dark to stand out from the maps.</p>
<pre class="brush: css; title: ; notranslate">
.map{
    -fx-background-color: #666970;
}
.map-toolbar .button, .map-toolbar .toggle-button, .map-toolbar .label {
    -fx-text-fill: white;
    -fx-background-radius: 0;
}
.map-toolbar{
    -fx-base: #505359;
    -fx-background: #505359;
    -fx-shadow-highlight-color: transparent;
    -fx-spacing: 5;
    -fx-padding: 4 4 4 4;
    -fx-background-color: linear (0%,0%) to (0%,100%) stops
                (0%,#919398)
                (4%,#919398)
                (4.1%,#666970)
                (66%,#494d53)
                (94%,#3c3f46)
                (94.1%,#515151);
}
</pre>
<h3>Download Source</h3>
<p style="color: #ff5400; text-align: center;"><strong><br />
<a href="http://fxexperience.com/applications/WebMapProject.zip"><img style="text-align: center; padding: 0; margin: 0;" src="http://fxexperience.com/applications/project-zip.png" alt="" /><br />
Download Netbeans Project</a></strong></p>
]]></content:encoded>
			<wfw:commentRss>http://fxexperience.com/2011/05/maps-in-javafx-2-0/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Writing a Java-based Task</title>
		<link>http://fxexperience.com/2009/11/writing-a-java-based-task/</link>
		<comments>http://fxexperience.com/2009/11/writing-a-java-based-task/#comments</comments>
		<pubDate>Tue, 24 Nov 2009 15:12:04 +0000</pubDate>
		<dc:creator>Richard Bair</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://fxexperience.com/?p=236</guid>
		<description><![CDATA[In a post from earlier this year I explored the concept of background tasks in JavaFX. If you haven&#8217;t yet, you might want to review that article before reading on. For the impatient: JavaFX is currently a single threaded programming language. All code you write in JavaFX occurs on the same thread. Since you don&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>In a post from earlier this year I explored the concept of <a href="http://fxexperience.com/2009/06/background-tasks-in-javafx/">background tasks in JavaFX</a>. If you haven&#8217;t yet, you might want to review that article before reading on. For the impatient: JavaFX is currently a single threaded <em>programming language</em>. All code you write in JavaFX occurs on the same thread. Since you don&#8217;t want to write an unresponsive application, you need to write long-lived operations on a background thread. The <a href="http://java.sun.com/javafx/1.2/docs/api/javafx.async/javafx.async.Task.html">Task</a> API provides a single consistent abstraction which all background operations in JavaFX are based on. This means whether you are computing fibonacci sequences, breaking down protein chains, writing to a database or reading data from disk there is a single consistent programming model and API that your GUI communicates with. And we think this is a pretty good idea.<span id="more-236"></span></p>
<div class="sidenote">
<div class="title">RunnableFuture Bug in FX 1.2</div>
<hr />
    JavaFX Script has to compile on desktop, mobile, and tv platforms. This puts some constraints on what Java API we can use for the core JavaFX platform.<br />
    <br/>The real RunnableFuture class in the java concurrent utils is one of these classes that we couldn&#8217;t use because it wasn&#8217;t available on all platforms, yet. So we wanted to use essentially the same interface, but needed to put it into the javafx namespace.<br />
    <br/>That is why we added a RunnableFuture interface to the javafx.async package. However, somehow along the way it got whacked and ended up looking just like Runnable. Doh! This will be fixed in the next release.
    </div>
<p>
Because each background task is encapsulated in a Task subclass of some kind, it also provides a convenient programming model for third party developers to build libraries of background tasks. For example, I expect third party libraries like <a href="http://jfxtras.org/">jfxtras</a> will probably provide several reusable tasks such as for reading lines of text from files, saving data to disk, executing SQL queries, or other such operations. You will likely want to create your own set of such background tasks as you commonly encounter to keep handy in your own toolbox.</p>
<p>
Because we require all background work to be done in a background Java thread, we have provided a helper class called JavaTaskBase from which you should extend to create custom background tasks. Unfortunately we made one small (and rather embarrassing) error in the 1.2 release which, while it will not impact your code much when you upgrade to 1.3, you should be aware of (see sidebar for details). We would also like to make the JavaTaskBase more convenient for you to use, although what we have currently I found rather quite friendly and helped me write threaded code rather cleanly.</p>
<h2>JavaTaskBase</h2>
<p>The Task class contains many different lifecycle variables, events, and functions. When you create a JavaTaskBase subclass, you get all of this for free. Your main responsibility is simply to define the parameters to the background thread, the results of the background computation, and the Java implementation that will carry out the work on the background thread.</p>
<p>
<b>Step 1: Define the input parameters</b><br/><br />
Let&#8217;s take as our example a simple Task implementation which reads the contents of a File from the file system and returns the entire contents as a single String. What would we need to define as the input parameters? For the simple case, it is probably sufficient to simply provide a path to the file as the input parameter. For the sake of this example, we&#8217;ll assume that this Task accesses the local filesystem only.</p>
<pre class="brush: javafx; title: ; notranslate">
public class LocalFileReader extends JavaTaskBase {
    public-init var path:String;
}
</pre>
<p>In the above code, we defined the path to the file as a <code>public-init var</code>. This means that it is a variable that can only be set by external code during init time &#8212; essentially rendering this variable immutable. This is an important key point about Tasks &#8212; they are designed to be used once and then thrown away, not reused. Create a new instance whenever you need to perform a new task.</p>
<p>
<b>Step 2: Define the results</b><br/><br />
Now that we have defined our input parameter, we should add to our class whatever output values, event handlers, or other API that the user would use during the course of this operation, or at its completion. In the case of our file reader, we are going to provide a single String variable which will contain the entire contents of the file as a single String. This is obviously a contrived example as it would only be useful with very small files, but should demonstrate many of the issues in building a basic Task implementation.</p>
<pre class="brush: javafx; title: ; notranslate">
public class LocalFileReader extends JavaTaskBase {
    public-init var path:String;

    /**
     * The contents of the file as a String. This is populated upon successful
     * completion of the background task.
     */
    public-read var contents:String;
}
</pre>
<p>The <code>contents</code> variable is defined as <code>public-read var</code>, meaning that it is publicly readable but not publicly settable. The LocalFileReader class itself can write to the variable (which is a good thing or it could never be set!), but no other code can.</p>
<p>
<b>Step 3: Define the Java implementation</b><br/><br />
We are now ready to write the Java implementation of the background task. To do this we simply need to create a Java class which implements <a href="…./RunnableFuture">RunnableFuture</a> (see sidebar for conversation). The Java implementation will generally also be an immutable object, and in our case, that is exactly what we are going to do.</p>
<pre class="brush: java; title: ; notranslate">
public class LocalFileReaderImpl implements RunnableFuture {
    /** The path to the file to read */
    private String path;
    /** The buffer to contain the contents of the file */
    private StringBuffer contents;

    public LocalFileReaderImpl(String path) {
        this.path = path;
        this.contents = new StringBuffer();
    }

    /**
     * All code executed in the run() method is done so on a background thread
     * and can happily take as long as it likes. Exceptions that occur will be
     * passed along to users of your Task for you
     */
    public void run() throws Exception {
        FileInputStream in = new FileInputStream(path);
        try {
            BufferedInputStream bin = new BufferedInputStream(in);
            String line = null;
            while ((line = bin.readLine()) != null) {
                contents.append(line);
                contents.append(&quot;\n&quot;);
            }
        } finally {
            try { in.close(); } catch (Exception e) { }
        }
    }
}
</pre>
<p>The <code>run</code> method executes on the background thread. JavaFX will make sure this happens, reusing threads in a thread pool and so forth. For advanced users, if you absolutely must manage your own thread pools or concurrency on a very fine-grained level, you will probably want to create your own JavaTaskBase equivalent which extends directly from Task.</p>
<p>
At the conclusion of the <code>run</code> method, the contents buffer has been completely populated with the file contents and the input stream has been closed. Now we must add a single method to our LocalFileReader which will create and return the LocalFileReaderImpl so that JavaFX knows what Java code to call when it comes time to call it on a background thread.</p>
<pre class="brush: javafx; title: ; notranslate">
public class LocalFileReader extends JavaTaskBase {
    //.… other code goes here as defined in the previous examples ….

    /** save a reference to this, we'll need it later */
    var impl:LocalFileReaderImpl;

    /**
     * Create and return an instance of the imp class. This is called
     * when the task is started.
     */
    override function create() { impl = new LocalFileReaderImpl(path) }
}
</pre>
<p>We now have created our Task and its Java implementation. However there is one big problem remaining, which is that when the task completes, our LocalFileReader has no way of knowing that this has occurred. We will add some convenience API to JavaTaskBase to make this a bit easier, but for the moment we can solve the problem by simply introducing a callback interface. Our LocalFileReader will implement this interface and the LocalFileReaderImpl will invoke the &#8220;finished&#8221; function of this interface when the background task completes. The LocalFileReader can then read the finished contents buffer from the impl class and set its own <code>contents</code> variable with the final result. The complete source code for this example is found below.</p>
<pre class="brush: java; title: ; notranslate">
public interface FinishedHandler {
    public void finished();
}
</pre>
<p>Now have LocalFileReader implement this interface and pass a reference of &#8220;this&#8221; down to the imp:</p>
<pre class="brush: javafx; title: ; notranslate">
public class LocalFileReader extends JavaTaskBase, FinishedHandler {
    /** A path to a file on the local file system */
    public-init var path:String;

    /**
     * The contents of the file as a String. This is populated upon successful
     * completion of the background task.
     */
    public-read var contents:String;

    /** save a reference to this, we'll need it later */
    var impl:LocalFileReaderImpl;

    /**
     * Create and return an instance of the imp class. This is called
     * when the task is started.
     */
    override function create() { impl = new LocalFileReaderImpl(this, path) }

    /**
     * This is called by the imp while still on the background thread so our
     * very first responsibility is to call FX.deferAction, which will execute the
     * supplied anonymous function on the FX event thread
     */
    override function finished() {
        FX.deferAction(function() {
            contents = impl.contents.toString();
        });
    }
}
</pre>
<pre class="brush: java; title: ; notranslate">
public class LocalFileReaderImpl implements RunnableFuture {
    /** The handler to call when we have finished reading from the file */
    private FinishedHandler handler;
    /** The path to the file to read */
    private String path;
    /** The buffer to contain the contents of the file */
    private StringBuffer contents;

    public LocalFileReaderImpl(FinishedHandler handler, String path) {
        this.handler = handler;
        this.path = path;
        this.contents = new StringBuffer();
    }

    /**
     * All code executed in the run() method is done so on a background thread
     * and can happily take as long as it likes. Exceptions that occur will be
     * passed along to users of your Task for you
     */
    public void run() throws Exception {
        FileInputStream in = new FileInputStream(path);
        try {
            BufferedInputStream bin = new BufferedInputStream(in);
            String line = null;
            while ((line = bin.readLine()) != null) {
                contents.append(line);
                contents.append(&quot;\n&quot;);
            }
            handler.finished();
        } finally {
            try { in.close(); } catch (Exception e) { }
        }
    }
}
</pre>
<p>There are loads of variations that you can make as suits your task. For example, you could establish a long running background task with job queues, callbacks, and more complicated state management (extra bonus props for the first person to implement a Python or Ruby like file read operation conveniently in FX). You can execute database calls or web service calls or other such long running tasks.</p>
<p> In the future we will add more convenience variables to JavaTaskBase, and maybe provide an implementation base class as well to help ease things. For example it would be nice to do away with the custom FinishedHandler and instead to have  JavaTaskBase automatically realize when a task has finished and invoke an overridden function in the sub class that does the synchronization. In the future we hope to add threading support tightly into the language itself which will make a lot of this easier. While there are a number of steps involved, there is not much code involved and it is fairly straightforward &#8212; as far as threading code goes that is!</p>
]]></content:encoded>
			<wfw:commentRss>http://fxexperience.com/2009/11/writing-a-java-based-task/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Enterprising JavaFX @ #devoxx</title>
		<link>http://fxexperience.com/2009/11/enterprising-javafx-devoxx/</link>
		<comments>http://fxexperience.com/2009/11/enterprising-javafx-devoxx/#comments</comments>
		<pubDate>Wed, 18 Nov 2009 12:16:50 +0000</pubDate>
		<dc:creator>Richard Bair</dc:creator>
				<category><![CDATA[Controls]]></category>
		<category><![CDATA[Devoxx]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://fxexperience.com/?p=210</guid>
		<description><![CDATA[In a couple hours Jasper and I will be presenting a talk titled &#8220;Enterprising JavaFX&#8221; at Devoxx. The main purpose of the talk is to describe how to use JavaFX for writing enterprise application content. Here&#8217;s a quick teaser screenshot of one of the apps we&#8217;re going to describe: We&#8217;ll be writing some additional blog [...]]]></description>
			<content:encoded><![CDATA[<p>In a couple hours Jasper and I will be presenting a talk titled &#8220;Enterprising JavaFX&#8221; at Devoxx. The main purpose of the talk is to describe how to use JavaFX for writing enterprise application content. Here&#8217;s a quick teaser screenshot of one of the apps we&#8217;re going to describe:</p>
<div id="attachment_211" class="wp-caption aligncenter" style="width: 310px"><a href="http://fxexperience.com/wp-content/uploads/2009/11/Dashboard.png"><img src="http://fxexperience.com/wp-content/uploads/2009/11/Dashboard-300x222.png" alt="Jira Dashboard Application" title="Dashboard" width="300" height="222" class="size-medium wp-image-211" /></a><p class="wp-caption-text">Jira Dashboard Application</p></div>
<p>We&#8217;ll be writing some additional blog posts over the next few weeks describing various tips n&#8217; tricks as to how we used web services in this app, how we wrote the custom list cells, and so forth.</p>
]]></content:encoded>
			<wfw:commentRss>http://fxexperience.com/2009/11/enterprising-javafx-devoxx/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Background Tasks in JavaFX</title>
		<link>http://fxexperience.com/2009/06/background-tasks-in-javafx/</link>
		<comments>http://fxexperience.com/2009/06/background-tasks-in-javafx/#comments</comments>
		<pubDate>Mon, 22 Jun 2009 15:01:32 +0000</pubDate>
		<dc:creator>Richard Bair</dc:creator>
				<category><![CDATA[API Design]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://fxexperience.com/?p=116</guid>
		<description><![CDATA[While on vacation I&#8217;ve been watching twitter to see what kinds of things people are doing with JavaFX. One thing I&#8217;ve seen a fair amount of tweets on that is pretty gratifying is tying JavaFX to backend data services. One project is a port of Cairngorm from Flex to Java/JavaFX. Another was an earlier demo [...]]]></description>
			<content:encoded><![CDATA[<p>While on vacation I&#8217;ve been watching twitter to see what kinds of things people are doing with JavaFX. One thing I&#8217;ve seen a fair amount of tweets on that is pretty gratifying is tying JavaFX to backend data services. One project is a port of <a href="http://code.google.com/p/cairngorm-fx">Cairngorm from Flex to Java/JavaFX</a>. Another was an <a href="http://hessian.caucho.com/ria/">earlier demo based on Hessian</a> (which needs to be ported to JavaFX 1.2). Another was about integrating <a href="http://exadel.com/web/portal/flamingo">Flamingo</a> to JavaFX.</p>
<p><span id="more-116"></span>It&#8217;s great to see a lot of people starting to play with this part of the JavaFX space because we haven&#8217;t really given much guidance to it yet. We do have some great web service APIs as a starting point (basic HTTP with HttpRequest, RSS and ATOM feed support), but haven&#8217;t so far given any guidance as to writing an end to end app. I wanted to take just a moment and outline how we designed the Task API and how it ought to be used by third parties when creating background tasks or services, including communicating with a server.</p>
<p>I also wanted to give a shout out to <a href="http://blogs.sun.com/baechul/">an excellent blog by my colleague Baechul</a> who has been writing some very detailed and well written articles on JavaFX. Of particular interest to this post is one he wrote on <a href="http://blogs.sun.com/baechul/entry/javafx_1_2_async">JavaFX 1.2 Async</a>.</p>
<p>The Task class in the javafx.async represents the basic programming model for all asynchronous tasks in JavaFX and should form the base class for all such background Tasks. Its design was heavily influenced by the excellent work of Hans Muller on the Swing Application Framework. All JavaFX Tasks have the notion of &#8220;state&#8221; and &#8220;progress&#8221;. The state of the Task is expressed though a series of public API members:</p>
<ul>
<li>started:Boolean</li>
<li>stopped:Boolean</li>
<li>failed:Boolean</li>
<li>succeeded:Boolean</li>
<li>done:Boolean</li>
</ul>
<p>We chose to break these states out into Boolean properties rather than have a single property with an enum for two reasons. First, it makes it a little cleaner in the onDone event handler to find out what state the Task ended up in, especially when checking for several states. Second, this allows you to bind to the state of the Task from an external class using some rather clean code. For example, suppose you had a progress indicator and error icon and wanted to make it so that if the task failed, the error icon would be made visible, otherwise the progress indicator would be visible and display progress appropriately.</p>
<pre class="brush: javafx; title: ; notranslate">
Group {
    content: [
        ProgressIndicator {
            visible: bind task.started and not task.failed and not task.stopped
            progress: bind task.percentDone
        }
        ErrorIndicator { // this class doesn't exist, but you could write a CustomNode
            visible: bind task.started and task.failed
            causeOfFailure: bind task.causeOfFailure
        }
    ]
}
</pre>
<p>You&#8217;ll notice in this code block I&#8217;m also taking advantage of another really nice feature of Task and ProgressIndicator. A ProgressIndicator has a <code>progress</code> property which, if -1, means it is indeterminate but if between 0 and 1 then it indicates the percent done. Task also has a similar property called <code>percentDone</code> where, if -1, it means that the progress of the Task is also indeterminate. This makes binding a ProgressIndicator to a Task very clean. Simply bind like this: <code>ProgressIndicator { progress: bind task.percentDone }</code> and the rest works exactly like it should (switching between determinate and indeterminate mode automatically).</p>
<p>There are several API members for tasks for tracking progress:</p>
<ul>
<li>progress</li>
<li>maxProgress</li>
<li>percentDone</li>
</ul>
<p>To help explain these properties lets imagine that our Task was to read a file from disk. In this case, <code>progress</code> could be used to indicate the number of bytes read from disk. <code>maxProgress</code> would indicate the size of the file in bytes, and <code>percentDone</code> would be automatically calculated based on <code>progress</code> and <code>maxProgress</code>. In this way, you can create a UI which will track not only the percent done, but also the discrete amount of work to be done, and how much has been done.</p>
<p>Another simple example would be computing prime numbers. Suppose your app wanted to compute the first 5 prime numbers. In this case, <code>maxProgress</code> would be 5, and <code>progress</code> would be incremented each time a prime number is computed.</p>
<p>Finally, there are two event handlers that all Tasks share: <code>onStart</code> and <code>onDone</code>. <code>onStart</code> is called whenever the Task&#8217;s <code>start()</code> method is called, <em>not</em> when the background task is actually started. For example, your Task implementation might push work onto a worker queue. In this case, <code>onStart</code> should be called immediately after <code>start()</code> is invoked, not when the actual background worker that was pushed on the queue starts working.</p>
<p>The <code>onDone</code> function is called whenever the task stops, for any reason. If the task was cancelled manually, or if there was a failure, or if the task completed successfully. In all these cases onDone will be called. I&#8217;d like to add &#8220;onSuccess&#8221; and &#8220;onFailure&#8221; and &#8220;onStopped&#8221; events in the future. It is the developer&#8217;s responsibility in onDone to check the state of the Task to determine whether the task succeeded or failed or was stopped by checking the state booleans of the Task.</p>
<p>All background operations in JavaFX should extend from Task. This design gives application developers a single common programming model to use with all background operations developed by the JavaFX team or by third party developers. HttpRequest was refactored to be a Task in 1.2 (hence the reason for some of the API changes between 1.1 and 1.2).</p>
<p>There is one major caveat that I need to make clear. As of JavaFX 1.2, JavaFX Script is <strong>single threaded</strong>. <em>All</em> background work <strong>must</strong> be done in Java code. The <code>JavaTaskBase</code> abstract class is the base class intended to be used by all background threading implementations in JavaFX 1.2. Unfortunately, the hookup between <code>JavaTaskBase</code> and <code>RunnableFuture</code> didn&#8217;t come out right in 1.2 and you&#8217;re left with very little guidance as to how to do this appropriately.</p>
<p>The key thing is to understand that <strong>nothing should touch JavaFX variables from a background thread</strong>. So the idiom to use is to have the JavaTaskBase subclass to have a Java language peer which does the background work. The JavaTaskBase subclass would register a listener on the peer, and the peer would communicate back to the JavaTaskBase through that listener interface. The JavaTaskBase subclass would then pump events from the peer back onto the JavaFX thread (i.e. event thread) using FX.deferAction.</p>
<p>That&#8217;s a whole other blog entry though. For starters, I suggest reading <a href="http://blogs.sun.com/baechul/entry/javafx_1_2_async">Baechul&#8217;s take on it</a>.</p>
<p>There is one last thing I wanted to mention, which is a futures item which Brian Goetz and I have been bouncing around a bit. It&#8217;s completely pie-in-the-sky at this point, take it with a grain of salt, etc etc. Having to write background tasks in Java is a pain at the moment primarily because you cannot create JavaFX objects in a background thread. Also, it involves writing a messaging interface, a Java class, and a JavaTaskBase subclass. What I&#8217;d like to see is something like this:</p>
<pre class="brush: javafx; title: ; notranslate">
var task = BackgroundTask {
    run: function() {
        // code in this function runs in a background thread
        defer(function() {
            // code in this function runs on the JavaFX thread
        });
    }
}
</pre>
<p>The kicker is, the compiler would check and enforce that you don&#8217;t illegally modify application state from the background thread, but that you can when using &#8220;defer&#8221; or &#8220;deferAction&#8221;. The thing that gets me all excited about the idea is that we don&#8217;t have to expose a full threading model (with synchronicity, concurrent collections, memory barriers, semaphores, or anything else), but can instead simplify the problem by having a much more limited coarse grained approach of &#8220;this body of work happens in some background thread&#8221;. If you want or need to have a full threading model, then we still make that available by writing a JavaTaskBase subclass, but for the vast majority of uses, you could just use the simplified BackgroundTask model.</p>
]]></content:encoded>
			<wfw:commentRss>http://fxexperience.com/2009/06/background-tasks-in-javafx/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Vaibhav: Charts and RSS</title>
		<link>http://fxexperience.com/2009/06/vaibhav-charts-and-rss/</link>
		<comments>http://fxexperience.com/2009/06/vaibhav-charts-and-rss/#comments</comments>
		<pubDate>Wed, 10 Jun 2009 16:05:57 +0000</pubDate>
		<dc:creator>Richard Bair</dc:creator>
				<category><![CDATA[API Design]]></category>
		<category><![CDATA[Charts]]></category>
		<category><![CDATA[Web Services]]></category>

		<guid isPermaLink="false">http://fxexperience.com/?p=82</guid>
		<description><![CDATA[Another link I found the other day to a blog posting by Vaibhav Choudhary on using the JavaFX 1.2 Charting APIs. 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 [...]]]></description>
			<content:encoded><![CDATA[<p>Another link I found the other day to a blog posting by Vaibhav Choudhary on <a href="http://jfxstudio.wordpress.com/2009/06/05/javafx-1-2-chart-apis/">using the JavaFX 1.2 Charting APIs</a>.<br />
<img src="http://blogs.sun.com/vaibhav/resource/bubblechart.PNG" alt="JavaFX Bubble Chart" /></p>
<p><span id="more-82"></span>He then <a href="http://jfxstudio.wordpress.com/2009/06/08/chart-api-with-del-icio-us-web-service/">followed up with a blog populating a chart from a web service call</a>. 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:</p>
<pre class="jfx:nogutter">function generateChartData(tg:TagInformation, done:Boolean):PieChart.Data[] {
    for (i in [0..&lt;sizeof tg.tag]) {
        PieChart.Data {
            action: function() {
                showShopping = true;
            }
            label: tg.tag[i]
            value: tg.tagCount[i]
        }
    }
}</pre>
<p>This function <code>generateChartData</code> simply returns a sequence of PieChart.Data instances. &#8220;for loop&#8221; 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.</p>
<p>This next block of code uses the <code>HttpRequest</code> 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 &#8220;long&#8221; way:</p>
<pre class="jfx:nogutter">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();
        }
    }</pre>
<p>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.</p>
<pre class="jfx:nogutter">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();
    }
}</pre>
<p>The only thing here that I found somewhat irritating and will get put on the bug list for the next release is that you <em>must</em> specify an interval for the RssTask, even if you won&#8217;t be polling. Expect this to change to some reasonable polling value as the default. Maybe 1 hour (as in this example) isn&#8217;t a bad default. 1 minute is a bit more extreme, but for the feed-junkies out there maybe that&#8217;s a better default.</p>
<p>As you can see, the code is much simpler using the feed APIs. I guess that&#8217;s a good thing <img src='http://fxexperience.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> . The RSS/ATOM feed APIs use the same basic programming model as HttpRequest &#8212; both extend from Task. Task&#8217;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.</p>
]]></content:encoded>
			<wfw:commentRss>http://fxexperience.com/2009/06/vaibhav-charts-and-rss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

