• Nov
    • 27
    • 2011

JFX Flow early access

Posted by In Uncategorized

This entry is part 7 of 15 in the series Building JEE applications in JavaFX 2.0

I started this blog a few weeks ago with the grand plan of stepping you through the process of building a clean architecture for building JEE, web-style GUI applications using JavaFX 2. As I wrote the first few blogs, I realised that if we stepped through each little twist and turn on the journey to a complete framework we’d be here for a few years. I also started to think that most of you probably don’t care about the details, you just want something that you can use so you can get on with the real job of building your applications and making your users happy.

So, “here’s one I prepared earlier”. The more attentive of you will have already noticed a new new link called ‘JFX Flow‘ in the menu bar above. Go on, click on it. In fact, have a flick through the ‘showcase’ linked to from the main page just to get a feel for what I’m talking about here.

This is an alpha version of a framework I’ve put together with all of my ideas in it for building web-style applications in JavaFX. I’m still fleshing out the documentation (yea, I leave the least fun stuff till last too) The core features are good enough to use right now (I’m using it in two of my projects currently, one which is a decent way along), however some of the supporting features (such as dialogs) are still a little rough around the edges and I can’t guarantee the API for some of these won’t change a little over the next few weeks.

It’s all free and open source. I’ve also tried as much as possible to make it so that you guys can customise bits and pieces without having to rewrite everything. If you want your own funky Browser that’s all in 3D and has flying magical dragons on it, you can write one (assuming you know how to use the javafx.magical.dragon package) and just plug it in.

I’ve deliberately limited JFX Flow to the GUI aspects of a JEE system. It’s goal is to allow you to build GUIs that provide the user with a familiar and enjoyable experience, and at a code level support dependency injection, have nice threading and error handling, and use a clean separation of concerns (view vs control, etc).

You won’t see anything in there specifically for database or server communication however. JFX Flow provides the ‘presentation’ tier only. It has ways to integrate with the back-end tiers but it does not give you an end-to-end JEE stack. JEE is at its best when it provides the developer with the freedom to mix and match technologies at each level of the stack. Specific projects always have their own specific requirements. Sometimes you need to use message queues and XML, sometimes you can make pure-Java RPC calls and can use Hibernate, and sometimes you might have to integrate with something weird like Google’s App Engine, or a legacy mainframe system. JFX Flow aims to give you that power, while making the front-end a bit easier to develop.

I’m guessing a lot of you probably still want to know how to do all that database and server communication stuff though. That’s what the rest of this blog will be about. Now that we’ve got a JavaFX presentation layer for our JEE stack, we can start looking at how this can be used for common scenarios. Those of you already familiar with the business and data layers of the JEE stack can go on ahead, JFX Flow is ready for you to use. The rest of you, stick with me and let’s see what we can come up with. For now have a play with JFX Flow and let me know what you like, and don’t like.

Continue Reading→
    • Nov
    • 14
    • 2011

File Downloading in JavaFX 2.0 (over HTTP)

Posted by In Uncategorized

I had to implement a File Download service for something I’m working on this week and thought I’d share.

File downloading is pretty easy these days if we use something like Apache’s HttpComponents. This can do all sorts of stuff, like proxy-support, retry-on-error and HTTP Basic Authentication. I won’t go into too much detail on this as we only need the basics here, but you can find a lot of good information about it on the web (check out their tutorial for a good starting point).

The trick to getting it working in JavaFX is the threading. Downloading a file is obviously a slow operation, the kind of thing we want to do on a background thread so we’re not blocking our GUI. Using JavaFX’s threading Worker framework we can create a fairly nifty little re-usable class for this sort of Downloading.

Have a look at the full source code for the FileDownloadTask first. As you can see, the main work happens in the ‘call’ method, so we’ll step through that in detail.

First we open a connection to our download URL. Using HttpClient this is ridiculously easy:

HttpGet httpGet = new HttpGet(this.remoteUrl);
HttpResponse response = httpClient.execute(httpGet);

There are a number of different ways we could access our response, we could get the whole thing as a String or a byte array for example, but for downloading files we want to use streams. This is as easy as:

InputStream remoteContentStream = response.getEntity().getContent();

Now we have our stream, we can use simple Java streaming to copy from our remote stream to a local file stream, but since we’re JavaFX programmers and we want to make nice, friendly GUIs for our users were going to add some support for tracking how much of the file we’ve downloaded and how much we have left to do.

First, we find out just how big our file is, using this command:

long fileSize = response.getEntity().getContentLength();

Now we can create our local file and get it ready for writing to:

File dir = localFile.getParentFile();
dir.mkdirs();
localFileStream = new FileOutputStream(localFile);

We’ll use a buffer to read chunks of data from the remote fiel and push this into our local file, as we go we’ll keep track of how many bytes we’ve downloaded:

int sizeOfChunk;
int amountComplete = 0;
while ((sizeOfChunk = remoteContentStream.read(buffer)) != -1)
{
    localFileStream.write(buffer, 0, sizeOfChunk);
    amountComplete += sizeOfChunk;
    updateProgress(amountComplete, fileSize);
}

Notice, the call to ‘updateProgress’, this is a method provided by Task that allows us to update the ‘progress; property of our task in a thread safe way. UI Controls (such as the ProgressBar) can bind to this property to monitor the progress of the download without having to do any special thread handling on their end.

That’s more or less all there is to it from the service perspective, to use this service anywhere in your code you just do the following:

FileDownloadTask fileDownloadTask = new FileDownloadTask("http://www.tagg.org/pdftest.pdf", "c:/temp/downloaded.pdf");

Generally, when you use this class there are a few tips and tricks that can be helpful.

If you want the user to choose where the download should be saved, you can use JavaFx’s FileChooser like so:

String remoteUrl = "http://media.beyondzeroemissions.org/ZCA2020_Stationary_Energy_Report_v1.pdf";
FileChooser chooser = new FileChooser();
File file = chooser.showSaveDialog(stage);
if (file != null)
{
    FileDownloadTask fileDownloadTask = new FileDownloadTask(remoteUrl, file);
    new Thread(fileDownloadTask).start();
}

To create a Progress Bar and have it display the progress of your download do the following:

ProgressBar progressBar = new ProgressBar();
progressBar.progressProperty().bind(fileDownloadTask.progressProperty());
progressBar.visibleProperty().bind(fileDownloadTask.runningProperty()); // optionally hide the progress bar when not loading

To create a launch button that is only enabled when the file is successfully download you can do this:

Hyperlink link = new Hyperlink();
link.setText(fileDownloadTask.getLocalFile().getName());
link.disableProperty().bind(fileDownloadTask.stateProperty().isNotEqualTo(Worker.State.SUCCEEDED));
link.setOnAction(new EventHandler()
{
    public void handle(ActionEvent event)
    {
        try
        {
            Desktop.getDesktop().open(fileDownloadTask.getLocalFile());
        }
        catch (IOException e)
        {
            // todo handle this by showing an error message
            e.printStackTrace();
        }
    }
});

I won’t bore you with the details of it all, but you can see a simple little demo of this all in action using this code found at: http://code.google.com/p/jfxee/source/browse/trunk/jfxee8/pom.xml

When you get it all running it should look like this:

 

Continue Reading→
    • Nov
    • 03
    • 2011

Client Server with JavaFX 2 and Hessian (+Guice +FXML)

Posted by In Uncategorized

This entry is part 6 of 15 in the series Building JEE applications in JavaFX 2.0

Ok, due to popular demand, I’m going to fast track a bit of this walk through. I had planned to do more on the client end first, but it seems everyone wants to know how to build a client-server app (apparently that Internet thing has really taken off).

So in this post we’re going to build a very simple hello world client-server application, using HTTP. We’re going to use Hessian to make all our client-server communication nice and easy. There are a whole load of other communication options out there but Hessian is simple, lightweight and just works.

By the looks of it people are favouring Guice over Spring at this stage, due to the concept of it being ‘lightweight’. As such, I’m going to stick with Guice as our DI toolkit for the front-end. In later posts we’ll have a look at changing over to Spring, which really starts to show its advantages when we start working with database transactions and security.

This topic is a little more in-depth than some of the previous stuff. If you’ve never written a servlet or basic web application before, you may want to brush up on this first. Also, we’re going to use some JavaFX threading which is only lightly documented at this stage, and the API is just a little raw still too in my opinion. It may be a bumpy ride for some.

The full source code (as a multi-module maven project) can be found at: http://code.google.com/p/jfxee/source/browse/trunk/jfxee7/

Step 1: Design your application

We’re going to keep things as simple as we can. We will have a simple client that allows the user to enter their first and last name. The client will then pass these details to the server and the server will return a simple welcome message based on the name entered.

If we get everything right, our client will end up looking like the following:

Step 2: Create a Service interface

The great thing about Hessian is that it allows us to define our client-server protocol in pure Java objects. It works in a very similar way to RMI, where you define an interface for your server, which your server implements and client accesses. Hessian then provides the magical wiring underneath our interface to serialize our data and send it (over HTTP) to the server, where it gets deserialized and passed into our server implementation. Pretty sweet.

For our example, our service interface is very simple and looks like this:

public interface HelloService
{
    String sayHello(Person person);
}

This is our ‘contract’ between the client and the server. The client will call the sayHello method and the server will implement it.

We could pass two strings into the sayHello method for the first name and last name, but to make things a little bit interesting and show the power of Hessian, I have chosen to encapsulate all this in a Person bean. Hessian will magically handle all the serialization for this.

Our person bean is a standard serializable Java bean and looks like this:

import java.io.Serializable;

public class Person implements Serializable
{
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public String getLastName()
    {
        return lastName;
    }
}

Step 3: Create a Service implementation

Now that we’ve defined the contract between our client and server, we need to have our server fulfill that contract. We’re keeping things simple in this example: our server will simply build a message out of the Person details and send this back to the client. In a real world application, your server will likely hit a database, provide some security and do all the other things that a serious application does, but we won’t worry about that here.

Our service is just another Java object that implements the HelloService interface we defined above. The only special thing about it is that it extends HessianServlet, which is a custom servlet provided by the Hessian platform. All the magic happens in here and by simply extending it we have a ready-to-roll server implementation. Too easy.

Our service implementation looks like this:

package com.zenjava.jfxee7;

import com.caucho.hessian.server.HessianServlet;

public class HelloServiceImpl extends HessianServlet implements HelloService
{
    public String sayHello(Person person)
    {
        // in the real world, use a logging API like slf4j or log4j
        System.out.println(String.format("The server received a request from %s %s",
                person.getFirstName(), person.getLastName()));

        return String.format("The server says hello %s %s!",
                person.getFirstName(), person.getLastName());
    }
}

Step 4: Run your server as a web application

The next step is to publish our service as a web service. I’m going to assume you are at least a little familiar with creating normal servlets and building webapps. If not, you probably want to google these topics – there’s a wealth of information out there on this, just ask Google.

To publish our service we create a web.xml that loads our HelloServiceImpl as a servlet. The HelloServiceImpl is no different to any other servlet and can be exposed in exactly the same way:

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_9" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee

http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <servlet>
        <servlet-name>HelloService</servlet-name>
        <servlet-class>com.zenjava.jfxee7.HelloServiceImpl</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloService</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

From here you simply have to bundle your application into a war file and then deploy it to a server. I use Maven for all my builds and this makes this step extremely easy. Check out the example POM for this. If you’re using ANT (maybe it’s time to upgrade :) ) then you might find something like this helpful: http://javabeanz.wordpress.com/2009/02/12/how-to-create-a-war-file-using-ant/

The resulting war file can be deployed to any servlet friendly server. I use good old Tomcat but you can use Jetty, Resin or any of the other free ones out there. If you’re insane, you can pay for one of the commercial JEE servers (but really, don’t bother).

Step 5: Create a view and controller

Our server is now deployed and running, and we’re ready to build our client. The first part is easy, we just build a GUI to service our needs. I’m going to use the same Guice + FXML approach as in my last post but you could use the Spring approach, or even roll it all by hand and use no Dependency Injection at all if you’re into an old-fashion style.

Here’s our view:

<?xml version="1.0" encoding="UTF-8"?>

<?language javascript?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<VBox fx:id="view"
      fx:controller="com.zenjava.jfxee7.HelloController"
      spacing="6"
      xmlns:fx="http://javafx.com/fxml">

    <styleClass><String fx:value="enterDetails"/></styleClass>

    <children>

        <Label fx:id="messageLabel" text="Waiting for your input">
            <styleClass><String fx:value="message"/></styleClass>
        </Label>

        <Label text="First Name"/>
        <TextField fx:id="firstNameField"/>

        <Label text="Last Name"/>
        <TextField fx:id="lastNameField"/>

        <Button text="Connect to Server" onAction="#submit"/>

    </children>
</VBox>

And here’s our controller:


import com.google.inject.Inject;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class HelloController
{
    @FXML private Node view;
    @FXML private Label messageLabel;
    @FXML private TextField firstNameField;
    @FXML private TextField lastNameField;

    public Node getView()
    {
        return view;
    }

    public void submit(ActionEvent event)
    {
        // todo implement this to talk to the server
    }
}

Step 7: Use Guice to load the UI and inject the service

In order for our client to connect to the server, all it needs to do is use the HelloService interface we created earlier and use Hessian to load this. The following code will do the trick:

HessianProxyFactory factory = new HessianProxyFactory();
String serverUrl = "http://localhost:8080/hello";
HelloService helloService = (HelloService) factory.create(HelloService.class, serverUrl);
// use the helloService object now and hessian will magically make the calls on the server for you

This is basic Hessian stuff – we use the HessianProxyFactory to create a new instance of our HelloService for us, passing in the URL of our server. The factory then creates a ‘proxy’ (in this case, you could call it a ‘stub’), that implements the interface by making HTTP calls onto the servlet on the server side. The Proxy and the servlet work together to serialize the data between each other and make the actual call on the server. From our end, it’s all just nice simple Java.

We could create this proxy anywhere in our code and use it via plain Java calls and for this simple little scenario that would do the job. In our last post however we looked at ways to use Guice to load our controllers and provide Dependency Injection and this is a great candidate for this. As our project gets bigger and we end up with more controllers wanting to use more services, this DI is really going to pay off.

In order to inject our service using Guice, we first add the following line to our HelloController:

@Inject private HelloService helloService;

And now we can just wire up everything in our Guice module. I’m going to use instance injection in this case, but you could use the provider style approach just as easily. The instance injection approach looks like so:

import com.caucho.hessian.client.HessianProxyFactory;
import com.google.inject.AbstractModule;
import javafx.fxml.FXMLLoader;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;

public class HelloClientModule extends AbstractModule
{
    protected void configure()
    {
        try
        {
            HessianProxyFactory factory = new HessianProxyFactory();
            String serverUrl = "http://localhost:8080/hello";
            HelloService helloService = (HelloService) factory.create(HelloService.class, serverUrl);
            bind(HelloService.class).toInstance(helloService);

            bind(HelloController.class).toInstance((HelloController) loadController("/Hello.fxml"));
        }
        catch (MalformedURLException e)
        {
            // NOTE: this is not best-practice for exception handling. Check the
            // Guice documentation for better ways.
            throw new RuntimeException(String.format("Error connecting to server"), e);
        }
        catch (IOException e)
        {
            // NOTE: this is not best-practice for exception handling. Check the
            // Guice documentation for better ways.
            throw new RuntimeException(String.format("Error loading FXML file"), e);
        }
    }

    protected Object loadController(String url) throws IOException
    {
        InputStream fxmlStream = null;
        try
        {
            fxmlStream = getClass().getResourceAsStream(url);
            FXMLLoader loader = new FXMLLoader();
            loader.load(fxmlStream);
            return loader.getController();
        }
        finally
        {
            if (fxmlStream != null)
            {
                try
                {
                    fxmlStream.close();
                }
                catch (IOException e)
                {
                    System.out.println("Warning: failed to close FXML file");
                }
            }
        }
    }
}

And then to launch our application, we simply have:


import com.google.inject.Guice;
import com.google.inject.Injector;
import javafx.application.Application;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class HelloClient extends Application
{
    public static void main(String[] args)
    {
        launch(args);
    }

    public void start(Stage stage) throws Exception
    {
        Injector injector = Guice.createInjector(new HelloClientModule());
        HelloController helloController = injector.getInstance(HelloController.class);
        Scene scene = new Scene((Parent) helloController.getView(), 320, 240);
        scene.getStylesheets().add("styles.css");
        stage.setScene(scene);
        stage.setTitle("JFX2.0 Sprung");
        stage.show();
    }
}

Step 8: Call the server in a background thread

So we have a server and a client, and our controller has access to the server via the HelloService. Now we can just make the following call in our controller right?

public void submit(ActionEvent event)
{
    Person person = new Person(firstNameField.getText(), lastNameField.getText());
    String messageFromServer = helloService.sayHello(person);
    messageLabel.setText(messageFromServer);
}

There’s two problems with this though: threads and exceptions.

Now that the call to sayHello() is actually a remote call to a server it could be slow. Depending on the network speed it could take seconds for the client and server to do all the socket and serialization work. Java FX (like Swing) uses a single thread for application processing. If we lock this thread up waiting for the server to respond then our UI will become unresponsive as the application thread won’t be able to process mouse moves or even redraw the screen (this is a slight simplification of how threads and rendering work in JFX but from our point of view this is enough for us to know).

As well as the threading issue, we’ve also introduced a lot more room for things to go wrong: the server may be down, the client may have lost internet connection, the wrong URL may have been entered, etc. These will all be thrown as runtime exceptions so we could just ignore them and have the system crap out but this is not very nice for our users. Ideally we need to start handling these errors and show the user a friendlier message, such as “Hey mate, did you forget to plug in your network cable again?”, so they can actually do something about it and try again.

Fortunately JFX has an answer to both of these problems, and that answer is the Worker/Task/Service framework. Unfortunately this is not a simple toolkit to use (although if you are familiar with SwingWorker you will have a good head start) and even more unfortunately there is extremely little documentation on this as yet. The only real guide that I’ve found is this post from Richard that uses an early version of the framework while still in beta. The API has been tidied up a little since and Richard also neglected to give us too much detail on how to actually handle the response from the server, or handle errors.

We can muddle through it however, and by piecing all the bits together here’s a threading approach that works:

public void submit(ActionEvent event)
{
    // extract person details from the screen
    final Person person = new Person(
            firstNameField.getText(),
            lastNameField.getText()
    );

    // pass the details to the server in a worker thread
    final Task task = new Task()
    {
        protected String call() throws Exception
        {
            return helloService.sayHello(person);
        }
    };

    // handle the result
    task.stateProperty().addListener(new ChangeListener()
    {
        public void changed(ObservableValue source,
                            Worker.State oldState, Worker.State newState)
        {
            if (newState.equals(Worker.State.SUCCEEDED))
            {
                messageLabel.setText(task.getValue());
            }
            else if (newState.equals(Worker.State.FAILED))
            {
                 // always log your system errors with stack trace (please!!!)
                messageLabel.setText("Oh no, a system error, we're all going to die!");
                Throwable exception = task.getException();
                exception.printStackTrace();
            }
        }
    });

    // start the task in a thread
    messageLabel.setText("Contacting server...");
    new Thread(task).start();
}

As you can see this approach uses a ‘Task’, which is the simplest unit of the Worker framework. The Service base class is much more powerful (you can cancel active threads for example) but is more complex to use. For an example of using a Service, check out this forum topic: https://forums.oracle.com/forums/thread.jspa?messageID=9928424&#9928424

We also have pretty simple exception handling here. Ideally we would check the type of the Exception thrown and provide an error message to match. To do this we just use a big if-else statement and instanceof like so:

else if (newState.equals(Worker.State.FAILED))
{
    Throwable exception = task.getException();
    if (exception instanceof HessianConnectionException)
    {
         messageLabel.setText("Couldn't connect to the server, sorry about that.");
    }
    else
    {
         // always log your system errors with stack trace (please!!!)
         messageLabel.setText("Oh no, a system error, we're all going to die!");
         exception.printStackTrace();
    }
}

A note on building, deploying and running

Above are all the bits and pieces we need for our client and server communication and if you’re familiar with web applications and this style of development that’s probably all you need to know. Simply deploy your generated WAR file to your web server, edit the URL in the client to match and then run HelloApplication. Sorted.

For anyone who is not familiar with this stuff however, there are a few gotchas to be aware of when it comes to deploying and running. Firstly is how to package all of this up. You have two separate applications now, a client and a server, but they both share the common service API. You could bundle all the classes together and deploy it this way if you’re being lazy, but you should really separate them to avoid bloat, especially the client which typically is downloaded.

In my setup, I have one module (bundles into a jar) for the ‘common’ code, which includes the HelloService interface and the Person bean. Then my ‘client’ module has all my client code (bundled into a jar) and my ‘server’ module has all my server code (bundled into a war). The client and server then reference back to the ‘common’ module as if it were a third party library. It’s a little more complicated but it is the cleanest separation – you are free to make your own setup work for you.

When you deploy your web application the server will have a base address (such as http://zenjava.com) where the server (e.g. Tomcat) is running. When you run locally this address will typically be http://localhost:8080. Depending on how you deploy your WAR file it may then be allocated a sub-domain. In Tomcat for example, if you name your WAR file ‘helloserver.war’ and then put this into Tomcat’s ‘webapps’ directory, the URL you will need to use in your HelloClientModule is “http://localhost:8080/helloserver/hello”.

Ultimately you will likely want to deploy your client via webstart and then you will want it all bundled into your server (but not on the server’s classpath just for some added complexity). I’m not going to confuse people further with this here, if you can’t work out the packaging side of it yourself just run the client from within the IDE for now. I am planning to post something on doing this sort of complex deployment using Maven (our best friend in this situation) in a future post.

The above is hopefully enough to get you started on the road to developing client-server Java FX 2 applications over the web.

Enjoy!

The full source code for this post (as a multi-module maven project) can be found at:http://code.google.com/p/jfxee/source/browse/trunk/jfxee7/

Continue Reading→